抽象类和接口都是 Java 中的重要概念,它们在面向对象编程中都扮演着重要角色,但是它们之间有许多不同点。下面在概念、用法、特性、设计等方面详细比较抽象类和接口的区别。
这里先列举接口和抽象类的区别
- 抽象类可以有构造方法,而接口不能有构造方法。因为接口是抽象的,它没有实现,所以它没有构造方法。
- 抽象类可以有成员变量,而接口没有成员变量。因为接口中的所有变量都默认为public static final,所以它们必须被初始化,而且不能被修改。
- 抽象类可以有非抽象方法,而接口不能有非抽象方法。因为接口是抽象的,它只能有抽象方法,而抽象类可以有抽象方法和非抽象方法。
- 抽象类可以实现接口,而接口不能实现抽象类。因为接口是抽象的,它只能被实现,而抽象类可以被继承和实现。
- 抽象类的子类只能继承一个抽象类,而一个类可以实现多个接口。因为Java不支持多继承,所以一个类只能继承一个抽象类,但它可以实现多个接口。
- 抽象类可以有普通的方法,而接口不能有普通的方法。因为接口中的所有方法都默认为public abstract,所以它们不能有方法体,而抽象类可以有普通的方法和方法体。
- 抽象类的访问权限可以是public、protected和default,而接口的访问权限只能是public。因为接口是用来定义公共的API,所以它的访问权限只能是public,而抽象类可以有不同的访问权限。
概念
抽象类和接口都是 Java 中的概念。抽象类是一个已经存在的类,并且是一个被声明为抽象的类。接口是一种完全抽象的类,它只定义了一组方法的签名,并没有实现任何具体行为。
用法
抽象类和接口的用法也不同。对于抽象类来说,我们可以使用 abstract
关键字将某个类定义为抽象类,然后定义抽象方法,子类必须实现这个抽象方法或将子类也定义为抽象类。而对于接口来说,我们使用 interface
关键字来定义接口,接口中所有的方法都是抽象方法,而且默认已经加上 public abstract
修饰符,子类必须实现接口中的所有方法。
// 抽象类
public abstract class AbstractClass {public abstract void call();}// 接口
public interface MyInterface {void run();}
特性
抽象类和接口也有自己独特的特性。抽象类不仅可以定义抽象方法,还可以定义普通方法、成员变量以及构造方法等。而接口则只能定义抽象方法、常量(final
)和静态方法(JDK 1.8 后)。
此外,接口还具有多继承的特性。在 Java 中,一个类只能继承自一个父类(除了 Object 类),但是一个类可以实现多个接口。
// 抽象类
public abstract class AbstractClass {private int value;public AbstractClass(int value) {this.value = value;}public void say() {System.out.println("Hello!");}}// 接口
public interface MyInterface1 {void say();}public interface MyInterface2 {void run();}class MyClass implements MyInterface1, MyInterface2 {@Overridepublic void say() {System.out.println("Hello");}@Overridepublic void run() {System.out.println("run");}
}
设计
抽象类和接口的设计目的也不同。抽象类主要是为了让子类继承并实现一些通用的行为,比如 java.util.AbstractList
和 java.util.AbstractMap
等。而接口主要是为了定义一些行为规范,比如 java.util.Collection
、java.io.Serializable
等。
因此,在设计接口和抽象类时需要考虑到其用途和目的。如果要定义一些通用行为并在子类中实现,可以使用抽象类;如果要定义一些行为规范,并且希望多个类实现这些规范,可以使用接口。
JDK1.8接口特性
在 JDK 1.8 中,Java 语言引入了一种新的概念:默认方法(default method),也叫扩展方法。接口中可以定义默认方法和静态方法,这样子类就可以直接继承这些方法,避免了它们需要重新实现。
示例代码如下:
public interface MyInterface {void say();default void run() {System.out.println("run");}static void call() {System.out.println("call");}
}// 如果想使用该接口的默认方法或静态方法,可以直接继承该接口即可
class MyClass implements MyInterface {@Overridepublic void say() {System.out.println("say");}
}
JDK1.9接口特性
在 JDK 1.9 及后续的版本中,Java 语言对接口进行了一些改变,包括私有方法和私有静态方法。私有方法和私有静态方法只能在接口内部被调用,无法从接口的实现类或外部访问。
示例代码如下:
public interface MyInterface {void say();default void methodA() {methodB();methodC();System.out.println("methodA is running");}private void methodB() {System.out.println("methodB is running");}private static void methodC() {System.out.println("methodC is running");}
}class MyClass implements MyInterface {@Overridepublic void say() {System.out.println("say");}
}
这样,我们就可以在接口中定义一些私有方法或私有静态方法,可以更好地封装一些不希望被外部访问的逻辑。