简体   繁体   English

通过Java中内联创建的对象访问私有元素

[英]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. 我是java的新手,正在尝试一些访问方法,但遇到了一些我不理解的问题。 The code below working fine, prints 9 and not giving any compilation errors. 下面的代码可以正常工作,显示9,并且未给出任何编译错误。 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. 我认为这段代码应该给出一个编译错误,并且测试方法应该无法访问该数字,因为new Human()是完全不同的类的实例。 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();    
}

You are correct before java 8 . 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. 但是,局部类只能访问声明为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. 局部变量应该是final以便可以在匿名类中访问。

Starting with Java 8, effectively final variables also allowed to access inside. 从Java 8开始, 有效的最终变量也允许在内部访问。

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. 但是,从Java SE 8开始,本地类可以访问最终变量或有效最终变量的局部变量和封闭块的参数。 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" . 现在number根本不是有效的final ,您会收到一个编译器错误,提示“封闭范围中定义的局部变量number必须是final或有效的final”

You might want to read Difference between final and effectively final 您可能需要阅读最终与有效最终之间的区别

This is perfectly valid (for java8 - prior to that, you would need thje final keyword when declaring number ): 这是完全有效的(对于java8-在此之前,在声明number时,您将需要final关键字):

  • you create an anonymous inner class that extends Human and provides the required implementation of the test() method. 您将创建一个匿名内部类,该类扩展了 Human并提供了test()方法的必需实现。
  • 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. 在main方法中-在定义该匿名内部类之后。 Or use some version of java that is older than java8. 或使用比java8早的Java版本。

Keep in mind that anonymous inner classes are closures , and that the JVM is copying the values that are required "inside" from the outside. 请记住,匿名内部类是closures ,并且JVM从外部“内部” 复制了所需的值。 But when the outside value changes - which value should be copied. 但是,当外部值更改时-应该复制哪个值。 See here for further reading. 请参阅此处以进一步阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM