Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 必须实现默认接口方法吗?_Java_Java 8_Default Method - Fatal编程技术网

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()

    但从长远来看,我更喜欢组合而不是继承,任务只是返回一个可运行项列表,而不是返回一个可运行项列表

  • 为什么我会犯这些错误?我希望它能够识别默认的实现
  • 我认为@biziclop在文章中正确地描述了这一点。简而言之,由于
    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)
    没有实现而阻塞,这是正确的:它没有实现。@Tunaki
    size
    get
    都同样实现了/没有实现implemented@aditsu
    SingleTask是一个单例实现
    ,您刚才已经说过了。如果它是一个实现,那么它应该是一个类,而不是一个接口。您在这里尝试使用的默认方法看起来有点像traits,它们不是专门为它设计的。如果这样做有效,您将得到一个
    列表
    实现,其中即使是
    equals
    hashCode
    等关键方法也会被破坏,因为它们最终可能会导致
    堆栈溢出错误
    。这种递归数据结构的意义是什么?我并没有强迫单任务实现者也扩展AbstractList,但看起来你是这样的。还有,你做了