刚学Java时,不少人靠Object类型“通吃”所有数据,结果要么频繁强转报错,要么代码乱糟糟——而泛型就是解决这问题的“类型安全神器”。今天用3个实战案例,带你搞懂泛型的核心用法,告别“万能Object”的尴尬。
一、泛型最常用:给集合“上锁”
没泛型的集合像个“杂货铺”,能塞任何类型数据,取的时候还得手动强转,一不小心就抛ClassCastException。
// 没有泛型的坑
List list = new ArrayList();
list.add("Java");
list.add(123); // 能存整数,编译不报错
String str = (String) list.get(1); // 运行时崩溃:Integer不能转String
// 有泛型的安全感
List strList = new ArrayList<>();
strList.add("Java");
// strList.add(123); // 编译直接报错,类型不匹配
String name = strList.get(0); // 无需强转,直接拿String
泛型让集合变成“专属货架”,编译期就校验类型,从根源杜绝类型转换错误。
二、自定义泛型类:一个类搞定所有类型
想写个通用容器(比如装字符串、整数、自定义对象),不用重复写多个类,泛型类一键搞定。
// 泛型类:T是类型占位符,使用时指定具体类型
public class Box {
private T content; // 泛型成员变量
// 泛型方法存数据
public void setContent(T content) {
this.content = content;
}
// 泛型方法取数据
public T getContent() {
return content;
}
}
// 测试:支持不同类型
public class BoxTest {
public static void main(String[] args) {
// 装字符串
Box strBox = new Box<>();
strBox.setContent("泛型真好用");
System.out.println(strBox.getContent()); // 输出:泛型真好用
// 装整数
Box intBox = new Box<>();
intBox.setContent(666);
System.out.println(intBox.getContent()); // 输出:666
}
}
三、泛型通配符:灵活适配多种类型
用 ? 通配符实现“类型兼容”,比如写一个方法能处理所有数字类型(Integer、Double)的集合,不用写多个重载方法。
public class GenericUtils {
// 上界通配符:? extends Number 表示只能是Number的子类
public static double sum(List list) {
double total = 0;
for (Number num : list) {
total += num.doubleValue(); // 所有数字都能转double
}
return total;
}
}
// 测试
public class WildcardTest {
public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
List doubleList = Arrays.asList(1.5, 2.5);
System.out.println(GenericUtils.sum(intList)); // 6.0
System.out.println(GenericUtils.sum(doubleList)); // 4.0
}
}
关键原则:读取数据用extends(生产者),写入数据用super(消费者),记好这波“PECS原则”,通配符用法不踩坑。
四、避坑小技巧
1. 泛型不能用基本类型(如List),要用水包装类(List);
2. 泛型在编译时会“类型擦除”,运行时不存在List和List的区别;
3. 泛型参数不能用于静态成员(比如static T value; 编译报错)。
总结
泛型的核心是“类型参数化”,既能保证类型安全,又能减少重复代码。学会集合泛型、自定义泛型类和通配符,你的Java代码会更简洁、更稳健,再也不用靠Object“硬扛”啦~