Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a private element through an inline created object in java

I am new to java and trying some accessing methods and i encountered something that i do not understand. The code below working fine, prints 9 and not giving any compilation errors. I think this code should give a compilation error and number should be inaccessible from the test method, since new Human() is an instance of a totally different class. Can anybody explain me what is happening here ?

public class Test{      
    public static void main(String[] args) {
        int number = 9;

        test("holla",new Human(){   
            @Override
            void test() {
                // TODO Auto-generated method stub
                System.out.println(number); // I think this line should not compile
            }               
        });    
    }

    private static void test(String a ,Human h){            
        h.test();           
    }    
} 

Human Class

public abstract class Human {       
    abstract void test();    
}
like image 417
rematnarab Avatar asked Aug 22 '17 12:08

rematnarab


People also ask

How to access private fields of a class in Java?

In order to access the private fields of any class, you need to know the name of field than by calling getDeclaredFields (String name) method of java.lang.Class class. Once you get the field reference you need to make it accessible by calling Field.setAccessible (true) because you are going to access private field.

Is there a way to access private objects from another class?

Reflection is the only way. If you're trying to access a private object from another class you're doing it wrong... @SotiriosDelimanolis - Actually, you can do it with native methods as well. @HotLicks Are native methods not restricted by access modifiers?

How to access the private constructor of a class in Java?

To access the private constructor, we use the method getDeclaredConstructor (). The getDeclaredConstructor () is used to access a parameterless as well as a parametrized constructor of a class. The following example shows the same.

How to call private method from outside class in Java?

You can call the private method from outside the class by changing the runtime behaviour of the class. By the help of java.lang.Class class and java.lang.reflect.Method class, we can call private method from any other class.


2 Answers

You are correct before java 8.

In addition, a local class has access to local variables. However, a local class can only access local variables that are declared final. When a local class accesses a local variable or parameter of the enclosing block, it captures that variable or parameter.

Local variables should be final inorder to accessible inside anonymous classes.

Starting with Java 8, effectively final variables also allowed to access inside.

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.

try

int number = 9;
number=10;

now number is not at all effectively final and you get a compiler error saying "Local variable number defined in an enclosing scope must be final or effectively final".

You might want to read Difference between final and effectively final

like image 134
Suresh Atta Avatar answered Nov 05 '22 05:11

Suresh Atta


This is perfectly valid (for java8 - prior to that, you would need thje final keyword when declaring number):

  • you create an anonymous inner class that extends Human and provides the required implementation of the test() method.
  • that method is using a variable from its enclosing "scope" - and the compiler is smart enough to detect that this variable is in fact a constant - as there no other subsequent assignments to it.

In order to "invalidate" your example: simply add an assignment

number = 42; 

within the main method - after defining that anonymous inner class. Or use some version of java that is older than java8.

Keep in mind that anonymous inner classes are closures, and that the JVM is copying the values that are required "inside" from the outside. But when the outside value changes - which value should be copied. See here for further reading.

like image 36
GhostCat Avatar answered Nov 05 '22 04:11

GhostCat