深入解析抽象类与接口
抽象类的规则:
- 抽象方法没有方法体(只声明,不实现,具体的实现由继承他的子类来完成)
- 抽象方法不能被实例化
- 抽象方法不能是private的,因为就不能被继承了
- 抽象类中可以包含其他非抽象方法,也可以包含字段(非抽象方法和普通方法的规则一样,可以被重写,也可以被子类调用)
接口的规则
- 接口是抽象类的更进一步,抽象类中还可以包含非抽象方法和字段,但是接口中只有抽象方法(接口中现在还可以有默认方法(
default
)和静态方法(static
)以及私有方法(private
)),字段只能是静态常量(默认public static final
) - 一个类通过继承接口的方式,从而继承接口的抽象方法
- 使用
interface
定义一个接口,使用implements
实现一个接口 - 接口中的方法一定是
public
的 - 接口不能被单独实例化
- Java不可以多继承,但是可以实现多个接口
- 接口可以继承自另一个接口,使用extends关键字,达到复用的效果
抽象类和接口的对比
抽象类是用来捕捉子类的通用特性的.接口时抽象方法的集合.
从设计层面来说,抽象类是对类的抽象,是一种模板设计,接口时行为的抽象,是一种行为的规范.
接口中变量默认是public static final
的,方法默认是public abstract
的
相同点:
- 接口和抽象类都不能实例化
- 都位于继承的顶端,用于被其他类实现或继承
- 都包含抽象方法,其子类都必须实现这些抽象方法
不同点
参数 | 抽象类 | 接口 |
---|---|---|
声明 | abstract | interface |
实现 | 子类使用extends 关键字来继承抽象类.如果子类不是抽象类的话,它需要实现抽象类中的所有的声明方法 | 子类使用implements关键字来实现接口.它需要提供接口中所有声明方法的实现 |
构造器 | 抽象类可以有构造器 | 接口不能有构造器 |
访问修饰符 | 抽象类中的方法可以是任意访问修饰符 | 接口中方法默认修饰符是public ,并且不允许定义为private 或protected |
多继承 | 一个类最多只能继承一个抽象类 | 一个类可以实现多个接口 |
字段声明 | 抽象类的字段声明可以是任意的 | 接口的字段默认都是public static fianl 的 |
实例化的方法 | 通过子类或你匿名内部类 | 通过实现类或匿名内部类 |
设计目的 | 定义部分实现(是什么 和能做什么 ) | 定义行为规范(能做什么 ) |
普通类和抽象类有哪些区别?
- 普通类不能包含抽象方法,抽象类可以包含抽象方法
- 抽象类不能直接实例化,普通类可以直接实例化
抽象类能使用final修饰吗?
不能,定义抽象类就是让其他类继承的,如果定义为final
该类就不能被继承,这样彼此就会产生矛盾,所有final
不能修饰抽象类
接口中可以定义哪些方法?
- 抽象方法:抽象方法是接口的核心部分,所有实现接口的类都必须实现这些方法,抽象方法默认是
public
和abstract
的,这些修饰符可以省略.
public interface Animal {
void makeSound();
}
- 默认方法:默认方法是在
Java8
中引入的,允许接口提供具体实现.实现类可以选择重写默认方法
public interface Animal {
void makeSound();
default void sleep() {
System.out.println("Sleeping...");
}
}
- 静态方法:静态方法也是在
Java8
中引入的,它们属于接口本身,可以通过接口名直接调用,而不需要实现类的对象
public interfaca Animal {
void makeSound();
static void staticMethod(){
System.out.println("Static method in interface");
}
}
- 私有方法:私有方法是在
Java9
中引入的,用于在接口中为默认方法或其他私有方法提供辅助功能.这些方法不能被实现类访问,只能在接口内部使用
public interface Animal{
void makeSound();
default void sleep(){
System.out.println("Sleep...");
logSleep();
}
private void logSleep(){
System.out.println("Logging sleep");
}
}
抽象类和接口可以被实例化吗?
在Java中,接口和抽象类都不能直接实例化.因为他们都不是完整的类型(缺少具体实现)
这意味着不能使用new
关键字直接创建一个抽象类的对象,但是可以通过以下方式间接实例化他们:
接口的实例化
-
通过实现类实例化接口
-
定义一个实现类,实现接口中的所有方法
-
然后通过实现类实例化接口
// 定义接口
interface Animal {
void makeSound();
}
// 定义实现类
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("The dog barks: Woof! Woof!");
}
}
// 测试类
public class Main {
public static void main(String[] args) {
// 通过实现类实例化接口
Animal dog = new Dog();
dog.makeSound(); // 输出: The dog barks: Woof! Woof!
}
}
- 通过匿名内部类实例化接口
- 使用匿名内部类世界实现接口,并实例化接口
// 定义接口
interface Animal {
void makeSound();
}
// 测试类
public class Main {
public static void main(String[] args) {
// 通过匿名内部类实例化接口
Animal dog = new Animal() {
@Override
public void makeSound() {
System.out.println("The dog barks: Woof! Woof!");
}
};
dog.makeSound(); // 输出: The dog barks: Woof! Woof!
}
}
抽象类的实例化
- 通过子类实例化抽象类
- 定义一个子类,继承抽象类并实现所有抽象方法
- 然后通过子类实例化抽象类
// 定义抽象类
abstract class Animal {
// 抽象方法
public abstract void makeSound();
// 普通方法
public void sleep() {
System.out.println("This animal is sleeping.");
}
}
// 定义子类
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("The dog barks: Woof! Woof!");
}
}
// 测试类
public class Main {
public static void main(String[] args) {
// 通过子类实例化抽象类
Animal dog = new Dog();
dog.makeSound(); // 输出: The dog barks: Woof! Woof!
dog.sleep(); // 输出: This animal is sleeping.
}
}
- 通过匿名内部类实例化抽象类
- 使用匿名内部类直接继承抽象类,并实现所有抽象方法
// 定义抽象类
abstract class Animal {
// 抽象方法
public abstract void makeSound();
// 普通方法
public void sleep() {
System.out.println("This animal is sleeping.");
}
}
// 测试类
public class Main {
public static void main(String[] args) {
// 通过匿名内部类实例化抽象类
Animal dog = new Animal() {
@Override
public void makeSound() {
System.out.println("The dog barks: Woof! Woof!");
}
};
dog.makeSound(); // 输出: The dog barks: Woof! Woof!
dog.sleep(); // 输出: This animal is sleeping.
}
}