【问题标题】:Compiler Prefers Object's Method to Implementation编译器更喜欢对象的方法而不是实现
【发布时间】:2015-03-04 11:18:51
【问题描述】:

我今天遇到了 Eclipse 编译器的一个奇怪行为,我不知道该怎么想。我们正在尝试创建一个有用的Cloneable 界面,如下所示:

public interface PublicCloneable extends Cloneable {

    Object clone();

    static <T extends PublicCloneable> T clone(final T obj) {
        if (obj != null) {
            return (T) obj.clone();
        }
        return null;
    }
}

有趣的是编译器抱怨obj.clone():Unhandled exception type CloneNotSupportedException

我知道如何解决它,我们可以将 obj 转换为 PublicCloneable 并完成它。但我感兴趣的是:为什么编译器会更喜欢Object 的方法而不是实现的方法?

【问题讨论】:

  • 编译器在编译时只检查被调用的方法是否存在于层次结构的最顶层类中。它不会解析对实际具体类的调用。
  • @TheLostMind 有什么区别?最顶级的仍然是PublicCloneable 而不是Object
  • 没有。编译器检查该方法是否在PublicCloneable 的超类之一中定义。在运行时,实际调用将解析为具体类的clone() 方法。简单地说,编译器并不关心 Your 具体类 是否真的是那个方法。它想知道的是你的类的类层次结构中的某个人应该拥有它。找到它的那一刻,它说 - 代码很好
  • @TheLostMind 所以编译器以与运行时执行完全相反的方向解析它?太疯狂了! o_O
  • 编译器只是检查它的存在.. 就是这样:P

标签: java eclipse


【解决方案1】:

来自这个答案:https://stackoverflow.com/a/13776045/896588

[...] 虽然接口本身不扩展 Object,但众所周知,任何实现都会。

所以既然你有一个接口,声明的clone() 不会覆盖Objectclone()。在这一点上,它是正式宣布的一项新行动。

尝试实现您的界面。您会看到它强制您从Object 覆盖clone(),但无一例外,因为它还必须实现接口。

你在这里创造了一个棘手而复杂的情况。编译器知道您的实现类也将扩展Object 并继承clone(),但有例外。当它在类型层次结构中查找声明时,它首先找到该声明并停止搜索。它不再关心 PublicCloneable (它将有一个 clone() 无一例外)也在类型层次结构中。如果你直接把参数类型改成PublicCloneable,它就会从那里开始搜索并找到另一个。

这可能解释得太简单了,但我似乎无法在 JLS 中找到相应的正式部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    相关资源
    最近更新 更多