当前位置: 首页 > 知识库问答 >
问题:

为什么method()和super.method()在匿名子类中引用不同的东西?

谢鸿
2023-03-14

我正在解决一些练习,以便更好地理解java中的内部类是如何工作的。我发现了一个很有趣的练习。该练习的条件是使printname()打印“sout”而不是“main”,且更改最少。有它的代码:

public class Solution {
    private String name;

    Solution(String name) {
        this.name = name;
    }

    private String getName() {
        return name;
    }

    private void sout() {
        new Solution("sout") {
            void printName() {
                System.out.println(getName());
                // the line above is an equivalent to:
                // System.out.println(Solution.this.getName);
            }
        }.printName();
    }

    public static void main(String[] args) {
        new Solution("main").sout();
    }
}

我们有一个有趣的情况--这两个类有is-A和HAES-A联系。这意味着匿名内部类扩展了外部类,而且内部类的对象也引用了外部类的对象。如果您运行上面的代码,“main”将被打印出来。子级不能通过继承调用父级的getname()。但是作为内部类的子类使用对父类(外部类)的引用来访问方法。

解决此任务的最简单方法是将getname()的访问修饰符从private更改为其他任何内容。因此子级能够通过继承使用getname(),并且由于后期绑定,将打印“sout”。

private void sout() {
    new Solution("sout") {
        void printName() {
            System.out.println(super.getName());
        }
    }.printName();
}

谢谢你的尝试)

共有1个答案

常源
2023-03-14

Java语言规范(JLS)在编译器解析方法调用表达式的上下文中规定

如果表单为super。[TypeArguments]identifier,则要搜索的类是其声明包含方法调用的类的超类。

在本例中,其声明包含方法调用的类是匿名solution子类,其超类是solution。在确定将使用哪个实例调用方法的上下文中,JLS接着说

new Solution("sout") {
    void printName() {
        System.out.println(getName());
    }
}.printName();

然后,JLS声明

否则,让t是方法作为成员的封闭类型声明,让n是整数,这样t是该类的第n个词法封闭类型声明,该类的声明立即包含方法调用。目标引用是this的第n个词法封闭实例。

同样,Tsolution,这是自其声明立即包含方法调用的类是匿名solution子类以来的第一个词法封闭类型。是匿名解决方案子类实例。因此,目标引用是这个的第一个词法封闭实例。解决方案实例,其名称字段是用值“main”初始化的。这就是为什么原始代码打印“main”

 类似资料:
  • null null 产品版本:NetBeans IDE 7.3.1(构建201306052037)Java:1.7.0_25;Java HotSpot(TM)64位服务器VM 23.25-B01运行时:Java(TM)SE运行时环境1.7.0_25-B17系统:Windows 7 Version6.1在AMD64上运行;CP1252;en_US(nb) 清理、构建和重新启动Netbeans并没有解

  • 我通过在public static void main()方法中实现接口I创建了匿名类。因此,Java8对于抽象方法test()的实现是从C类的imple()方法中提供的。 因此,在public static void main()方法printing_interface.getclass(),我得到了 但最终它打印的是package_path.C(告诉我C是类名)。这怎么可能?不应该再次打印pa

  • 问题内容: 如果我有以下课程: 我显然可以实例化该对象,并且我知道必须进行某种子类化,因为我可以覆盖Hooray方法,但是如果有子类化,为什么我不能在匿名类内创建一个新方法? 返回语法错误 问题答案: 您可以创建方法,方法没有任何问题(除了它的前面有一个大写字母之外)。问题在于,在匿名类之外,Boo方法不可用(它没有作为类API的一部分公开)。 这与实现接口的任何类都是相同的…如果该类具有不属于接

  • 问题内容: 在Java 7和更高版本中,菱形通常可以像这样毫无问题地用于推断类型: 但是,它不能用于这样的匿名内部类: 为什么是这样?从逻辑上讲,在这种情况下,我绝对可以将类型推断为。做出该决定的逻辑上的理由是,实际上不能在匿名内部类上推断类型,还是出于其他原因而将其省略了? 问题答案: 在JSR-334中: 不支持将Diamond与匿名内部类一起使用,因为这样做通常需要扩展类文件签名属性以表示不

  • 问题内容: 在进行一些基本的lambda练习时,一个看似完全相同的匿名内部类的输出给我的输出与lambda不同。 场景1 输出 2 和 2 。这里没有新内容。 但是当我这样做时: 场景2 输出 2 和 3 问题:两个输出不应该相同吗? 我想念什么吗? 为了完整起见: 方案3 输出 3 和 3 。这里也没有什么新鲜的。 更新:仍从1.8.0-b132获得相同的输出 更新#2:错误报告: https

  • 问题内容: 就在今天,我需要一种在不同对象之间传递函数的方法。我很快了解到您不能直接在Java中做到这一点,但是您可以传递一个wht实例,该实例显然被称为“匿名内部类”,如下所示: 定义类: 使其成为一个实例: 并称之为: 很简单。但是我不明白的是为什么它被称为“匿名”。我不只是给它起名字MyCallback吗?命名的东西不能匿名,对吗?请避免对这个术语感到困惑。 问题答案: 不,您说的是MyCa