在Java 1.8中添加默认方法后,接口是否仍然保持完全抽象?

3
在Java 1.8中添加默认方法后,接口是否仍然保持完全抽象?
如果我没有清楚地表述问题,我很抱歉。

1
是的,它将保持抽象,您需要为其提供实现类。 - justAbit
4
“fully” abstract 的确切含义是什么? - yshavit
4个回答

5

JLS8 §9.1.1.1. (抽象接口)明确规定(重点标记为我的):

每个接口都是隐式抽象的。这个修饰符已经过时,不应在新程序中使用。

此外,“完全抽象”这个术语对我来说没有意义。它应该意味着什么? “部分抽象”意味着什么? 没有这样的概念。


3
即使您的接口中只有一个默认方法,它也是抽象的。您必须提供实现类来实例化对象。请注意,在Java 8中添加的default方法具有特殊用途。从Java文档中可以看到:

默认方法使您能够向库的接口中添加新功能,并确保与为旧版本那些接口编写的代码具有二进制兼容性。

因此,您应该明智地使用default方法。

你为什么得出结论说“你应该谨慎使用default方法”?我不一定不同意,但我不明白你的断言是如何从引文中得出的。 - dimo414
想象一种场景,一个类实现了2个接口并且这两个接口具有相同签名的默认方法,你会得到编译时错误。 - justAbit
当然,但这是个问题吗?无论如何,你怎么能希望实现两个不同的接口来指定相同方法的不同行为呢?我不明白为什么一个人应该谨慎使用“default”方法,只是因为实现者可能会做出一些非理性的事情。 - dimo414
是的,这就是问题所在。假设客户端代码正在实现来自两个库的接口,并且这两个库的开发人员决定提供具有相同签名的默认方法实现,导致客户端代码出现错误。 - justAbit
当然,这只是一个理论上的危险。实际上,这并没有什么意义;为什么要使用两个不同的接口来执行相同方法的不同操作呢?但我并不反对建议接口设计者要小心谨慎。我只是想知道你在回答中提到了这些问题的哪些部分。 - dimo414
我明白你的意思,我应该在我的答案中解释清楚。但现在它已经在评论中了,所以用户可以看到我的意思 :) - justAbit

2
在我看来,是的。事实上,接口中的默认方法弥合了接口和抽象类之间的差异。默认方法有助于在不破坏现有代码的情况下实现接口。
关于Java接口默认方法的重要点:
1. Java 8接口默认方法将帮助我们避免使用实用程序类,例如所有集合类方法都可以在接口本身中提供。
2. Java接口默认方法将帮助我们删除基础实现类,我们可以提供默认实现,实现类可以选择覆盖哪个实现。
3. 引入接口默认方法的主要原因之一是增强Java 8中的Collections API以支持lambda表达式。如果层次结构中的任何类具有相同签名的方法,则默认方法变得无关紧要。
4. 默认方法不能覆盖java.lang.Object中的方法。原因非常简单,因为Object是所有Java类的基类。因此,即使我们在接口中定义了Object类方法作为默认方法,它也将是无用的,因为始终会使用Object类方法。这就是为什么要避免混淆,我们不能有覆盖Object类方法的默认方法。
5. Java接口默认方法也称为Defender方法或Virtual扩展方法。
来源:Java 8接口更改-静态方法,默认方法 示例:
在Java 8之前,我的接口更像下面这样,我们无法添加具有实现的方法:
public interface OldInterface {
    public void existingMethod();
}

在Java 8之后,我们可以添加默认方法,因此新接口将如下所示:
public interface OldInterface {
    public void existingMethod();

    default public void newDefaultMethod() {
        System.out.println("Default Interface method added in Java 8");
    }
}

以下类将正常工作:

public class OldInterfaceImpl implements OldInterface {
    public void existingMethod() {
     // existing implementation is here…
    }
}

我们可以创建一个 OldInterfaceImpl 的实例:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod(); 

1
我认为您在询问关于带有默认方法的接口是否有“具体”或“非抽象”的内容。答案是否定的。类在实例字段中存储状态,并与类的特定实例具体相关联。接口没有状态(即它们不能定义字段),因此根据您的术语,它们是“完全抽象的”。
Java 8添加了默认方法,因此现在可以指定方法的默认行为,但仅限于接口中的其他方法,而不是对象中的任何状态(因为在定义方法时没有这样的对象)。从概念上讲,默认方法只是让实现在一个方法可以完全基于接口中的其他方法定义时避免样板代码。例如,Collection.addAll()可以基于循环中调用的Collection.add()定义。这样做不会影响实现接口的任何类的状态-它们仍然通过定义所有非默认方法来完全控制类。
与此相反,抽象类可以具有实例字段,因此每个子类实例都有一些具体状态,子类无法阻止。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接