(一)语法层面的区别:
抽象类:
1.用abstract表示
2.里面有一个或多个抽象方法,在方法前加abstract,抽象类中也可以没有抽象方法,如静态方法,静态代码块
3.抽象类用extends继承,并且必须重写抽象方法,如果不重写的话则子类也会成为抽象类
接口
1.用implement表示
2.接口是极度抽象的类,所有方法都是抽象的,都需要进行重写
3.接口中默认的修饰符为public abstract(如果非要自己加访问符号,jdk1.8之前只能是public,而不能是private,static这些。jdk1.8新特性后面会有介绍)
接口的作用:解决java中的单继承问题,一个类可以实现多个接口,但只能有一个父类
(二)设计模式上的区别
抽象类:
1.面向类的整体进行一个抽象。比如对飞机或者鸟抽象出这两个类都具有的特点
2.是一种模板式设计,抽象出这个类的共同点。如果对抽象类新增了实现方法,则子类将不会发生发生改变,新增抽象方法则将发生改变
接口:
1.面向行为进行一个抽象。如鸟和飞机都会飞是一个行为,则可以将其设计为一个接口,然后让鸟类和飞机类都实现它们各自飞的特性
2.是一种辐射式设计模式,修改了接口,则实现了接口的类则需要发生改变
共同点:都不能被实例化
java8接口新特性:
java8使用两个概念扩展了接口的含义:默认方法和静态方法。
1)默认方法
默认方法使得开发者可以在不破坏二进制兼容包的情况下,默认实现接口中的方法。即不强制那些实现了该类的接口的类也实现这个方法。默认方法会被接口的实现类继承或者覆盖。默认方法需要被default修饰。
举个例子:
接口:TestJava8Interface
public interface TestJava8Interface {
default String hello() {
return "hello";
}
}
实现类:TestInterface8.java
public class TestInterface8 implements TestJava8Interface{
@org.junit.Test
public void Test() {
TestJava8Interface t = new TestInterface8();
System.out.println(t.hello());
}
}
运行结果:
hello
对接口中的方法进行覆盖
实现类:TestInterface8.java
public class TestInterface8 implements TestJava8Interface{
@Override
public String hello () {
return "override hello";
}
@org.junit.Test
public void Test() {
TestJava8Interface t = new TestInterface8();
System.out.println(t.hello());
}
}
运行结果:
override hello
2)静态方法
接口:TestJava8Interface
public interface TestJava8Interface {
static String helloWorld() {
return "hello world";
}
}
实现类:TestInterface8.java
public class TestInterface8 implements TestJava8Interface{
@Test
public void test () {
System.out.println(TestJava8Interface.helloWorld());
}
}
运行结果:
hello world
由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等。
尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误。如果你想了解更多细节,可以参考官方文档。