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

rem*_*rab 7 java oop inline abstract-methods java-8

我是java新手并尝试一些访问方法,我遇到了一些我不理解的东西.下面的代码工作正常,打印9并没有给出任何编译错误.我认为这段代码应该给出编译错误,并且测试方法中的数字应该是不可访问的,因为新的Human()是一个完全不同的类的实例.谁能解释一下这里发生了什么?

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();           
    }    
} 
Run Code Online (Sandbox Code Playgroud)

人类

public abstract class Human {       
    abstract void test();    
}
Run Code Online (Sandbox Code Playgroud)

Sur*_*tta 12

你在java 8之前是对的.

此外,本地类可以访问局部变量.但是,本地类只能访问声明为final的局部变量.当本地类访问封闭块的局部变量或参数时,它会捕获该变量或参数.

局部变量应该可以final在匿名类中访问.

从Java 8开始,有效的最终变量也允许访问内部.

但是,从Java SE 8开始,本地类可以访问最终或有效最终的封闭块的局部变量和参数.在初始化之后其值永远不会改变的变量或参数实际上是最终的.

尝试

int number = 9;
number=10;
Run Code Online (Sandbox Code Playgroud)

现在number根本不是最终的,你得到一个编译错误,说"在封闭范围内定义的局部变量号必须是最终的或有效的最终".

您可能希望阅读最终和有效最终之间的差异


Gho*_*ica 7

这是完全有效的(对于java8 - 在此之前,你需要final在声明时使用关键字number):

  • 您创建一个扩展 Human 的匿名内部类,并提供该方法所需的实现.test()
  • 该方法使用来自其封闭"范围"的变量 - 并且编译器足够智能以检测此变量实际上是常量 - 因为没有其他后续赋值.

为了使您的示例"无效":只需添加作业即可

number = 42; 
Run Code Online (Sandbox Code Playgroud)

在main方法中 - 定义匿名内部类之后.或者使用早于java8的某些版本的java.

请记住,匿名内部类是闭包,并且JVM正在从外部复制 "内部"所需的值.但是当外部值发生变化时 - 应该复制哪个值.请参阅此处以进一步阅读