SoFunction
Updated on 2025-04-08

Several ways to get hidden properties of a class in Java

In Java, the commonly referred to as "hidden attribute" refers to the private field of the class. Due to the encapsulation principle, these fields should not be directly accessed outside the class. However, there are several ways to access or modify these private fields indirectly in some cases:

1. Use public getter and setter methods

This is the most common practice. If the designer of the class already provides getter and setter methods for private fields, you should use them to access or modify the values ​​of those fields.

public class MyClass {  
    private String hiddenField;  
  
    public String getHiddenField() {  
        return hiddenField;  
    }  
  
    public void setHiddenField(String hiddenField) {  
         = hiddenField;  
    }  
}  
  
// useMyClass obj = new MyClass();  
("Hello");  
(()); // Output: Hello

2. Use Reflection

Java's reflection API allows you to check and modify code at runtime. However, using reflection to access private fields is usually not recommended because it breaks the encapsulation and can make the code difficult to understand and maintain.

import ;  
  
public class Main {  
    public static void main(String[] args) throws Exception {  
        MyClass obj = new MyClass();  
  
        // Get the Class object of MyClass class        Class<?> clazz = ();  
  
        // Use getDeclaredField method to get the field named "hiddenField" (private)        Field hiddenField = ("hiddenField");  
  
        // Set to accessible so that we can access private fields        (true);  
  
        // Use the set method to set the value of the field        (obj, "Hello from Reflection");  
  
        // Use the get method to get the value of the field        String value = (String) (obj);  
        (value); // Output: Hello from Reflection    }  
}  
  
class MyClass {  
    private String hiddenField;  
}

3. Use inheritance

If you have a subclass of a class and the class does not declare private fields as final, you can access these fields in the subclass indirectly by overwriting the public method of the parent class (if any) or using the protected fields of the parent class (if any). However, it is still impossible to directly access the private fields of the parent class.

In Java, when we say "get hidden properties of a class with inheritance", we actually refer to the subclass that can access these properties if the parent class has protected (protected) or default access level (package level private, without modifiers). However, if the property of the parent class is private, the subclass cannot be accessed directly, unless it is provided through public methods such as getters and setters provided by the parent class.

Here is a code example that uses inheritance to access the protected properties of the parent class and the default access level properties:

// Parent classclass ParentClass {  
    // Protected fields, subclasses can access    protected String protectedField = "This is a protected field.";  
      
    // The default access level field (package level private), subclasses under the same package can be accessed    String defaultField = "This is a default (package-private) field.";  
      
    // Private fields, subclasses cannot be accessed directly    private String privateField = "This is a private field.";  
      
    // Public getter and setter methods are used to access and modify private fields    public String getPrivateField() {  
        return privateField;  
    }  
      
    public void setPrivateField(String privateField) {  
         = privateField;  
    }  
}  
  
// Subclass, in the same package as parent classclass ChildClass extends ParentClass {  
    // Subclasses can directly access protected fields    public void printProtectedField() {  
        ("Protected Field: " + protectedField);  
    }  
      
    // Because the subclass is in the same package as the parent class, the subclass can also access fields at the default access level.    public void printDefaultField() {  
        ("Default Field: " + defaultField);  
    }  
      
    // Subclasses cannot directly access private fields, but can be accessed and modified through inherited getter and setter methods.    public void printAndChangePrivateField() {  
        ("Private Field: " + getPrivateField());  
        setPrivateField("Private field has been changed.");  
        ("Changed Private Field: " + getPrivateField());  
    }  
}  
  
// Main class, used for testingpublic class Main {  
    public static void main(String[] args) {  
        ChildClass child = new ChildClass();  
        (); // Output: Protected Field: This is a protected field.        (); // Output: Default Field: This is a default (package-private) field.        (); // Output the value of the private field and change it    }  
}

In this example, ParentClass has three fields: a protected, a default access level, and a private one. ChildClass inherits ParentClass so it can directly access protected fields and fields at the default access level (because they are visible to subclasses). For private fields, subclasses cannot access directly, but they can be accessed and modified through inherited getter and setter methods (if provided by the parent class).

4. Using Java's serialization mechanism

This is a more complex approach that involves using Java's serialization and deserialization capabilities. But this approach also has many limitations and potential problems, so it is usually not recommended. .

In Java, using a serialization mechanism (interface) is not a method that is directly used to obtain hidden properties of a class. The serialization mechanism is mainly used to convert the state of an object into a byte stream so that it can be written to a stream (such as a file or a network connection) where the object can be restored from these streams.

However, there is an indirect way to access the private fields of an object by serializing and deserializing, but this is usually not recommended because it breaks the encapsulation and can lead to unforeseen problems.

Here is a deprecated example showing how to "bypass" the encapsulation of private fields by serialization/deserialization:

import .*;  
  
// Class that implements Serializable interfaceclass MyClass implements Serializable {  
    private String privateField = "This is a private field.";  
  
    // To simplify the example, there are no getter and setter methods  
    // This is a method that will be called when serialized (if any)    private void writeObject(ObjectOutputStream out) throws IOException {  
        // Usually all the states of the object, including private fields, will be written here.        // But for example, we assume that nothing is done here    }  
  
    // This is a method that will be called when deserialized (if any)    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {  
        // Usually, the state in the stream will be read here to restore the object        // But for example, we assume that nothing is done here    }  
}  
  
public class SerializationExample {  
  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        // Create an object        MyClass originalObject = new MyClass();  
  
        // Serialize objects to byte array        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);  
        (originalObject);  
  
        // Deserialize byte array to object        byte[] serializedData = ();  
        ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(serializedData));  
        MyClass deserializedObject = (MyClass) ();  
  
        // Note: The value of the private field cannot be directly obtained here, because Java does not provide such a mechanism        // But if we know the internal implementation, and by reflection or otherwise, we can "bypass" the encapsulation  
        // Suppose we use reflection (not recommended because it breaks the encapsulation)        try {  
             field = ("privateField");  
            (true); // Set to accessible to bypass the encapsulation of private fields            String privateFieldValue = (String) (deserializedObject);  
            ("Private field value: " + privateFieldValue);  
        } catch (NoSuchFieldException | IllegalAccessException e) {  
            ();  
        }  
    }  
}

Important Tips

1. Using reflection to access private fields is not recommended because it breaks the encapsulation and can make the code difficult to maintain and understand.

2. In actual applications, getter and setter methods should always be used to access and modify the state of the object.

3. The serialization mechanism is mainly used for object persistence and network transmission, rather than accessing private fields.

In short, the best practice is to respect the encapsulation of the class and use public getter and setter methods to access and modify private fields.

This is the end of this article about several methods for obtaining hidden attributes of a class in Java. For more related content on obtaining hidden attributes of a class in Java, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!