java 内部/外部类关于外部类私有变量访问的问题

2022-09-03 07:03:17

我有以下java类:

class Outer
{
    private Integer a;
    private Long b;

    class Inner
    {
        public void foo()
        { 
            System.out.println("a and b are " + a + " " + b);
        }
    }
}

当我在Outer和Outer$Inner上运行javap时,我得到以下结果:

C:\test>javap Outer
Compiled from "Outer.java"
class Outer extends java.lang.Object{
    Outer();
    static java.lang.Integer access$000(Outer);
    static java.lang.Long access$100(Outer);
}

C:\test>javap Outer$Inner
Compiled from "Outer.java"
class Outer$Inner extends java.lang.Object{    
    final Outer this$0;
    Outer$Inner(Outer);
    public void foo();
}

我有两个问题:

1)为什么java编译器生成静态方法,这些方法在外部类中采用“Outer”参数来访问其私有变量?为什么不是内部类可以通过其 this$0 成员轻松调用的实例方法?

2)为什么这个内部班级的0美元是最终的?如果不是最终的,会发生什么?

谢谢和问候。


答案 1

非静态内部类具有对外部类实例的隐式引用。这是作为对外部类的引用实现的。如果它不是技术上,它可以在实例化后进行修改。finalfinal

外部类是隐式传递的,这就是为什么内部类上的任何构造函数都具有外部类的隐式参数的原因,这就是传入的方式。this$0

编辑:至于方法,关键线索是它们是包访问,并且它们将a作为参数。因此,当代码在调用中时,例如,它实际上是在调用。因此,这些方法是为了向内部类提供对外部类成员的访问权限。access$000OuterInnerInner.this.aInner.access$000(this$0)private


答案 2

1) 它们必须是 ,以免在某些子类中被覆盖。我希望你能理解。static

<Addendum>

Shrini,从您的评论中,似乎有必要解释这些事情以避免一些误解。首先,要知道方法不能被覆盖。覆盖在对象中是排他性的,它的存在是为了促进多态性。而静态方法属于该类。找到一些很好的资源来支持我的论点,并让你明白静态方法不能被覆盖。static

现在,对于您的第二次反驳,您正确地说它们具有包级别访问权限,并且不能在包外部的子类中被覆盖。但是我不知道为什么你忽略了子类/es存在于同一包中的情况。这是一个有效的案例,海事组织。事实上,在一部真正的作品中,命名一个这样的方法或类似的东西是荒谬的。但不要低估意外覆盖的可能性。在有些情况下,比如说,的子类也有一个内部类。我自己没有尝试过这种情况,只是猜测。access$000()OuterSubOuterjavap

</Addendum>

2)即使您认为它不会被修改,从技术上讲,正如cletus已经指出的那样,使用也可以通过编译器提供简单的优化。final