Java abstract和interface的区别
1. 抽象类(Abstract Class)
定义:抽象类是包含一个或多个抽象方法(没有实现的方法)的类,不能直接实例化,必须由子类继承并实现抽象方法。
使用abstract关键字:类和方法都需要用abstract关键字声明。
继承方式:抽象类可以使用普通的类继承机制,支持单继承(一个类只能继承一个抽象类)。
成员变量:可以包含实例变量(字段)、构造方法和已实现的方法(非抽象方法)。
访问修饰符:抽象类中的方法和成员变量可以使用所有的访问修饰符(public、protected、private)。
适用场景:当多个类有一些相同的功能,并且还需要一些差异化的实现时,可以使用抽象类。
interface Animal { void sound(); default void sleep() { System.out.println("Sleeping..."); } }
class Dog implements Animal { @Override public void sound() { System.out.println("Bark"); } }
|
2. 接口(Interface)
定义:接口是一种纯抽象类型,只能定义方法签名(方法没有具体实现),所有方法默认是public abstract。
使用interface关键字:接口使用interface关键字声明。
继承方式:接口支持多继承(一个类可以实现多个接口),这使得接口比抽象类更加灵活。
成员变量:接口中只能定义public static final的常量,不能有普通成员变量。
默认方法:从 Java 8 开始,接口可以有默认方法(default),这意味着接口可以提供方法的默认实现。
静态方法:从 Java 8 开始,接口中也可以定义静态方法。
适用场景:当你需要定义类的行为,而不需要关注类的实现细节时,适合使用接口。
interface Animal { void sound(); default void sleep() { System.out.println("Sleeping..."); } }
class Dog implements Animal { @Override public void sound() { System.out.println("Bark"); } }
|
具体区别
1. 继承 vs 实现
抽象类通过继承,接口通过实现。
抽象类的继承:
abstract class Animal { public abstract void sound(); }
class Dog extends Animal { @Override public void sound() { System.out.println("Dog barks"); } }
|
接口的实现:
interface Animal { void sound(); }
class Dog implements Animal { @Override public void sound() { System.out.println("Dog barks"); } }
|
区别在于:Dog类通过extends关键字继承抽象类,而通过implements关键字实现接口。
2. 方法实现
抽象类可以有方法的实现,而接口(在 Java 8 之前)只能有方法声明。从 Java 8 开始,接口可以有默认方法。
抽象类的实现:
abstract class Animal { public abstract void sound(); public void eat() { System.out.println("Eating..."); } }
class Dog extends Animal { @Override public void sound() { System.out.println("Dog barks"); } }
|
接口中的默认方法(Java 8+):
interface Animal { void sound();
default void eat() { System.out.println("Eating..."); } }
class Dog implements Animal { @Override public void sound() { System.out.println("Dog barks"); } }
|
区别:抽象类中的eat()方法是可以直接在类中实现的,而接口中的eat()是通过default关键字实现的默认方法。
3. 成员变量
抽象类可以有实例变量,接口只能有public static final常量。
抽象类中的实例变量:
abstract class Animal { String name;
public abstract void sound();
public void printName() { System.out.println("Animal name is " + name); } }
class Dog extends Animal { public Dog(String name) { this.name = name; }
@Override public void sound() { System.out.println("Dog barks"); } }
|
接口中的常量:
interface Animal { String TYPE = "Mammal";
void sound(); }
class Dog implements Animal { @Override public void sound() { System.out.println("Dog barks, Type: " + TYPE); } }
|
区别:抽象类可以有非final的实例变量,而接口中的成员变量默认是public static final,即常量。
4. 构造方法
抽象类可以有构造方法,接口不能有构造方法。
抽象类中的构造方法:
abstract class Animal { String name;
public Animal(String name) { this.name = name; }
public abstract void sound(); }
class Dog extends Animal { public Dog(String name) { super(name); }
@Override public void sound() { System.out.println("Dog barks, Name: " + name); } }
|
接口不能有构造方法:
interface Animal { void sound(); }
|
区别:抽象类可以定义构造方法,用于初始化类的状态,而接口不能定义构造方法,因为接口不能被实例化。