jdk8jdk9-接口的变化以及好处

在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的。由于这些修饰符都是默认的以下写法等价

public interface JDK8BeforeInterface { 
public static final int field1 = 0; 

int field2 = 0; 

public abstract void method1(int a) throws Exception; 

void method2(int a) throws Exception; 
}

JDK8及以后,允许我们在接口中定义static方法和default方法。

public interface JDK8Interface { 

// static修饰符定义静态方法 
static void staticMethod() { 
System.out.println("接口中的静态方法"); 
} 

// default修饰符定义默认方法 
default void defaultMethod() { 
System.out.println("接口中的默认方法"); 
} 
}

public class JDK8InterfaceImpl implements JDK8Interface { 
//实现接口后,因为默认方法不是抽象方法,所以可以不重写,但是如果开发需要,也可以重写 
}

public class Main { 
public static void main(String[] args) { 
// static方法必须通过接口类调用 
JDK8Interface.staticMethod(); 

//default方法必须通过实现类的对象调用 
new JDK8InterfaceImpl().defaultMethod(); 
} 
}

当然如果接口中的默认方法不能满足某个实现类需要,那么实现类可以覆盖默认方法。

public class AnotherJDK8InterfaceImpl implements JDK8Interface { 

// 签名跟接口default方法一致,但是不能再加default修饰符 
@Override 
public void defaultMethod() { 
System.out.println("接口实现类覆盖了接口中的default"); 
} 
}

由于java支持一个实现类可以实现多个接口,如果多个接口中存在同样的static和default方法会怎么样呢?如果有两个接口中的静态方法一模一样,并且一个实现类同时实现了这两个接口,此时并不会产生错误,因为jdk8只能通过接口类调用接口中的静态方法,所以对编译器来说是可以区分的。但是如果两个接口中定义了一模一样的默认方法,并且一个实现类同时实现了这两个接口,那么必须在实现类中重写默认方法,否则编译失败
也就是说继承两个接口如果有相同的默认方法类,就需要去重写默认方法。

好处

这样实现的好处:可以对于解决某些情况下,接口中的某些方法在子类之中的实现是一样的,这样就能减少重复代码,完成代码的复用;

Java9 的接口私有方法

抽象方法和接口的比较

接口方法默认修饰符是public。在java9以后可以用private定义私有方法,私有方法必须包含方法体。

通过以上对比抽象类的使用场景被削减,那么什么时候还需要使用抽象类
1、需要构造方法。
2、独立运行。
3、定义final方法防止子类篡改

在使用接口过程中需要注意如下几个问题:

1、Interface的所有方法访问权限自动被声明为public。在java9以后可以定义私有方法,但是必须有方法体不能是抽象方法。

2、接口中可以定义“成员变量”,或者说是不可变的常量,因为接口中的“成员变量”会自动变为为public static final。可以通过类命名直接访问:ImplementClass.name。

3、不能使用new操作符实例化一个接口,但可以声明一个接口变量,该变量必须引用(refer to)一个实现该接口的类的对象。可以使用 instanceof 检查一个对象是否实现了某个特定的接口。例如:if(anObject instanceof Comparable){}。

4、在实现多接口的时候一定要避免方法名的重复,尤其是default方法。

5、接口里的方法不能用final修饰

在使用抽象类时需要注意几点:

1、抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。

2、抽象方法必须由子类来进行重写。

3、只要包含一个抽象方法的抽象类,该类必须要定义成抽象类。

4、抽象类中可以包含具体的方法,当然也可以不包含抽象方法。

5、子类中的抽象方法不能与父类的抽象方法同名。

6、abstract不能与final并列修饰同一个类。

7、abstract 不能与private、static、final或native并列修饰同一个方法。

参数抽象类接口
默认的方法实现它可以有默认的方法实现jdk1.8之前没有,现在可以使用default关键字创在interface中创建一个default方法,该方法包含了具体的实现代码,一个接口中可以有多个default方法
实现子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有抽象的方法的实现。子类使用关键字implements来实现接口。它需要提供接口中所有声明的非default方法的实现
构造器抽象类可以有构造器接口没有构造器
实例化不能不能
访问修饰符抽象方法可以有public、protected和default这些修饰符接口方法默认修饰符是public。在java9以后可以用private定义私有方法,私有方法必须包含方法体。 私有方法体只能自己接口内使用
main方法抽象方法可以有main方法并且我们可以运行它接口没有main方法,因此我们不能运行它。
继承单一继承多继承
访问速度它比接口速度要快接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法
添加新方法如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。jdk1.8以后可以添加了,也就是说有一些在接口设计上的顽疾现在有了完美解决的方法
public interface SimpleInterface {
     public void doSomeWork();
      //A default method in the interface created using "default" keyword
      //使用default关键字创在interface中直接创建一个default方法,该方法包含了具体的实现代码
      default public void doSomeOtherWork(){
          getStu();
        System.out.println("DoSomeOtherWork implementation in the interface");
      }
      static void getStatic() {
          System.out.println("static method");
        }
      default public void doSomeOtherWork2(){
          getStu();
          //私有静态方法用于为接口中的默认方法服务
          getStatic1();
            System.out.println("DoSomeOtherWork2 implementation in the interface");
          }
      //java9中可以创建私有方法了
      private void getStu() {
          System.out.println( "private method!");
        }
    //java9中可以创建私有静态方法了
      private static void getStatic1() {
          System.out.println("private static method");
        }
}

class SimpleInterfaceImpl implements SimpleInterface{
 @Override
 public void doSomeWork() {
   System.out.println("Do Some Work implementation in the class");
 }
 @Override
 public void doSomeOtherWork() {
   System.out.println("Do doSomeOtherWork implementation in the class");
 }
 /*
  * Not required to override to provide an implementation 
  * for doSomeOtherWork.
  * 在SimpleInterfaceImpl里,不需要再去实现接口中定义的doSomeOtherWork方法
  */

 public static void main(String[] args) {
     SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();
   simpObj.doSomeWork();
   simpObj.doSomeOtherWork();
   simpObj.doSomeOtherWork2();
   SimpleInterface.getStatic();
 }
}
···