T 是类型参数,通常使用 T、E、K、V 等字母来表示不同类型。
使用时,必须指定 T 的具体类型,例如:Box box = new Box<>();
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
/*注意标记符只是起一个提示作用并不代表你写了E就只能传入集合类型,这些字母其实可以自己定义。
所有字母的作用都是一样的代表不确定类型*/
//比如
public static void main(String[] args) {
add(1);
add("2");
add(new int[]{1, 2, 3});
}
public static void add(A a) {
System.out.println(a);
}
public class Box {
private T item;
public void set(T item) {
this.item = item;
}
public T get() {
return item;
}
}
public class Main {
public static void main(String[] args) {
Box integerBox = new Box<>();
integerBox.set(10);
System.out.println(integerBox.get()); // 输出: 10
Box stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get()); // 输出: Hello
}
}
public interface Container {
void add(T item);
T get(int index);
}
public class ArrayListContainer implements Container {
private List list = new ArrayList<>();
@Override
public void add(T item) {
list.add(item);
}
@Override
public T get(int index) {
return list.get(index);
}
}
public class Main {
public static void main(String[] args) {
Container container = new ArrayListContainer<>();
container.add("Hello");
container.add("World");
System.out.println(container.get(0)); // 输出: Hello
System.out.println(container.get(1)); // 输出: World
}
}
public class Util {
public static void printArray(T[] array) {
for (T item : array) {
System.out.println(item);
}
}
}
public class Main {
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3};
Util.printArray(intArray); // 输出: 1, 2, 3
String[] stringArray = {"Hello", "World"};
Util.printArray(stringArray); // 输出: Hello, World
}
}
定义:表示类型参数是某个特定类型的子类型。
用途:用于限制泛型参数的类型范围,确保类型安全。
public class Test {
//限制T的类型必须是继承自Number类型的,所以我们传入的类型只能是Number的子类,
//及java中值类型所对应的引用类型 int->Integer
public static void printList(List list) {
for (Number num : list) {
System.out.println(num);
}
}
public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
printList(intList); // 输出: 1, 2, 3
List doubleList = Arrays.asList(1.1, 2.2, 3.3);
printList(doubleList); // 输出: 1.1, 2.2, 3.3
}
}
错误写法
public static void printList(List list) {
for (Number num : list) {
System.out.println(num);
}
}
public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
printList(intList); // 输出: 1, 2, 3
List doubleList = Arrays.asList(1.1, 2.2, 3.3);
printList(doubleList); // 输出: 1.1, 2.2, 3.3
}
/*
在Java中,泛型的类型参数不能使用super关键字来定义下界。正确的语法是使用extends关键字来定义上界,或者在方法参数中使用通配符加上super关键字来定义下界。
我们的代码尝试定义了一个泛型方法addNumbers,该方法接受一个列表参数,列表中的元素类型为T,并且T应该是Integer的超类型(即可以是Integer本身或它的父类)
但是,这种写法是不正确的。如果你想表达这个意思,应该使用通配符? super Integer来代替。
*/
对于下界(lower bound)的定义,Java 泛型只支持使用通配符 ? super
来表示。具体来说,? super T
表示类型 T
及其所有父类型。
表示未知类型,适用于参数未知的通用集合。
java复制代码public static void printList(List> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
所以下界的正确写法为
public static void addNumbers(List super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
public static void main(String[] args) {
List intList = new ArrayList<>();
addNumbers(intList); // 向intList中添加1, 2, 3
List numberList = new ArrayList<>();
addNumbers(numberList); // 向numberList中添加1, 2, 3
List
上界通配符写法
public static void printList(List extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
}
public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
printList(intList); // 输出: 1, 2, 3
List doubleList = Arrays.asList(1.1, 2.2, 3.3);
printList(doubleList); // 输出: 1.1, 2.2, 3.3
}
类型擦除:Java 编译器会在编译时将泛型参数擦除为 Object
或其边界类型。
编译后的class文件代码
public static void printList(List list) {
Iterator var1 = list.iterator();
while(var1.hasNext()) {
Number num = (Number)var1.next();//将T类型擦除为Number类型
System.out.println(num);
}
}
public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
printList(intList);
List doubleList = Arrays.asList(1.1, 2.2, 3.3);
printList(doubleList);
}
类型擦除的限制:
T obj = new T();
)。instanceof
检测泛型类型。T[] array = new T[10];
)。List
、Map
等,提升了集合的类型安全性。Optional
和 Future
等,用于特定类型的操作。