-2

如果一个类实现了一个接口并有一个toString()方法,并且我们将子引用存储到父变量中,或者只是完成了动态绑定,那么为什么编译器不检查toString()接口中的方法,因为动态绑定的规则是检查函数的唯一性在父母

例如。

interface my {
    void show();
}

class child implements my {
    public void show() {
        System.out.println("working");
    }

    public String toString() {
        return "hello";
    }

    public static void main(String... s) {
        my m = new child();

        m.show();

        String s = m.toString();
        System.out.println(s);
    }
}

我们知道,只要动态绑定完成,子个人方法就无法执行,除非它覆盖了上述方法,那么为什么toString()要编译上述函数并给出输出呢?

4

4 回答 4

3

听起来你在问这个问题:

在我的示例代码中,局部变量m的类型为my. 接口my只声明了一个方法,show()为什么我可以调用m.toString()呢?

这在 Sun(现在的 Oracle)Java 继承教程中进行了解释:

类可以从从类派生的类派生的类派生,依此类推,并最终从最顶层的类 Object 派生。据说这样的类是继承链中所有类的后裔,这些类一直延伸到 Object。

该类Object声明了一个默认toString()方法(以及其他几个基本方法),因此您可以调用JavatoString()中的任何对象


更新

由于 Java 中的所有类实例都必须继承自 Object,因此使用接口作为类型的实际语义更像是这样的:

public static void main(String... s) {
    // This won't actually compile
    (? extends Object implements my) m = new child(); 

    m.show();

    String s = m.toString();
    System.out.println(s);
}

换句话说,当您声明 that mhas type时,my您实际上是在说那m是一些Object实现 interface 的类型my。由于Object声明了一个方法,即使接口中不存在toString(),您也可以调用。m.toString()toString()my

Java 是故意设计Object在类层次结构的顶部的,因此您无法让编译器抱怨调用toString()任何对象的任何实例。hashCode(),equals()等也是如此。

于 2012-09-26T16:32:41.037 回答
1

我认为您的问题将通过已经给出的两个答案得到解决。我只想指出关于您的陈述的一些事情:-

  • if a class implements an interface and have a toString() method

您定义的任何类都有一个toString()方法。虽然它可能看起来不明显,但是当您打印您的类的实例时,它是调用toString()的类的方法..(类是您定义的所有其他类的超类) .. 因此,类中定义的任何方法都可以从任何其他.ObjectObjectObjectclass object

您可以根据需要覆盖此方法以打印您的实例。但是,如果没有被覆盖,您将获得hashcode您的对象..(类似于:- classname@12343.. 现在由于此toString()方法可用于所有类,编译器不要不需要在任何地方检查它interface。它知道toString()方法是Object类的一部分,它是super class所有类的一部分。

  • we store the child reference into parent variable

虽然你的理解是对的,但是让我重新定义这句话,让它更有意义:- We Store the reference to child class object in the parent class reference variable

  • function uniqueness will be check in parent

我真的不明白,你这句话是什么意思.. 但据我了解,你是说 - “当在 a 上调​​用一个方法时child classparent class reference编译器将首先检查该方法是否定义在parent class与否,那么只有您可以调用该方法..

*编辑*:-

根据Java 语言规范,第 9.2 节:-

如果接口没有直接的超接口,则接口隐式声明一个公共抽象成员方法 m,其签名为 s,返回类型为 r,并且 throws 子句 t 对应于每个签名为 s、返回类型为 r 和 throws 子句的公共实例方法 m在 Object 中声明,除非接口显式声明了具有相同签名、相同返回类型和兼容 throws 子句的方法。

如果在 Object 中将 m 声明为 final 的情况下,接口显式声明了这样的方法 m,则会出现编译时错误。

如果接口声明的方法具有与 Object 的公共方法重写等效(第 8.4.2 节)的签名,但具有不同的返回类型或不兼容的 throws 子句,则会出现编译时错误。

于 2012-09-26T16:31:41.433 回答
0

所有对象都扩展Objectpublic String toString()定义在Object所有对象都有一个toString()方法。

于 2012-09-26T16:22:52.983 回答
0

如果你问我认为你在问什么,那是因为 Java 中的每个非原始(原始是int,long等;但不是String)都有 type ObjectObject有方法toString()hashCode()equals(),这意味着任何非原始也有这些方法。

但是,这些方法通常过于通用,无法用于特定的类,这就是我们在需要时重载它们的原因。

于 2012-09-26T16:23:05.200 回答