Java 接口是否被视为对象?

Java 接口是否被视为对象?,java,Java,为什么下面的代码可以工作 interface I { } class A implements I{ public String toString(){ return "in a"; } } class B extends A{ public String toString(){ return "in b"; } } B b = new B(); A a = b; I i = a; System.out.println(i); System.out.println((B)a

为什么下面的代码可以工作

interface I { }

class A implements I{
    public String toString(){ return "in a"; }
}

class B extends A{
    public String toString(){ return "in b"; }
}
B b = new B();
A a = b;
I i = a;

System.out.println(i);
System.out.println((B)a);
System.out.println(b);
如您所见,
i
println
方法的有效参数。为什么?通过查看此方法接受的参数类型,似乎只有对象是相关的

我在寻找答案,发现了一些相关的东西: 引用类型都继承自java.lang.Object。类、枚举、数组和接口都是引用类型

但也发现了这个问题:“接口是否继承自Java中的对象类?”答案是:不,它们不是。在这方面,也没有公共的“根”接口隐式地由所有接口继承(与类的情况一样)。(*)

这是什么意思?有人能解释一下为什么接口被接受为
println
函数的参数吗

我想这里的要点是,如果没有对象本身,就无法通过接口传递对象


但问题仍然存在。为什么编译器接受接口作为此方法的参数?

是这样的。您不能实例化接口,因此任何对接口的引用都必须指向实现该接口的某个类的对象。并且该对象的超类在某个点上必须是object。

对此进行了解释:

给定非泛型类型声明C,类型C的直接超类型如下所示:

C的直接超类(§8.1.4)

C的直接上界面(§8.1.5)

类型对象,如果C是没有直接超级接口的接口类型(§9.1.3)


您可能会问,为什么对象是任何接口的超类型。原因是对象不能不作为具体类的实例,这个具体类也不能不扩展对象。因此,编译器知道对接口类型的引用就是对对象的引用。

您的误解源于混淆。继承和子类型是分开的

解释继承的含义:

接口
I
从其直接上级接口继承所有抽象和默认方法
m
[…]

当您有类似于
类字符串扩展对象{}
的内容时,
字符串
对象
的子类型,因此继承超类
对象
的成员


另一方面,接口是
对象的子类型,但不从中继承成员。这就是解释,接口不会继承的原因。

编译器与其说接受接口,不如说接受参数,而是对碰巧实现接口的对象的引用。考虑下面的代码片段,类似于您的代码,以及输出。您将看到,在这两种情况下,输出都是Box对象。在这两种情况下传递给println()的参数(或“thing”)是同一个Box对象。只是在一种情况下,它被称为Box的具体实例化,而在另一种情况下,它被称为实现a接口的对象

interface A {}

public class Box implements A
{

   public Box()
   {

   }

    public static void main(String[] args)
    {
        Box b =new Box();
        A a = b;   //define a reference to an object that implements interface A
        System.out.println(a);
        System.out.println(b);
    }
}
输出为:

Box@19e0bfd


Box@19e0bfd

接口不继承
对象
,但实现任何接口的任何实例都继承
对象
toString()
方法也是如此。我想,当调用System.out.println(..)时,如果将对象传递给它,编译器就会调用它的toString(),因此,理想情况下,我们传递的是一个字符串。@SashaSalauyou:不确定
toString
的相关性是什么…@SashaSalauyou相关性不大。它只是为了打印消息和查看方法调用而添加的
System.out.println
调用对象上的
toString
方法。编译器知道
i
实现了接口,因此
i
扩展了
object
。给定一个名为
Countable
接口
,我能够将已初始化为
null
Countable
类型的引用传递给
println
语句。既然
null
不是一个对象,那么它是如何工作的呢?@ChetanKinger我们这里讨论的是类型,而不是对象。类型
对象
总是类型
可数
@biziclop的直接(或间接)超类型。这个答案说
每个对象都是某个具体类的实例
。我想知道这与OP中的问题以及我在前面评论中的问题有什么关系。也就是说,你的意思是说
java
中的所有引用都是
Object
?@ChetanKinger它不是直接相关的,因为JLS规则说每个接口类型都直接或间接地将Object作为其超类型。但您可能会问,为什么对象是任何接口的超类型,原因是对象不能不作为具体类的实例,这个具体类也不能不扩展对象。@JBNizet您的编辑有意义,因为您添加了一些上下文:)