1.1抽象类与接口的区别
1.1.1. Abstract classes versus interfaces in Java 8
1.1.2. Conceptual Difference:
1.2 Java 8中的接口默认方法
1.2.1. What is Default Method?
1.2.2. ForEach method compilation error solved using Default Method
1.2.3. Default Method and Multiple Inheritance Ambiguity Problems
1.2.4. Important points about java interface default methods:
1.3 Java接口静态方法
1.3.1. Java Interface Static Method, code example, static method vs default method
1.3.2. Important points about java interface static method:
1.4 Java功能接口
1.1.1. Java 8中的抽象类与接口
Java 8 interface changes include static methods and default methods in
interfaces. Prior to Java 8, we could have only method declarations in
the interfaces. But from Java 8, we can have default methods and
static methods in the interfaces.
After introducing Default Method, it seems that interfaces and
abstract classes are same. However, they are still different concept
in Java 8.
Abstract class can define constructor. They are more structured and
can have a state associated with them. While in contrast, default
method can be implemented only in the terms of invoking other
interface methods, with no reference to a particular implementation's
state. Hence, both use for different purposes and choosing between two
really depends on the scenario context.
1.1.2. 概念上的差别:
抽象类对接口的骨架(即部分)实现有效,但如果没有匹配的接口就不应该存在。
因此,当抽象类被有效地简化为低可见性的接口骨架实现时,默认方法是否也能消除这种情况呢?毫无疑问:不!实现接口几乎总是需要一些或全部的类构建工具,而默认方法不具备这些工具。如果某些接口没有,这显然是一个特例,不应该让您误入歧途。
1.2 Java 8中的接口默认方法
Java 8引入了“默认方法”或(防御方法)新特性,允许开发人员在不破坏现有接口实现的情况下向接口添加新方法。它提供了灵活性,允许接口定义实现,在具体类无法为该方法提供实现的情况下,接口定义实现将作为默认值使用。
让我们看一个小例子来理解它是如何工作的:
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
下面的类将在Java JDK 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.2.1. 默认的方法:
默认方法从来不是最终的,不能同步,也不能
重写Object的方法。他们总是公开的,这很严重
限制了编写简短且可重用方法的能力。
缺省方法可以提供给接口而不影响类的实现,因为它包含实现。如果在用实现定义的接口中添加的每个方法都不影响实现类。实现类可以覆盖接口提供的默认实现。
默认方法允许向现有接口添加新功能
而不会破坏这些接口的旧实现。
当我们扩展一个包含默认方法的接口时,我们可以执行以下操作,
不重写默认方法,将继承默认方法。
重写默认方法,类似于重写中的其他方法
子类。
将默认方法重新声明为抽象,从而强制子类为
覆盖它。
1.2.2. 使用默认方法解决了所有方法编译错误
对于Java 8, JDK集合已经被扩展,forEach方法被添加到整个集合中(它与lambdas一起工作)。使用常规方法,代码如下所示,
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
由于此结果每个实现类都有编译错误,因此,默认方法添加了必需的实现,以便现有的实现不应被更改。
具有默认方法的可迭代接口如下所示,
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
同样的机制已经被用于在不破坏实现类的情况下在JDK接口中添加流。
1.2.3. 默认方法与多重继承歧义问题
由于java类可以实现多个接口,并且每个接口可以定义具有相同方法签名的默认方法,因此,继承的方法之间可能会发生冲突。
考虑下面的例子,
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
上述代码将无法编译,并出现以下错误:
类Impl继承defaultMethod()的不相关默认值
类型为InterfaceA和InterfaceB
为了修复这个类,我们需要提供默认的方法实现:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
此外,如果我们想调用任何一个super Interface提供的默认实现,而不是我们自己的实现,我们可以这样做:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
我们可以选择任何默认实现,也可以同时选择两者作为新方法的一部分。
1.2.4. java接口默认方法的要点:
Java interface default methods will help us in extending interfaces without having the fear of breaking implementation classes.
Java interface default methods have bridge down the differences between interfaces and abstract classes.
Java 8 interface default methods will help us in avoiding utility classes, such as all the Collections class method can be provided in the interfaces itself.
Java interface default methods will help us in removing base implementation classes, we can provide default implementation and the implementation classes can chose which one to override.
One of the major reason for introducing default methods in interfaces is to enhance the Collections API in Java 8 to support lambda expressions.
If any class in the hierarchy has a method with same signature, then default methods become irrelevant. A default method cannot override a method from java.lang.Object. The reasoning is very simple, it’s because Object is the base class for all the java classes. So even if we have Object class methods defined as default methods in interfaces, it will be useless because Object class method will always be used. That’s why to avoid confusion, we can’t have default methods that are overriding Object class methods.
Java interface default methods are also referred to as Defender Methods or Virtual extension methods.
资源链接:
何时使用:Java 8+接口默认方法,vs.抽象方法
JDK 8时代的抽象类与接口
通过虚拟扩展方法进行接口演化
1.3 Java接口静态方法
1.3.1. Java接口静态方法,代码示例,静态方法与默认方法
Java接口静态方法与默认方法类似,只是我们不能在实现类中重写它们。这个特性可以帮助我们避免在实现类中实现不好的情况下产生不希望看到的结果。让我们用一个简单的例子来研究这个问题。
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
现在让我们来看看一个实现类,它有一个isNull()方法,但实现很差。
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
注意isNull(String str)是一个简单的类方法,它不会覆盖接口方法。例如,如果我们将@Override注释添加到isNull()方法,它将导致编译器错误。
现在,当我们运行应用程序时,会得到以下输出。
接口空检查
Impl Null检查
如果我们将接口方法从静态改为默认,我们将得到以下输出。
Impl Null检查
MyData打印:
Impl Null检查
Java接口静态方法只对接口方法可见,如果我们从MyDataImpl类中删除isNull()方法,我们将不能将它用于MyDataImpl对象。然而,像其他静态方法一样,我们可以使用类名来使用接口静态方法。例如,一个有效的语句将是:
boolean result = MyData.isNull("abc");
1.3.2. java接口静态方法的要点:
Java interface static method is part of interface, we can’t use it for implementation class objects.
Java interface static methods are good for providing utility methods, for example null check, collection sorting etc.
Java interface static method helps us in providing security by not allowing implementation classes to override them.
We can’t define interface static method for Object class methods, we will get compiler error as “This static method cannot hide the instance method from Object”. This is because it’s not allowed in java, since Object is the base class for all the classes and we can’t have one class level static method and another instance method with same signature.
We can use java interface static methods to remove utility classes such as Collections and move all of it’s static methods to the corresponding interface, that would be easy to find and use.
1.4 Java功能接口
在我结束这篇文章之前,我想简单介绍一下Functional接口。只有一个抽象方法的接口称为功能接口。
引入了一个新的注释@FunctionalInterface,将接口标记为Functional interface。@FunctionalInterface注释是避免在函数接口中意外添加抽象方法的工具。这是可选的,但使用它是很好的实践。
函数式接口是人们期待已久的Java 8特性,因为它允许我们使用lambda表达式来实例化它们。添加了一个新的包java.util.function,其中包含一系列函数接口,为lambda表达式和方法引用提供目标类型。我们将在以后的文章中讨论函数接口和lambda表达式。
资源位置:
Java 8接口更改-静态方法,默认方法