java – private + final = "Cannot be changed"

Question:

In some sources, in the literature, they write just such a statement. My question is, "Is this statement absolute?" Or is it done specifically for general understanding?

I read here on the forum that there is reflection and that you can still influence it. Are there other possibilities?

Answer:

It all depends on what these modifiers are used for:

  1. If the final modifier is used for a class field , then the field must be defined in the class constructor (and once for the entire constructor), or, directly, at the place of the declaration.

    The collection of private final modifiers for a field imposes a prohibition on changing (it is possible to define this field either in the constructor or in the place of declaration at the expense of final ) and the visibility of this field is limited by the methods of this class (due to private ).

  2. If the final modifier is used for a class method , then it prohibits overriding this method in derived classes.

    The use of a pair of private final modifiers for a class method is meaningless, since private restrict access to this method to the limits of the class, and final prohibit its redefinition in its heirs. those. descendants will not see this method, and therefore will not be able to override.

When using reflection, the value of a field with the private modifier can be changed, but this is not allowed for a final field (no exception / warning will be generated, but the field will not change).

Test case:

class WithPrivateFinalField { 
    private int i = 1; 
    private final String s = "String S"; 
    private String s2 = "String S2"; 

    public String toString() { 
        return "i = " + i + ", " + s + ", " + s2; 
    } 
} 

public class ModifyngPrivateFields {
    public static void main(String[] args) throws Exception {
        WithPrivateFinalField pf = new WithPrivateFinalField(); 

        Field f = pf.getClass().getDeclaredField("i"); 
        f.setAccessible(true); 
        f.setInt(pf, 47); 
        System.out.println(pf);  // i = 47, String S, String S2

        f = pf.getClass().getDeclaredField("s"); 
        f.setAccessible(true); 
        f.set(pf, "MODIFY S"); 
        System.out.println(pf);  // i = 47, String S, String S2


        f = pf.getClass().getDeclaredField("s2"); 
        f.setAccessible(true); 
        f.set(pf, "MODIFY S2"); 
        System.out.println(pf);  // i = 47, String S, MODIFY S2
    } 
}
Scroll to Top