泛型 是java中的基础知识,大家学习java的时候都学习过,平时也经常使用,今天在这里总结一下泛型。
1.为什么我们使用泛型呢?两种情况:
第一种:
List list = new ArrayList();
list.add("123");
list.add(123);
for (int i = 0; i < list.size(); i++) {
String a = (String) list.get(i);
}
这段代码,是会报运行时错误的。使用泛型,将这种错误反应在编译时。如下:
第二种:
private void equal(String a,String b){
System.out.print(a.equals(b));
}
private void equal(Integer a,Integer b){
System.out.print(a.equals(b));
}
上面这两个方法,只是参数类型不一样,实现方式一样,造成了代码冗余。用泛型简化如下:
private <T> void equal(T a, T b) {
System.out.print(a.equals(b));
}
2.泛型的使用
泛型的一般有三种使用情况:泛型类,泛型接口,泛型方法。
(1)泛型类:
(2)泛型接口:
interface test1<T> {
abstract void aa(T a);
}
(3)泛型方法
注意: 1.第一个不属于泛型方法,他只是使用了泛型的方法;第二个才是。
2. 上图泛型方法的泛型申明和类中一样,都是T。但是两个不是一个泛型对象,和形参一样(局部变量和成员变量名字一 样时,方法中的该变量和成员变量不是一个)。
3. 泛型的继承
public class Test1<T extends Node&test1> {
}
如上,我们需要约束泛型使用的时候(比如:希望这个泛型使用只能时Node或者时Node的子类时)我们可以如上约束。
注意:1.约束条件中只能有一个父类约束;
2. 约束条件中可以有无数接口约束;
3. 如果既有父类约束又有接口约束时,父类约束写第一个。
4. 通配符
public void fanxin() {
//Nodevos 继承 Node
List<Node> a = new ArrayList<>();
List<Nodevos> b = new ArrayList<>();
setHa(a);
setHa(b);//编译出错
}
private void setHa(List<Node> ha) {
return;
}
如上代码,虽然Nodevos继承Node,但是List<Node>和List<Nodevos>属于一个类的对象,不是继承关系。我们可以验证一下:
//Nodevos 继承 Node
List<Node> a = new ArrayList<>();
List<Nodevos> b = new ArrayList<>();
System.out.println(a.getClass());
System.out.print(b.getClass());
这是输出:
class java.util.ArrayList
class java.util.ArrayList
那这种情况怎么办呢?我们使用通配符,代码如下:
public void fanxin() {
//Nodevos 继承 Node
List<Node> a = new ArrayList<>();
List<Nodevos> b = new ArrayList<>();
setHa(a);
setHa(b);
}
private void setHa(List<? extends Node> ha) {
return;
}
通配符的两种情况:
上界通配符 < ? extends E>
下界通配符 < ? super E>
5.小知识:
(1):泛型名称可以是任意字母,一般大家会选择一个容易懂的字符:
T:表示一个具体的java类型;
K: key值,V value值;