有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我是java新手,尝试了一些访问方法,但遇到了一些我不理解的问题。下面的代码工作正常,打印9,没有给出任何编译错误。 我认为这段代码应该给出一个编译错误,测试方法应该无法访问数字,因为new 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();           
    }    
} 

人类阶级

public abstract class Human {       
    abstract void test();    
}

共 (2) 个答案

  1. # 1 楼答案

    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.

    局部变量应该是final,以便在匿名类中访问

    从Java8开始,还允许访问内部变量

    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.

    试一试

    int number = 9;
    number=10;
    

    现在number根本不是有效的final,您会得到一个编译器错误,它说“在封闭范围中定义的局部变量号必须是final或有效的final”

    您可能需要阅读Difference between final and effectively final

  2. # 2 楼答案

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

    • 您创建了一个匿名内部类,该类扩展了人,并提供了test()方法所需的实现
    • 该方法使用的是来自其封闭“作用域”的变量——编译器足够聪明,可以检测到该变量实际上是一个常量——因为没有其他后续赋值给它

    为了使您的示例“无效”:只需添加一个赋值

    number = 42; 
    

    在主方法中-在定义匿名内部类之后。或者使用比java8旧的java版本

    请记住,匿名内部类是闭包,JVM是从外部复制内部所需的值。但是当外部值发生变化时,应该复制哪个值。进一步阅读见here