Java 必须实现默认接口方法吗?
下面是一个显示我的问题的简化示例:Java 必须实现默认接口方法吗?,java,java-8,default-method,Java,Java 8,Default Method,下面是一个显示我的问题的简化示例: import java.util.List; 公共接口SingleTask扩展列表,可运行{ 默认可运行get(最终整数x){ 如果(x!=0){ 抛出新的IndexOutOfBoundsException(); } 归还这个; } 默认整数大小(){ 返回1; } } 导入java.util.AbstractList; 公共类MyTask扩展了AbstractList,实现了SingleTask{ @凌驾 公开募捐{ System.out.println(“
import java.util.List;
公共接口SingleTask扩展列表,可运行{
默认可运行get(最终整数x){
如果(x!=0){
抛出新的IndexOutOfBoundsException();
}
归还这个;
}
默认整数大小(){
返回1;
}
}
导入java.util.AbstractList;
公共类MyTask扩展了AbstractList,实现了SingleTask{
@凌驾
公开募捐{
System.out.println(“你好”);
}
}
在SingleTask
中,我提供了方法get
和size
的实现,这是AbstractList
中唯一的抽象方法。但是,当我编译MyTask
时,仍然会出现如下错误:
MyTask类型必须实现继承的抽象方法
AbstractCollection.size()
或
java:3:错误:MyTask不是抽象的,并且不重写抽象列表中的抽象方法get(int)
(取决于编译器)。当然,我正在使用Java8
所以我有两个问题:
MyTask
中使用这两个方法而不复制整个代码的最简单方法是什么强制
SingleTask
实现者也实现List
的所有方法不是很优雅,默认方法也不是用来定义你的SingleTask
界面看起来像的特征实体
将默认方法作为trait是个坏主意有几个原因,最明显的一个原因是任何实现者都可以简单地覆盖默认方法,破坏您的trait
这正是这里发生的事情:因为AbstractList
明确地将get()
和size()
声明为abstract
,这意味着SingleTask
将继承它们,而不是您在超级接口中可能拥有的默认实现
:
类C继承自其直接超类和直接
SuperInterface所有抽象和默认(§9.4)方法
以下所有情况都是正确的:
- C从其直接超类继承的具体方法没有签名是m签名的子签名
public abstract class SingleTask extends AbstractList<Runnable> implements Runnable {
@Override
public final Runnable get(final int x) {
if (x != 0) {
throw new IndexOutOfBoundsException();
}
return this;
}
@Override
public final int size() {
return 1;
}
@Override
public abstract void run();
}
公共抽象类SingleTask扩展AbstractList实现可运行{
@凌驾
公共最终可运行get(最终整数x){
如果(x!=0){
抛出新的IndexOutOfBoundsException();
}
归还这个;
}
@凌驾
公共最终整数大小(){
返回1;
}
@凌驾
公开摘要无效运行();
}
它的缺点是您的任务必须扩展SingleTask
,因此不能扩展任何其他内容,从好的方面来说,虽然它们不需要处理任务,但它们也是列表
,它们只需要实现run()
但从长远来看,我更喜欢组合而不是继承,任务只是返回一个可运行项列表,而不是返回一个可运行项列表
AbstractList
将get(int)
和size()
方法声明为抽象方法,因此它们优先于SingleTask
中的默认实现
MyTask
中使用这两个方法而不复制整个代码的最简单方法是什么MyTask
中的get(int)
和size()
方法,以便它们委托给SingleTask
界面中的默认方法:
public class MyTask extends AbstractList<Runnable> implements SingleTask {
@Override
public void run() {
System.out.println("hello");
}
@Override
public Runnable get(int index) {
return SingleTask.super.get(index);
}
@Override
public int size() {
return SingleTask.super.size();
}
}
公共类MyTask扩展AbstractList实现SingleTask{
@凌驾
公开募捐{
System.out.println(“你好”);
}
@凌驾
公共可运行get(int索引){
返回SingleTask.super.get(索引);
}
@凌驾
公共整数大小(){
返回SingleTask.super.size();
}
}
使用这种方法,您将有点委托给
SingleTask
中的默认方法。我不认为这是一件坏事(至少,您不需要使用属性)。此外,编写这些方法是有意义的,这样您就可以选择提供默认实现的接口。不要让您的任务扩展List
(这在语义上意味着什么?),而是使用公共列表getRunnables()创建一个接口Task
代码>方法。如果做不到这一点,只需将SingleTask
变成一个抽象类,而不是一个接口。值得注意的是,Eclipse被未实现的size()
阻塞了:这可能是一个Eclipse错误javac
1.8.0\u 51被get(int)
没有实现而阻塞,这是正确的:它没有实现。@Tunakisize
和get
都同样实现了/没有实现implemented@aditsuSingleTask是一个单例实现
,您刚才已经说过了。如果它是一个实现,那么它应该是一个类,而不是一个接口。您在这里尝试使用的默认方法看起来有点像traits,它们不是专门为它设计的。如果这样做有效,您将得到一个列表
实现,其中即使是equals
或hashCode
等关键方法也会被破坏,因为它们最终可能会导致堆栈溢出错误
。这种递归数据结构的意义是什么?我并没有强迫单任务实现者也扩展AbstractList,但看起来你是这样的。还有,你做了