一、抽象类(Abstract Class)
1. 核心概念
- 抽象类是用
abstract
关键字修饰的类,不能被实例化,只能被继承。 - 可以包含抽象方法(没有方法体的方法)和具体方法。
- 作用:定义模板,强制子类实现抽象方法,实现代码复用。
2. 特点
- 若类包含至少一个抽象方法,则类必须声明为抽象类。
- 抽象类可以有构造方法(用于初始化子类对象)。
- 子类必须实现抽象类中的所有抽象方法(除非子类也是抽象类)。
3. 示例
java 复制 // 抽象类:动物 public abstract class Animal { private String name; // 抽象方法:子类必须实现 public abstract void makeSound(); // 具体方法:子类可直接使用或重写 public void sleep() { System.out.println(name + "在睡觉"); } public Animal(String name) { this.name = name; } public String getName() { return name; } } // 子类继承抽象类 public class Dog extends Animal { public Dog(String name) { super(name); } @Override public void makeSound() { System.out.println(getName() + ":汪汪!"); } } // 使用抽象类 public class Main { public static void main(String[] args) { Animal dog = new Dog("旺财"); dog.makeSound(); // 输出:旺财:汪汪! dog.sleep(); // 输出:旺财在睡觉 } }
二、接口(Interface)
1. 核心概念
- 接口是使用
interface
关键字定义的纯抽象类型,不能包含具体方法(Java 8+ 支持默认方法)。 - 类通过
implements
关键字实现接口,一个类可以实现多个接口(支持多继承)。 - 作用:定义行为规范,实现解耦和多态。
2. 特点
- 接口中的方法默认是
public abstract
,变量默认是public static final
。 - Java 8 开始支持默认方法(
default
方法)和静态方法。 - Java 9 开始支持私有方法。
3. 示例
java
复制
// 接口:飞行能力
public interface Flyable {
// 抽象方法
void fly();
// 默认方法(Java 8+)
default void land() {
System.out.println("降落");
}
// 静态方法(Java 8+)
static void showInfo() {
System.out.println("这是飞行能力接口");
}
}
// 实现接口的类
public class Bird implements Flyable {
@Override
public void fly() {
System.out.println("鸟在飞翔");
}
}
// 使用接口
public class Main {
public static void main(String[] args) {
Bird bird = new Bird();
bird.fly(); // 输出:鸟在飞翔
bird.land(); // 输出:降落(来自接口默认方法)
Flyable.showInfo(); // 输出:这是飞行能力接口
}
}
三、内部类(Inner Class)
1. 核心概念
- 内部类是定义在另一个类内部的类,可以访问外部类的所有成员(包括私有成员)。
- 分类:
- 静态内部类:用
static
修饰,不依赖外部类实例。 - 非静态内部类:默认类型,依赖外部类实例。
- 匿名内部类:没有类名的内部类,通常用于实现接口或继承抽象类。
- 静态内部类:用
2. 静态内部类(Static Inner Class)
- 通过外部类名访问,只能访问外部类的静态成员。
- 示例:
java
复制
public class Outer { private static String staticMsg = "外部类静态成员"; // 静态内部类 public static class StaticInner { public void print() { System.out.println(staticMsg); // 访问外部类静态成员 } } } // 使用静态内部类 public class Main { public static void main(String[] args) { Outer.StaticInner inner = new Outer.StaticInner(); inner.print(); // 输出:外部类静态成员 } }
3. 匿名内部类(Anonymous Inner Class)
- 没有类名的内部类,直接在代码中实现接口或继承抽象类。
- 适用场景:快速实现一次性使用的类。
- 示例:
java
复制
public interface Greeting { void sayHello(); } public class Main { public static void main(String[] args) { // 匿名内部类实现接口 Greeting greeting = new Greeting() { @Override public void sayHello() { System.out.println("你好,世界!"); } }; greeting.sayHello(); // 输出:你好,世界! } }
四、抽象类 vs 接口
特性 | 抽象类 | 接口 |
---|---|---|
定义 | 用 abstract 修饰的类 |
用 interface 修饰的类型 |
方法实现 | 可以包含具体方法和抽象方法 | Java 8+ 支持默认方法和静态方法 |
多继承 | 单继承(一个类只能继承一个抽象类) | 多实现(一个类可实现多个接口) |
设计目的 | 提取类的共性(is-a关系) | 定义行为规范(can-do关系) |
构造方法 | 可以有构造方法 | 不能有构造方法 |
五、内部类总结
类型 | 特点 | 示例场景 |
---|---|---|
静态内部类 | 不依赖外部类实例,只能访问外部类静态成员 | 工具类、Builder模式 |
非静态内部类 | 依赖外部类实例,可访问外部类所有成员 | 事件监听、数据封装 |
匿名内部类 | 没有类名,直接实现接口或继承抽象类 | 快速实现回调、临时逻辑 |
六、综合示例
java
复制
// 抽象类与接口结合使用 public abstract class Shape { public abstract double area(); } public interface Drawable { void draw(); } // 静态内部类实现接口 public class Circle extends Shape { private double radius; public Circle(double radius) { this.radius = radius; } @Override public double area() { return Math.PI * radius * radius; } // 静态内部类实现Drawable接口 public static class Drawer implements Drawable { private Circle circle; public Drawer(Circle circle) { this.circle = circle; } @Override public void draw() { System.out.println("绘制半径为" + circle.radius + "的圆"); } } } // 匿名内部类实现接口 public class Main { public static void main(String[] args) { Circle circle = new Circle(5); Drawable drawer = new Circle.Drawer(circle); // 静态内部类 drawer.draw(); // 输出:绘制半径为5的圆 // 匿名内部类直接实现Drawable Drawable anonymousDrawer = new Drawable() { @Override public void draw() { System.out.println("匿名内部类绘制操作"); } }; anonymousDrawer.draw(); } }
总结
- 抽象类:适合定义共性模板,强制子类实现特定行为。
- 接口:适合定义行为规范,支持多继承和解耦。
- 内部类:用于逻辑封装,静态内部类独立于外部类,匿名内部类简化代码。