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

发布于 2024-08-20 09:32:34 字数 859 浏览 6 评论 0原文

我有以下 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 被定为最终的?如果不是最终结果会怎样?

谢谢和问候。

I have the following java class:

class Outer
{
    private Integer a;
    private Long b;

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

when I run javap on Outer and Outer$Inner, I get the following:

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();
}

I have two questions:

1) why does java compiler generate static methods that take 'Outer' param, in the outer class, for accessing its private variables ? why not instance methods that the inner class can easily call through its this$0 member ?

2) why is this$0 in inner class made final ? what will happen if it is not final ?

Thanks and regards.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

倾城°AllureLove 2024-08-27 09:32:34

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

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

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

Non-static inner classes have an implicit reference to an instance of the outer class. This is implemented as a final reference to the outer class. If it wasn't final technically it could be modified after instantiation.

The outer class is implicitly passed in which is why any constructors on the inner class have an implicit parameter of the outer class, which is how this$0 is passed in.

Edit: as for the access$000 methods the key clue is that they're package access and they take an Outer as an argument. So when code in Inner calls, say, Inner.this.a it's actually calling Inner.access$000(this$0). So those methods are there to give access to private members of the outer class to the inner class.

微凉徒眸意 2024-08-27 09:32:34

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

<附录>

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

现在你的第二个反驳,你说得对,它们具有包级别的访问权限,并且不能在包外部的子类中被覆盖。但我不知道你为什么忽略子类存在于同一个包中的情况。 IMO,这是一个有效的案例。事实上,在实际工作中,将方法命名为 access$000() 或类似的名称是荒谬的。但不要低估意外覆盖的可能性。可能存在这样的情况:Outer 的子类(例如 SubOuter)也有其自身的内部类。我自己并没有尝试javap这种情况,只是猜测。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文