Java 泛型
Java 泛型
泛型(generics),即“参数化类型”,用于编写更通用、类型安全的代码。定义时由参数代替具体的类型,使用时传入具体的类型(即形参不指定类型,由实参指定)。
泛型类型
泛型类
public class Box<T> { private T content; ... } Box<Integer> intBox = new Box<>(123); Box<String> stringBox = new Box<>("Hello, World!");
泛型方法
private Node root; public <K extends Comparable<K>, V> void insert(K key, V value) { root = insert(root, key, value); ... }
泛型接口
interface Generator<T> { T generate(); } class StringGenerator implements Generator<String> { @Override public String generate() { return "Generated String"; } }
泛型参数
<T extends Comparable<T>
Comparable 是指类型 T 必须实现 Comparable 接口,即 T 之间能比较大小(Java 不支持运算符重载,只能通过 Comparable<T> 接口比较两个对象)
<T extends Comparable<? super T>>
实现 Comparable 接口;输入参数可以是 <T> 或其子孙类。
判断泛型类型
public static <T> T t1(Object t1) { log(type(t1)); return (T)t1; } public static <A> A t2(A t1) { log(type(t1)); return t1; } List l1 = new ArrayList<>(); Map<String, String> m1 = new HashMap<>(); m1.put("a","1"); log(t1(l1)); log(t1(m1));
java 伪泛型
Java 和 C++ 都提供了泛型功能,但两者在实现和功能上存在一些关键差异。由于 Java 泛型在某些方面存在限制,因此有时被称为“伪泛型”。
- 擦除类型信息
Java 和 C++ 的一个主要区别在于泛型类型信息的处理方式。在 Java 中,泛型类型参数会在编译过程中被擦除,即替换为其原始类型。例如,List<Integer> 会被擦除为 List。这意味着 Java 泛型在运行时并不知道实际使用的具体类型是什么,这限制了一些泛型功能的实现,例如泛型方法和泛型继承。
C++ 则不会擦除泛型类型信息。这意味着 C++ 泛型在运行时仍然知道实际使用的具体类型,这使得 C++ 泛型可以实现 Java 泛型无法实现的功能,例如泛型方法和泛型继承。
- 泛型实例化
Java 和 C++ 对泛型实例化的支持也存在差异。Java 泛型只能实例化为引用类型,不能实例化为基本类型。这意味着不能创建像 List<int> 这样的泛型实例。C++ 则支持泛型实例化为引用类型和基本类型。
- 类型安全
由于 Java 泛型在运行时并不知道实际使用的具体类型是什么,因此存在潜在的类型安全问题。例如,如果向 List<Integer> 中添加一个 String 对象,则会导致运行时错误。C++ 泛型由于保留了类型信息,因此在类型安全方面具有更好的优势。