所谓泛型,实质上就是不使用具体数据类型(int、double、float 等),而是使用一种通用类型(T、K、V、E 等)来进行程序设计的方法,该方法可以避免因为程序中数据类型的不同,而被迫重复编写大量相同业务逻辑的代码。
一个简单的泛型类
public class Pair<T> {
private T first;
private T second;
public Pair(){}
public Pair(T first, T second){
this.first = first;
this.second = second;
}
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getSecond() {
return second;
}
public void setSecond(T second) {
this.second = second;
}
}
定义一个泛型方法
public class ObjFactory {
public static <T> T getObj(Class<T> clazz) throws Exception {
return clazz.newInstance();
}
}
有些时候,类或方法需要对类型变量加以约束。如下面的例子:
public static <T extends Comparable> T min(T... arr){
if (arr == null || arr.length == 0) return null;
T min = arr[0];
for (int i = 1; i < arr.length; i++){
if(min.compareTo(arr[i]) > 0){
min = arr[i];
}
}
return min;
}
注意min方法的代码内部。变量min类型为T, 这意味着它可以是任何一个类的对象。怎么才能确保T所属的类有compareTo方法呢?
解决这个问题的方案是将T限制为实现了Comparable接口(只含一个方法compareTo的标准接口)的类。可以通过对类型变量T设置限定(bound) 实现这一点:
public static <T extends Comparable> T min(T... arr)
虚拟机中没有泛型类型对象——所有的对象都属于普通类。
无论在何时定义了一个泛型类型,都会自动提供一个相应的原始类型(raw type)。
原始类型的名字就是删去类型参数后的泛型类型名,擦除(eerased)类型变量,并替换为限定类型(无限定类型的变量用Object替换)。
例如上面的泛型类Pair的原始类型如下:
//删除类型参数
public class Pair {
//擦除类型变量,并替换为限定类型,无限定类型的变量用Object替换
private Object first;
private Object second;
public Pair(){}
public Pair(Object first, Object second){
this.first = first;
this.second = second;
}
}
原始类型使用第一个限定的类型变量来进行替换,如果没有给定限定就使用Object替换。
public class Interval <T extends Comparable & Serializable> implements Serializable{
private T lower;
private T upper;
}
类型擦除后
public class Interval implements Serializable{
//
private Comparable lower;
private Comparable upper;
}
if(a instanceof Pair<String>)//错误
if(a instanceof Pair<T>)//错误
Pair<String>[] pairs = new Pair<String>[10];//不可以
Pair<String>[] pairs = new Pair[10];//可以
public class Pair<T> {
private T first;
private T second;
public static T filed;
public static T getFiled(){
return filed;
}
在使用泛型类时,需要了解一些有关继承和子类型的准则。考虑一个类和一个子类,如Employee和Manager。Pair<Manager>是Pair<Employee> 的一个子类吗? 答案是“不是”, 或许人们会感到奇怪,奇怪我也不想再继续写了。
固定的泛型类型使用起来并没有那么有意思,Java的设计者发明了一种巧妙的(仍然是安全的)“解决方案”:通配符类型。
通配符类型子类限定
比如,通配符类型Pair<? extends Employee>,表示任何泛型Pair类型,它的类型参数必须是Employee的子类,像Pair<Manager>,但Pair<String>不可以。
通配符类型超类限定
Pair<? super Manager>,这个通配符限制为 Manager 的所有超类型。
常见的用法是作为一个函数式接口的参数类型。例如,
Collection接口有一个方法:
default boolean removeIf(Predicate<? super E> filter)
这个方法会删除所有满足给定谓词条件的元素。
如果你希望传入一个Predicate
原文:https://www.cnblogs.com/codeloong/p/14832572.html