接口如何成为类成员并由类构造函数实例化?

时间:2019-07-04 11:59:59

标签: java

由于无法实例化Java接口,接口如何成为类成员并由类构造函数实例化。

jdk代码:

public class PriorityQueue<E> extends AbstractQueue<E>
    implements java.io.Serializable {
 private final Comparator<? super E> comparator;
...
}

和用户代码:

PriorityQueue<Point> pq = new PriorityQueue<Point>(1005,new Comparator<Point>(){
            public int compare(Point p1,Point p2){
                ...
            }
        });

上面PriorityQueue的用法是有效的(仅作为示例)。而且PriorityQueue类中的Comparator实际上是一个接口。那么接口成为类的成员了吗?此外,当实例化PriorityQueue时,该接口也被实例化,这是如此神秘。

3 个答案:

答案 0 :(得分:4)

语法new Comparator<Point>(){...}创建实现Comparator<Point>接口的匿名类的实例。因此,您正在创建一个类的实例。

您永远不能创建接口的实例,只能创建实现该接口的类的实例。

最后,可以将实现接口的类的实例分配给该接口类型的变量。因此,可以为private final Comparator<? super E> comparator分配一个实现Comparator接口的类的实例。

答案 1 :(得分:0)

如果您声明类成员为接口类型,则可以将实现该接口的任何类分配给该成员。只要您不真正在意实现,这就很有用,只要接口中定义的方法可用即可。

例如,List是一个接口。我可以将ArrayListLinkedList(或任何其他实现)分配给类型List的变量,但是我只能调用接口中定义的方法,而不能调用特定于接口的方法。任何实现类。

您给出的实例化Comparator的代码实际上创建了一个实现该接口的匿名类。下面的方法是接口的实现方式。

答案 2 :(得分:0)

“无法实例化界面”是一个相当笼统的口号,它掩盖了更加细微的现实,在学习该语言的第一个月之后就不应该真正记住它。

代码

CategoryViewModel

做两件事:

compile time:创建一个实现接口的匿名类(通过为接口的方法提供具体实现)-该类还将具有通常的no-arg构造函数,因此可以在运行时创建该类的实例。

运行时:通过确保构造函数被调用来创建该匿名类的运行时实例。

因此,“接口无法实例化”旨在解释一个人不能编写

CategoryViewModel[]

(即,不提供提供接口方法的实现),但这并不意味着不可能创建作为实现该接口的类的实例的对象,即,创建已知并保证符合该接口。

“接口如何成为类成员”这个问题(及其措辞)在这里也暴露了您的一些困惑:代码

MainViewModel

不会导致将'Comparator <...>'声明为该类的成员,而是会导致'comparator'被声明为该类的成员,而该成员恰巧< em>属于'Comparator <...>'(在这种情况下,它必须是已知可以实现此接口的类型(/ class))。