Home >Java >javaTutorial >Detailed introduction to the default method of Java8
What is the default method?
After the release of Java 8, new methods can be added to the interface, but the interface can still remain compatible with its implementation class. This is important because the library you develop may be widely used by multiple developers. Before Java 8, after an interface was published in a class library, if a new method was added to the interface, applications that implemented this interface would be in danger of crashing using the new version of the interface.
With Java 8, is there no such danger? the answer is negative.
Adding default methods to interfaces may make some implementation classes unavailable.
First, let us look at the details of the default method.
In Java 8, methods in interfaces can be implemented (static methods in Java 8 can also be implemented in interfaces, but this is another topic). The method implemented in the interface is called the default method, which is identified with the keyword default as a modifier. When a class implements an interface, it can implement methods that are already implemented in the interface, but this is not required. This class will inherit the default method. This is why when the interface changes, the implementation class does not need to be changed.
What about multiple inheritance?
When a class implements more than one (such as two) interfaces, and these interfaces have the same default method, things become very complicated. Which default method does the class inherit? Neither! In this case, the class itself (either directly or a class higher up the inheritance tree) must implement the default method.
The same is true when one interface implements the default method and another interface declares the default method as abstract. Java 8 tries to avoid ambiguity and maintain rigor. If a method is declared in multiple interfaces, then none of the default implementations will be inherited and you will get a compile-time error.
However, if you have compiled your class, there will be no compile-time errors. At this point, Java 8 is inconsistent. It has its own reasons, and there are various reasons. I don’t want to explain it in detail or discuss it in depth here (because: the version has been released, the discussion time is too long, and this platform has never had such a discussion).
1. Suppose you have two interfaces and one implementation class.
2. One of the interfaces implements a default method m().
3. Compile the interface and implementation class together.
4. Modify the interface that does not contain the m() method and declare the m() method as abstract.
5. Recompile the modified interface separately.
6. Run the implementation class.
The class can run normally in the above situation. However, you cannot recompile with the modified interface, but compiling with the old interface can still run. Next
#1. Modify the interface containing abstract method m() and create a default implementation.
2. Compile the modified interface
3. Run the class: Failed.
When two interfaces provide a default implementation for the same method, this method cannot be called unless the implementation class also implements the default method (either directly or higher up in the inheritance tree) class does the implementation).
However, this class is compatible. It can be loaded using the new interface, and can even be executed, as long as it does not call methods that have default implementations in both interfaces.
Example code:
In order to demonstrate the above example, I created a test directory for C.java, There are also 3 subdirectories under it, used to store I1.java and I2.java. The test directory contains the source code C.java of class C. The base directory contains the version of the interface that can be compiled and run. I1 contains the m() method with default implementation, and I2 does not contain any methods.
The implementation class contains the main method, so we can execute it in the test. It will check whether there are command line parameters, so that we can easily perform tests calling m() and not calling m().
~/github/test$ cat C.java public class C implements I1, I2 { public static void main(String[] args) { C c = new C(); if(args.length == 0 ){ c.m(); } } } ~/github/test$ cat base/I1.java public interface I1 { default void m(){ System.out.println("hello interface 1"); } } ~/github/test$ cat base/I2.java public interface I2 { }
Use the following command line to compile and run:
~/github/test$ javac -cp .:base C.java ~/github/test$ java -cp .:base C hello interface 1
The compatible directory contains the I2 interface with abstract method m(), and the unmodified I1 interface.
~/github/test$ cat compatible/I2.java public interface I2 { void m(); }
This cannot be used to compile class C:
~/github/test$ javac -cp .:compatible C.java C.java:1: error: C is not abstract and does not override abstract method m() in I2 public class C implements I1, I2 { ^ 1 error
The error message is very precise. Because we have the C.class obtained in the previous compilation, if we compile the interface in the compatible directory, we will still get two interfaces that can run the implementation class:
~/github/test$ javac compatible/I*.java ~/github/test$ java -cp .:compatible C hello interface 1
The third directory called wrong contains The I2 interface also defines the m() method:
~/github/test$ cat wrong/I2.java public interface I2 { default void m(){ System.out.println("hello interface 2"); } }
我们应该不厌其烦的编译它。尽管m()方法被定义了两次,但是,实现类仍然可以运行,只要它没有调用那个定义了多次的方法,但是,只要我们调用m()方法,立即就会失败。这是我们使用的命令行参数:
~/github/test$ javac wrong/*.java ~/github/test$ java -cp .:wrong C Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: I1.m I2.m at C.m(C.java) at C.main(C.java:5) ~/github/test$ java -cp .:wrong C x ~/github/test$
结论
当你把给接口添加了default实现的类库移植到Java 8环境下的时候,一般不会有问题。至少Java8类库开发者给集合类添加default方法的时候就是这么想的。使用你类库的应用程序仍然依赖没有default方法的Java7的类库。当使用和修改多个不同的类库的时候,有很小的几率会发生冲突。如何才能避免呢?
像以前那样设计你的类库。可能依赖default方法的时候不要掉以轻心。万不得已不要使用。明智的选择方法名,避免和其它接口产生冲突。我们将会学习到Java编程中如何使用这个特性做开发。
更多Detailed introduction to the default method of Java8相关文章请关注PHP中文网!