【问题标题】:Why Object class methods are available in interface?为什么Object类方法在接口中可用?
【发布时间】:2009-09-26 14:28:51
【问题描述】:

以下接口和类已成功编译。 下面的输出中提到了问题:

interface MyInterface{}

class MyClass implements MyInterface{}

class InterDoubt{

    static MyInterface mi ;//= new MyClass() ;

    public static void main(String[] args){
        System.out.println("X") ;

        try{
            synchronized(mi){
                try{
                    mi.wait(4000) ;
                }
                catch(InterruptedException ie){
                    System.out.println("Exception occured at main.") ;
                }
            }
        }
        catch(Exception e){
            System.out.println("voilla, MyInterface is an interface,\n" + 
                       "then why compiler allows compilation of\n" +
                       "mi.getClass(), mi.wait().\n" +
                       "Or how the methods of Object class are available in an interface."
            );
        }

        System.out.println("Y") ;
    }
}

输出:

X

瞧,MyInterface 是一个接口,

那么为什么编译器允许编译

mi.getClass(), mi.wait().

或者 Object 类的方法如何在接口中可用。

是的


已编辑:- 我接受了 disown 的回答,因为这是最能说明问题的。但是在阅读了答案之后,又出现了一个问题:-

"请记住,如果接口试图在 Object 类中声明一个声明为 'final' 的公共实例方法,则会导致编译时错误。例如,'public final Class getClass()' 是在 Object 类中声明为“final”的公共实例方法,因此如果接口尝试使用此签名声明方法,则编译将失败”(引自解释)。

那么为什么下面的代码会被成功编译:-

interface MyInter{
    public void method() ;
}

class MyClass implements MyInter{

    public final void method() {
        .......
        .......
              .......
    }

}

【问题讨论】:

  • 以上你确定吗?当我尝试这个(在 Eclipse 中)时,我得到一个错误,说变量 mi 可能没有被初始化。
  • 另外,引发异常的不是 wait() 调用。这是同步的(mi)。
  • 至于您的附加语句 - 当然它可以编译,因为方法 method 只是接口中声明的内容的实现。 JLS 声明所说的是在 Object 类本身上声明的方法。

标签: java


【解决方案1】:

Java 语言规范中指定了您正确指出的异常。接口将自动从添加的类 java.lang.Object 中获取所有成员。来自here

Java 语言规范明确指出接口的成员是在接口中声明的成员和从直接超接口继承的成员。如果接口没有直接的超接口,则该接口隐式声明一个公共抽象成员方法,对应于 Object 类中声明的每个公共实例方法,除非具有相同签名、相同返回类型和兼容 throws 子句的方法显式声明为那个界面。这就是使编译器可以使用 Object 方法的签名并且代码编译没有任何错误的原因。请记住,如果接口试图在 Object 类中声明一个声明为“final”的公共实例方法,那么它将导致编译时错误。例如,“public final Class getClass()”是 Object 类中声明为“final”的公共实例方法,因此如果接口尝试使用此签名声明方法,则编译将失败。

【讨论】:

    【解决方案2】:

    在运行时,引用 mi 后面应该有一个真实对象(或 null)。真正的类型将实现这个接口,因此编译器允许它。在运行时,任何实现该接口的类型都可能存在。

    【讨论】:

    • 给定一个接口类型,一个实现该接口的具体类型,以及对该具体类型实例的接口引用,编译器不允许您调用具体实例上的方法是不正确的在接口中指定。此外,Object 方法根本不是任何(显式)接口的一部分。
    【解决方案3】:

    是的,Object 的所有方法都可用于除 Primitive 值之外的所有内容。接口对象仍然是对象,因此它们具有对象的方法。

    【讨论】:

    • 接口实例是不是对象,它们只是委托对象的公共方法。
    • 接口实例必须是对象。除了原始值之外的所有东西 DATA 都是对象。当你创建一个实例时,你需要从一个类中创建(尽管你用一个接口变量来保存它)。要创建一个实现对象的类,该类必须继承某些东西(如果您不指定它,该类将继承 Object)。这意味着每个实例(包括那些由接口变量持有的实例)都是始终对象。
    • TYPO:“创建实现对象的类”=>“创建实现接口的类”。 :-p
    • 阅读我在第一篇文章中提到的文章。接口是对象是不正确的。它与语言的纠缠比如此(考虑 invokevirtual 等)。
    【解决方案4】:

    cast (Object)mi 总是会成功,那么为什么需要你提供它呢?

    【讨论】:

      【解决方案5】:

      Java 语言规范明确指出接口的成员是在接口中声明的成员和从直接超接口继承的成员。如果接口没有直接的超接口,则该接口隐式声明一个公共抽象成员方法,对应于 Object 类中声明的每个公共实例方法,除非具有相同签名、相同返回类型和兼容 throws 子句的方法显式声明为那个界面。

      【讨论】:

      • 除了当前接受的答案(正确地归因于引用)之外,这有何贡献?
      猜你喜欢
      • 2020-07-03
      • 2013-01-20
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      • 2019-07-16
      相关资源
      最近更新 更多