ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
除了接口的多重继承,另一个区别是Java8中只有一个方法的抽象类不是Functional接口。
@FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
}
execute(SimpleFuncInterface function) {
function.doWork();
}
execute(()->System.out.printline("Did work"));
我想到的一个例子是Java MapReduce API for Hadoop,它在0.20.0版本中进行了更改,以支持抽象类而不是接口,因为它们更容易发展。这意味着,一个新的方法可以添加到抽象类(默认实现),而不破坏类的旧实现。 随着Java 8 Interface Default方法的引入,这种缺乏可扩展性的问题得到了解决。
public interface MyInterface {
int method1();
// default method, providing default implementation
default String displayGreeting(){
return "Hello from MyInterface";
}
}
4条答案
按热度按时间mo49yndu1#
是的,他们是不同的。
有了接口,客户端可以实现它,也可以扩展一个类:
对于类,客户端将能够扩展它,但不能扩展任何其他类型:
当
interface
或abstract class
只有一个抽象方法声明时,会出现另一个差异,它与匿名函数(lambda)有关。正如@AlexanderPetrov所说,具有一个方法的接口可以用作 * 函数接口 *,允许我们在指定函数接口类型的地方“动态”创建函数:
这不能用
abstract class
来完成。所以你不能互换使用它们。不同之处在于客户端如何使用它的限制,这是由JVM的语义强制执行的。至于资源使用的差异,这不是什么值得担心的事情 *,除非它导致您的软件问题 *。**使用内存管理语言的想法是不要担心这些事情,除非你有问题。**不要预先优化,我相信差异是可以忽略的。即使存在差异,也应该只在可能导致软件问题时才有关系。
如果您的软件有资源问题,请分析您的应用程序。如果它确实导致了内存问题,您将能够看到它,以及每个问题消耗了多少资源。在那之前,你不用担心。您应该更喜欢使代码更易于管理的功能,而不是消耗最少资源的功能。
zzzyeukh2#
JVM内部结构和内存表示对于JVM来说几乎相同。我的陈述基于第四章-类文件格式。从所附文档中可以看出,JVM通过access_flags在类和接口之间产生差异。如果你有一个Simple接口只有一个方法和一个简单的抽象类只有一个方法。此格式中的大多数字段都是相同的(空),主要区别在于access_flags。
默认构造函数生成抽象类正如@Holger所指出的,Interface和Abstract类之间的另一个小区别是普通类需要构造函数。Java编译器将为Abstract类生成一个默认构造函数,该构造函数将被Abstract类的每个子类调用。从这个意义上说,抽象类定义将比接口稍大。
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
除了接口的多重继承,另一个区别是Java8中只有一个方法的抽象类不是Functional接口。
这一点在抽象类中是无法实现的。
**接口-缺乏“扩展的开放性”。**直到Java 8的接口都因缺乏可扩展性而受到批评。如果你改变了接口约定,你需要重构一个接口的所有客户端。
我想到的一个例子是Java MapReduce API for Hadoop,它在0.20.0版本中进行了更改,以支持抽象类而不是接口,因为它们更容易发展。这意味着,一个新的方法可以添加到抽象类(默认实现),而不破坏类的旧实现。
随着Java 8 Interface Default方法的引入,这种缺乏可扩展性的问题得到了解决。
使用Java 8,可以向接口和抽象类添加新方法,而不会破坏客户端类的契约。http://netjs.blogspot.bg/2015/05/interface-default-methods-in-java-8.html
igsr9ssn3#
它们在实现上是不同的
1zmg4dgp4#
如果你在谈论性能,那么不久前有一种观点认为接口比抽象类慢。但是现在JIT在它们之间没有区别。
请参阅this answer了解更多详情。