上次我们聊了 Java 面向对象的三大特性,封装、继承、多态。 今天我们来聊聊 实现、泛型。
一、实现(implements)
定义: "实现" 是 Java 中类与接口(Interface) 之间的关系,关键字是 implements。接口是一组 "行为规范" (只定义方法签名,不包含具体实现),而实现类需要兑现这些规范,即编写接口中所有抽象方法的具体逻辑。
类比: 接口 = 一份 "合同"(比如 Runnable 接口规定 "必须有 run () 方法"),实现类 = 签约方(比如 MyThread 类实现 Runnable,必须写 run () 的具体代码,兑现合同)。
作用:
- 弥补 Java 单继承的不足:一个类只能继承 1 个父类,但 可以实现多个接口(比如class A extends B implements C, D),实现 "多继承" 的效果;
- 定义行为标准:接口封装 "能做什么",实现类负责 "怎么做",解耦行为规范和具体实现;
- 接口多态的核心基础。
示例代码:
// 1. 定义接口:封装行为规范(只有方法签名,无实现)
public interface AnimalBehavior {
// 抽象方法:无方法体
void eat();
void move();
// 默认方法(JDK8+):有默认实现,实现类可重写
default void breathe() {
System.out.println("动物呼吸空气");
}
}
// 2. 实现类:必须实现接口的所有抽象方法
public class Dog1 implements AnimalBehavior {
@Override
public void eat() {
System.out.println("狗啃骨头");
}
@Override
public void move() {
System.out.println("狗跑");
}
// 可选:重写接口的默认方法
@Override
public void breathe() {
System.out.println("狗用鼻子呼吸");
}
public static void main(String[] args) {
Dog1 dog1 = new Dog1();
dog1.eat(); // 输出:狗啃骨头
dog1.move(); // 输出:狗跑
dog1.breathe();// 输出:狗用鼻子呼吸
}
}
二、泛型(Generics)
定义:参数化类型 —— 允许在定义类、接口、方法时使用 "类型参数",编译时指定具体类型,从而实现类型安全和代码复用。
类比: 快递箱(泛型类)可以装任何物品(类型参数),你在使用时指定装 "书籍"(String)或 "电子产品"(Integer),箱子就只接受对应类型,避免装错。
作用:
- 类型安全:编译时检查类型,避免运行时 ClassCastException(强制类型转换异常);
- 代码复用:一套代码支持多种类型,无需为不同类型重复编写;
- 消除冗余的强制类型转换。
泛型类 示例:
// 自定义泛型类:Box<T>,T是类型参数(可以任意命名,常用T/E/K/V)
public class Box<T> {
private T content;
// 泛型方法:设置内容
public void setContent(T content) {
this.content = content;
}
// 泛型方法:获取内容
public T getContent() {
return content;
}
// 测试泛型类
public static void main(String[] args) {
// 1. 指定T为String类型
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello 泛型");
String str = stringBox.getContent(); // 无需强制转换
System.out.println(str); // 输出:Hello 泛型
// 2. 指定T为Integer类型
Box<Integer> integerBox = new Box<>();
integerBox.setContent(100);
Integer num = integerBox.getContent();
System.out.println(num); // 输出:100
// 3. 类型安全:编译时检查,避免装错类型
// stringBox.setContent(100); // 编译错误:不能将Integer赋值给String类型的Box
}
}
泛型方法(独立于类的泛型) 示例:
public class GenericMethodDemo {
// 泛型方法:<T>是方法的类型参数,T[]是参数类型,T是返回类型
public static <T> T getFirstElement(T[] array) {
if (array == null || array.length == 0) {
return null;
}
return array[0];
}
public static void main(String[] args) {
String[] strArray = {"Java", "泛型", "教程"};
Integer[] intArray = {1, 2, 3, 4};
// 调用泛型方法,自动推断类型
String firstStr = getFirstElement(strArray);
Integer firstInt = getFirstElement(intArray);
System.out.println(firstStr); // 输出:Java
System.out.println(firstInt); // 输出:1
}
}
泛型通配符(<?>、<? extends T>、<? super T>) 示例:
// 父类:抽象的"动物"
public class Animal {
// 父类属性
protected String name; // protected:子类可直接访问
// 父类构造方法
public Animal(String name) {
this.name = name;
}
// 父类方法
public void eat() {
System.out.println(name + "在吃食物");
}
// 父类方法
public void sleep() {
System.out.println(name + "在睡觉");
}
}
// 子类:Dog2(继承Animal)
public class Dog2 extends Animal {
// 子类特有属性
private String breed; // 品种
// 子类构造方法:必须通过super调用父类构造
public Dog2(String name, String breed) {
super(name); // 调用父类的构造方法
this.breed = breed;
}
// 重写(Override)父类方法:扩展/修改父类行为
@Override
public void eat() {
System.out.println(name + "(" + breed + ")在啃骨头");
}
// 子类特有方法:扩展父类功能
public void bark() {
System.out.println(name + "在汪汪叫");
}
}
// 子类:Cat(继承Animal)
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
// 重写eat方法
@Override
public void eat() {
System.out.println(name + "在吃小鱼干");
}
// 子类特有方法
public void meow() {
System.out.println(name + "在喵喵叫");
}
}
public class GenericWildcardDemo {
// 通配符<?>:表示任意类型(只读,不能添加元素)
public static void printList(List<?> list) {
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
// 上限通配符<? extends Animal>:只能是Animal或其子类
public static void feedAnimals(List<? extends Animal> animals) {
for (Animal animal : animals) {
animal.eat();
}
}
// 下限通配符<? super Dog2>:只能是Dog2或其父类
public static void addDog(List<? super Dog2> list) {
list.add(new Dog2("旺财", "金毛")); // 可以添加Dog或其子类
}
public static void main(String[] args) {
List<Dog2> dogs = new ArrayList<>();
dogs.add(new Dog2("旺财", "金毛"));
List<Cat> cats = new ArrayList<>();
cats.add(new Cat("咪宝"));
// 通配符<?>
printList(dogs); // 输出:Dog2@6f496d9f - 旺财
printList(cats); // 输出:Cat@723279cf - 咪宝
// 上限通配符<? extends Animal>
feedAnimals(dogs); // 输出:旺财(金毛)在啃骨头
feedAnimals(cats); // 输出:咪宝在吃小鱼干
// 下限通配符<? super Dog>
List<Animal> animals = new ArrayList<>();
addDog(animals);
System.out.println(animals.size()); // 输出:1
}
}
说明:
- 泛型擦除:Java 的泛型是 "编译时泛型",运行时会擦除类型参数(比如 Box 运行时变成 Box ),目的是兼容旧代码;
- 泛型上限:<? extends T> 表示只能是 T 或其子类(读操作安全);
- 泛型下限:<? super T> 表示只能是 T 或其父类(写操作安全);
- 不能用基本类型作为泛型参数:比如 Box 错误,需用包装类 Box。
- 实现 是类对接口行为规范的 "兑现",核心作用是弥补单继承不足、定义行为标准,是接口多态的基础;
- 泛型 是参数化类型,编译时检查类型安全,消除强制转换,核心是类型参数(T/E 等),实现代码复用。
总结:
成功者的目标,不是让别人相信自己是对的,而是弄明白谁是对的。-- 烟沙九洲