1 泛型定义
数据类型的参数化
2 泛型类
类中的参数类型由外部决定。
实现:在类后边加<T>
泛型类
public class Node<T> {
private T data;
public Node() {
}
public Node(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
泛型类调用
@Test
public void testNode() {
Node<Integer> intNode = new Node<>(1);
Node<String> strNode2 = new Node<>("str");
System.out.println(intNode.getData());
System.out.println(strNode2.getData());
}
3 泛型接口
和泛型类一样。
4 泛型通配符
同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
我们知道Ingeter
是Number
的一个子类,同时在特性章节中我们也验证过Generic<Ingeter>
与Generic<Number>
实际上是相同的一种基本类型。那么问题来了,在使用Generic<Number>
作为形参的方法中,能否使用Generic<Ingeter>
的实例传入呢?在逻辑上类似于Generic<Number>
和Generic<Ingeter>
是否可以看成具有父子关系的泛型类型呢?
为了弄清楚这个问题,我们使用Generic<T>
这个泛型类继续看下面的例子:
//静态函数的参数为泛型类Node,并且泛型类中的参数类型为Number
public static void getData(Node<Number> node) {
System.out.println(node.getData());
}
//n2的数据类型为Integer,n2作为参数调用getData()会报错
@Test
public void test3() {
Node<Number> n1 = new Node<>(1);
Node<Integer> n2 = new Node<>(1);
getData2(n2);
}
如何解决上面的问题?总不能为了定义一个新的方法来处理Generic<Integer>
类型的类,这显然与java中的多台理念相违背。因此我们需要一个在逻辑上可以表示同时是Generic<Integer>
和Generic<Number>
父类的引用类型。由此类型通配符应运而生。
public static void getData2(Node<?> node) {
// 通配符不知道是哪种类型了,无法对参数进行修改
// node.setData(20);
System.out.println(node.getData());
}
“?”表示可以接收任意的泛型类型,但是只是接收输出,并不能修改。因为?不能确定到底是什么类型,因此,没法对类中的参数进行修改。类型通配符一般是使用?代替具体的类型实参,注意了,此处’?’是类型实参,而不是类型形参 。可以把通配符理解成接口,可以被不同的对象实现。
4.1 泛型通配符的上限和下限
上限:只能设置其具体的类和子类。例如。现在最大的上限设置为”Number”类型,那么泛型的上限通过以下语法完成:
//? extends 类
Public static void getUpperNumberData(Node<? extends Number>node){
System.out.println(node.getData());
}
下限:只能设置其具体的类和父类。设置语法如下
Public static void getLowerNumberData(Node<? super Integer>node){
System.out.println(node.getData());
}
5 泛型的嵌套
泛型里面再嵌套一个泛型。
Map.Entry :Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
map.entrySet:返回一个Map.Entry的集合
Set<T>:集合泛型
public void test5() {
Map<Integer, String> map = new HashMap<>();
map.put(1, "vince");
map.put(2, "tom");
Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
for (Map.Entry<Integer, String> entry : entrySet) {
System.out.println(entry.getKey() + ":" + entry.getValue());
}
}
Set<T>:是一个泛型,这test5中T为Map.Entry。同时,Map.Entry<K,V>也是泛型,K,V的类型分别为Integer,String