对于泛型的设计思路

前面了解到,

java基础代码

其实也就是处理一堆数据。

那其实有个bug。

就是,只能传类型确定的数据

我们在写一段代码的时候。

如果想传递和接受,不确定类型的数据,应该怎么办

于是发明了泛型这个概念。

你理解得很准!泛型(Generics) 就是为了解决"代码写死类型、无法复用"这个问题而生的。

痛点演示:没有泛型时怎么办?

你想写一个打印任意类型数组的方法:

java 复制代码
// 只能打印String数组
public static void printString(String[] arr) { ... }

// 只能打印Integer数组
public static void printInteger(Integer[] arr) { ... }

// 只能打印Double数组 → 还得再写一个... 无穷无尽

有人会说:用 Object 不就行了?

java 复制代码
public static void print(Object[] arr) {
    for (Object o : arr) {
        System.out.println(o);
    }
}

但有问题

  • ❌ 取出元素必须强制转型 ,容易 ClassCastException
  • ❌ 编译期不检查类型,错误推迟到运行期
  • ❌ 没有"这个数组里只能是同一种类型"的约束

泛型解决方案

把类型也当作一个"参数"传进去 ,用 <T> 表示:

java 复制代码
// T 代表"待定的类型"
public static <T> void print(T[] arr) {
    for (T t : arr) {
        System.out.println(t);
    }
}

// 使用时,自动推导类型
String[] strs = {"a", "b"};
Integer[] nums = {1, 2, 3};

print(strs);  // 编译器理解为 print<String>
print(nums);  // 编译器理解为 print<Integer>

对比效果

用 Object 用泛型
编译时类型检查 ❌ 无 ✅ 有
取出元素需强转 ✅ 需要 ❌ 不需要
代码复用度 一般
类型安全

泛型最经典的例子:集合类

java 复制代码
// 没有泛型时(旧代码),一个篮子啥都能装
List list = new ArrayList();
list.add("hello");
list.add(123);          // 混入不同类型
String s = (String) list.get(0); // 强转,第2个元素取出来就报错

// 有泛型后,明确约束
List<String> list2 = new ArrayList<>();
list2.add("hello");
// list2.add(123);      // 编译错误!类型不匹配
String s2 = list2.get(0); // 无需强转

泛型的核心概念

1. 泛型类/接口

java 复制代码
class Box<T> {
    private T content;
    public void set(T t) { content = t; }
    public T get() { return content; }
}

Box<String> box = new Box<>();  // 这里的String是"类型实参"

2. 泛型方法(刚才展示的)

3. 类型通配符 ?

当你不确定具体类型,只想表达"某种类型"时:

java 复制代码
public void printList(List<?> list) {  // 可以接收 List<String> / List<Integer> ...
    for (Object o : list) System.out.println(o);
}

4. 上限 extends / 下限 super

java 复制代码
// 只允许 Number 及其子类
List<? extends Number> nums;

// 只允许 Integer 及其父类
List<? super Integer> ints;

一个更贴近你之前"数据处理"的例子

假设你要写一个"数据处理器",处理不同类型的数值:

java 复制代码
// 泛型接口
interface Processor<T> {
    T process(T input);
}

// String 处理器
class StringReverse implements Processor<String> {
    public String process(String s) {
        return new StringBuilder(s).reverse().toString();
    }
}

// Integer 处理器
class IntegerDouble implements Processor<Integer> {
    public Integer process(Integer n) {
        return n * 2;
    }
}

// 使用
Processor<String> p1 = new StringReverse();
String result = p1.process("abc");  // "cba"

泛型在 Java 中的"小缺点"(相对于 C++ 模板)

类型擦除:泛型只在编译期检查,运行时会擦掉类型信息。

java 复制代码
List<String> list1 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();

// 下面这行会输出 true,因为运行时都是 ArrayList
System.out.println(list1.getClass() == list2.getClass());

为什么?为了兼容旧版本 Java(1.4 之前没有泛型)。


总结

你的问题 泛型的答案
只能传类型确定的数据 <T> 把类型参数化
代码写死类型 类型变成可传入的"参数"
需要强制转型 编译期自动补上,类型安全

一句话记忆:泛型 = 类型的参数化,让你写出"处理任意类型数据的通用代码",同时保留编译时的类型检查。

相关推荐
A_aspectJ2 小时前
【Java基础开发】基于 Java Swing 开发的简易计算器 - 支持键盘
java·开发语言
2501_913061342 小时前
网络原理知识(7)
java·网络·面试
南境十里·墨染春水2 小时前
linux学习进程 线程同步——读写锁
java·jvm·学习
ZWZhangYu2 小时前
MCP 实战:从协议原理到 Java 自定义工具服务落地
java·开发语言·人工智能
Flittly2 小时前
【SpringSecurity新手村系列】(5)RBAC角色权限与账户状态校验
java·spring boot·笔记·安全·spring·ai
笨蛋不要掉眼泪2 小时前
面试篇-java基础下
java·后端·面试·职场和发展
wechatbot8882 小时前
企业微信 iPad 协议客服机器人自动化管理平台开发指南
java·运维·微信·自动化·企业微信·ipad
weisian1512 小时前
Java并发编程--46-热点Key与大Value:Redis集群中的“定时炸弹”
java·redis·热key·大key
Go away, devil2 小时前
Java——IO
java·开发语言