在Java8之前,java中的接口只能有抽象方法。默认情况下,接口的所有方法都是公共和抽象的。Java8允许接口具有默认和静态方法。我们在接口中使用默认方法的原因是,允许开发人员向接口添加新方法,而不会影响实现这些接口的类。

为什么选择默认方法?

例如,如果ABCD等几个类实现了一个接口XYZInterface,那么如果我们向XYZInterface添加一个新方法,我们必须更改实现该接口的所有类(A、B、C和D)中的代码。在本例中,我们只有四个类实现了我们想要更改的接口,但是想象一下,如果有数百个类实现了一个接口,那么几乎不可能更改所有这些类中的代码。这就是为什么在Java8中,我们有了一个新概念“默认方法”。这些方法可以添加到任何现有接口中,我们不需要强制在实现类中实现这些方法,因此我们可以在不破坏代码的情况下将这些默认方法添加到现有接口中。

我们可以说,java 8中引入了默认方法的概念,以便在现有接口中添加新方法,从而使它们向后兼容。向后兼容性是在不破坏旧代码的情况下添加新功能。

接口中的静态方法与默认方法类似,只是我们不能在实现这些接口的类中重写这些方法。

Java 8示例:接口中的默认方法

MyInterface中的方法newMethod()是默认方法,这意味着我们不需要在实现类示例中实现该方法。通过这种方式,我们可以将默认方法添加到现有接口中,而不必担心实现这些接口的类。

interface MyInterface{  
    /* This is a default method so we need not
     * to implement this method in the implementation 
     * classes  
     */
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    /* Already existing public and abstract method
     * We must need to implement this method in 
     * implementation classes.
     */
    void existingMethod(String str);  
}  
public class Example implements MyInterface{ 
	// implementing abstract method
    public void existingMethod(String str){           
        System.out.println("String is: "+str);  
    }  
    public static void main(String[] args) {  
    	Example obj = new Example();
    	
    	//calling the default method of interface
        obj.newMethod();     
        //calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn"); 
  
    }  
}

输出:

Newly added default method
String is: Java 8 is easy to learn

Java 8示例:接口中的静态方法

如上所述,接口中的静态方法与默认方法类似,因此我们不需要在实现类中实现它们。我们可以安全地将它们添加到现有接口中,而无需更改实现类中的代码。由于这些方法是静态的,我们不能在实现类中重写它们。

interface MyInterface{  
    /* This is a default method so we need not
     * to implement this method in the implementation 
     * classes  
     */
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    
    /* This is a static method. Static method in interface is
     * similar to default method except that we cannot override 
     * them in the implementation classes.
     * Similar to default methods, we need to implement these methods
     * in implementation classes so we can safely add them to the 
     * existing interfaces.
     */
    static void anotherNewMethod(){
    	System.out.println("Newly added static method");
    }
    /* Already existing public and abstract method
     * We must need to implement this method in 
     * implementation classes.
     */
    void existingMethod(String str);  
}  
public class Example implements MyInterface{ 
	// implementing abstract method
    public void existingMethod(String str){           
        System.out.println("String is: "+str);  
    }  
    public static void main(String[] args) {  
    	Example obj = new Example();
    	
    	//calling the default method of interface
        obj.newMethod();     
        //calling the static method of interface
        MyInterface.anotherNewMethod();
        //calling the abstract method of interface
        obj.existingMethod("Java 8 is easy to learn"); 
        
  
    }  
}

输出:

Newly added default method
Newly added static method
String is: Java 8 is easy to learn

Java 8 – 抽象类与接口

随着接口中默认方法的引入,抽象类似乎与Java8中的接口相同。然而,这并不是完全正确的,尽管我们现在可以像抽象类一样在接口中有具体的方法(带主体的方法),但这并不意味着它们是相同的。它们之间仍然没有什么区别,其中之一是抽象类可以有构造函数,而在接口中我们不能有构造函数。

接口的目的是提供完全抽象,而抽象类的目的是提供部分抽象。这仍然适用。界面就像是类的蓝图,通过引入默认方法,您可以简单地说,我们可以在界面中添加附加功能,而不会影响最终用户类。

默认方法和多重继承

当我们有两个具有相同签名的默认方法的接口时,可能会出现多重继承问题。让我们举个例子。

interface MyInterface{  
 
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    void existingMethod(String str);  
}  
interface MyInterface2{  
	 
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    void disp(String str);  
} 
public class Example implements MyInterface, MyInterface2{ 
	// implementing abstract methods
    public void existingMethod(String str){           
        System.out.println("String is: "+str);  
    }  
    public void disp(String str){
    	System.out.println("String is: "+str); 
    }
    
    public static void main(String[] args) {  
    	Example obj = new Example();
    	
    	//calling the default method of interface
        obj.newMethod();     
  
  
    }  
}

输出:

Error: Duplicate default methods named newMethod with the parameters () and () are inherited from the types MyInterface2 and MyInterface

这是因为我们在接口中都有相同的方法,而编译器不确定要调用哪个方法。

如何解决这个问题?

为了解决这个问题,我们可以在实现类中实现这个方法,如下所示:

interface MyInterface{  
 
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    void existingMethod(String str);  
}  
interface MyInterface2{  
	 
    default void newMethod(){  
        System.out.println("Newly added default method");  
    }  
    void disp(String str);  
} 
public class Example implements MyInterface, MyInterface2{ 
	// implementing abstract methods
    public void existingMethod(String str){           
        System.out.println("String is: "+str);  
    }  
    public void disp(String str){
    	System.out.println("String is: "+str); 
    }
    //Implementation of duplicate default method
    public void newMethod(){  
        System.out.println("Implementation of default method");  
    }  
    public static void main(String[] args) {  
    	Example obj = new Example();
    	
    	//calling the default method of interface
        obj.newMethod();     
  
  
    }  
}

输出:

Implementation of default method