16

我有以下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)为什么内部类中的 this$0 是 final ?如果它不是最终的会发生什么?

谢谢并恭祝安康。

4

2 回答 2

14

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

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

编辑:至于access$000方法,关键线索是它们是包访问并且它们以 aOuter作为参数。因此,当调用中的代码时Inner,比如说,Inner.this.a它实际上是在调用Inner.access$000(this$0). 所以这些方法可以让private外部类的成员访问内部类。

于 2010-02-04T11:24:25.233 回答
2

1) They have to be static, in order to not be overridden in some sub class. I hope you understand.

<Addendum>

Shrini, from your comment, it seems that there is a need to explain the things to avoid some misconceptions. First of all, know on thing that static methods can not be overridden. Overriding is exclusive in objects, and it is there to facilitate polymorphism. Whereas static methods belongs to the class. Found a couple of good resources to support my argument and for you to understand that static methods can not be overridden.

Now for your second retort, you are right in saying that they have package level access and can't be overridden in subclasses outside the package. But I don't know why are you neglecting the case where subclass/es exist in the same package. Its a valid case, IMO. In fact, it would be absurd to name a method like access$000() or something like that, in a real work. But don't underestimate the chance of accidental overriding. There can be a case where the subclass of Outer, say SubOuter, has an inner class of itself too. I didn't try to javap that case myself, just guessing.

</Addendum>

2) Even if you think it will not get modified, technically there is a possibility as cletus pointed out already, use of final can provide easy optimizations by the compiler.

于 2010-02-04T11:26:26.427 回答