Java 匿名类重新定义

问题描述 投票:0回答:1

这是匿名类的简单java程序,其中类被重新定义(而不是接口)为匿名类。

class Anonymous {
    int i = 10;
    void main() {
        System.out.println("Anonymous Main " + i);
    }

    void setI(int i) {
        System.out.println("under set");
        this.i = i;
    }

    void main2() {
        setI(30);
        System.out.println("Main 2's " + i);
    }

}

public class AnonymousClass {

    public static void main(String[] args) {
        Anonymous a = new Anonymous() {
            int i = 20;

            @Override
            void setI(int i) {
                System.out.println("Over set");
                this.i = i;
            }

            @Override
            public void main() {
                setI(0);
                System.out.println("Redefined Anonymous Main " + i);
            }
        };
        a.main();
        a.main2();
    }

}

输出:-

Over set
Redefined Anonymous Main 0
Over set
Main 2's 10

我有几个问题:

  1. main2
    中,为什么它可以访问具有
    i
    值的
    10

  2. 为什么对象

    a
    有两个
    i
    的副本?

  3. 如果有,那么调用

    setI
    时为什么没有两份
    setI

  4. 为什么

    main2
    可以访问重新定义的
    setI
    而不是
    i

  5. Java 到底在做什么?

java anonymous-class
1个回答
0
投票

我认为你应该开始从阅读JLS的这一部分开始。那么我希望一切对你来说都更加透明。您应该了解的是,父级中的

i
和子级中的
i
根本不一样

所以,关于你的问题:

  1. main2() 不会被重写,因此 JIT 当然会使用其可见性上下文来使用该方法的父版本。父母不知道孩子的变量

    i

    。只有子级知道它隐藏了父级字段。因此,您的父母打印它是 
    i
    (与孩子的 
    i
     不同),但 
    setI
     被覆盖,因此 
    setI
     设置孩子的 
    i
     的值。

  2. 因为这就是 Java 的工作原理:) 已经提供了链接

  3. 因为子级中的方法会覆盖父级中的方法。

    本例中并不是隐藏,它是真正的多态性

  4. 因为您正在对已覆盖

    main2()

     的对象调用 
    setI
    。因此它会调用 
    setI
     的重写版本。再次强调 - 当 
    i
     内部修改 
    main2
     时,它与子级中的 
    i
     不同,并且父级中的 
    main2()
     无法访问子级中的 
    i

  5. 只需遵守 JLS :) 这是预期的行为,我希望现在您明白为什么。

© www.soinside.com 2019 - 2024. All rights reserved.