接口和抽象类的区别、Java8接口特性
接口和抽象类的区别:
1.接口的方法默认为public abstract ,接口中的变量默认为public static final,在java8之前所有的方法不能有实现
抽象类中可以有非抽象方法
2.一个类可以实现多个接口,但只能继承一个抽象类
3.一个类实现接口,要实现该接口的所有抽象方法。
4.接口不能被实例化,但可以声明,但是必须引用一个实现该接口的对象。
抽象类可以有构造方法,但是不能被直接通过new进行实例化。但可以通过子类继承,实例化子类的时候抽象类也会被实例化。
这其实用到了多态,向上转型。父类引用指向子类对象。
5.从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
java8为接口添加了 静态方法和默认方法
静态方法:使用 static 关键字修饰。可以通过接口直接调用静态方法,不能被重写。
默认方法:默认方法使用 default 关键字修饰。可以通过实现类对象来调用,可以被重写但要去掉default关键字
interface MyInterface{ //抽象方法 public abstract void eat(); //静态方法 public static void sleep() { System.out.println("睡觉中"); } //默认方法 public default void coding() { System.out.println("写代码"); } } public class Test implements MyInterface{ public static void main(String[] args){ //通过接口名,调用接口中的静态方法 MyInterface.sleep(); //通过实现类对象调用默认方法 Test t = new Test(); t.coding(); } //默认方法可以被重写,但要去掉default关键字 @Override public void coding() { System.out.println("我在写代码"); } //实现一个接口,必须重写所有的抽象方法 @Override public void eat() { // TODO Auto-generated method stub } }
函数式接口:
1.有且仅有一个抽象方法的接口,比如Java标准库中的java.lang.Runnable和 java.util.Comparator都是典型的函数式接口。
2.java 8提供 @FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),
虚拟机会自动判断, 但最好在接口上使用注解@FunctionalInterface,它可以检测接口是否是一个函数式接口。
3.函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用
于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。
4.Lambda可以被当做匿名内部类,但是稍有不同,匿名内部类编译完成会生成$文件,Lambda则不会。
5.函数式接口的使用:一般可以作为方法的参数和返回值类型
/** *函数式接口:有且仅有一个抽象方法的接口称为函数式接口。接口中也可以包含其他方法(默认、静态) *@FunctionalInterface注解 可以检测该接口是否为函数式接口(即只能有一个抽象方法) */ @FunctionalInterface interface MyFunctionInterface{ //抽象方法 public abstract void method(); } /** *接口的实现类 */ class MyFunctionInterfaceImpl implements MyFunctionInterface{ @Override public void method() { System.out.println("接口的实现类,重写接口中的方法"); } } /** * 测试类 * 函数式接口的使用:作为方法的参数 * */ public class Test01 { //定义一个方法,参数使用函数式接口 public static void show(MyFunctionInterface mfi) { mfi.method(); } public static void main(String[] args) { //调用show方法,方法的参数是一个接口,所以可以传递接口的实现类对象 show(new MyFunctionInterfaceImpl()); //调用show方法,方法的参数是一个接口,所以可以传递接口的匿名内部类 show(new MyFunctionInterface() { @Override public void method() { System.out.println("使用匿名内部类重新接口中的方抽象法"); } }); //使用lambda表达式简化匿名内部类 show(()->{ System.out.println("使用lambda表达式重写接口中的方法"); }); //简化后的lambda表达式 show(()->System.out.println("简化后的")); } }