由于无法实例化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时,该接口也被实例化,这是如此神秘。
答案 0 :(得分:4)
语法new Comparator<Point>(){...}
创建实现Comparator<Point>
接口的匿名类的实例。因此,您正在创建一个类的实例。
您永远不能创建接口的实例,只能创建实现该接口的类的实例。
最后,可以将实现接口的类的实例分配给该接口类型的变量。因此,可以为private final Comparator<? super E> comparator
分配一个实现Comparator
接口的类的实例。
答案 1 :(得分:0)
如果您声明类成员为接口类型,则可以将实现该接口的任何类分配给该成员。只要您不真正在意实现,这就很有用,只要接口中定义的方法可用即可。
例如,List
是一个接口。我可以将ArrayList
或LinkedList
(或任何其他实现)分配给类型List
的变量,但是我只能调用接口中定义的方法,而不能调用特定于接口的方法。任何实现类。
您给出的实例化Comparator
的代码实际上创建了一个实现该接口的匿名类。下面的方法是接口的实现方式。
答案 2 :(得分:0)
“无法实例化界面”是一个相当笼统的口号,它掩盖了更加细微的现实,在学习该语言的第一个月之后就不应该真正记住它。
代码
CategoryViewModel
做两件事:
compile time:创建一个实现接口的匿名类(通过为接口的方法提供具体实现)-该类还将具有通常的no-arg构造函数,因此可以在运行时创建该类的实例。
运行时:通过确保构造函数被调用来创建该匿名类的运行时实例。
因此,“接口无法实例化”旨在解释一个人不能编写
CategoryViewModel[]
(即,不提供提供接口方法的实现),但这并不意味着不可能创建作为实现该接口的类的实例的对象,即,创建已知并保证符合该接口。
“接口如何成为类成员”这个问题(及其措辞)在这里也暴露了您的一些困惑:代码
MainViewModel
不会导致将'Comparator <...>'声明为该类的成员,而是会导致'comparator'被声明为该类的成员,而该成员恰巧< em>属于'Comparator <...>'(在这种情况下,它必须是已知可以实现此接口的类型(/ class))。