Java泛型

目录

泛型是什么

为什么要使用泛型

泛型有哪些

怎么用泛型 


泛型是什么

Java泛型(generics)是JDK5开始引入的一个新特性,指所操作的数据类型被指定为一个参数。

为什么要使用泛型

在没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这本身就是一个安全隐患。那么泛型的好处就是在编译的时候能够检查类型安全,并且所有的强制转换都是自动和隐式的。

泛型有哪些

?表示不确定的java类型。
T(type) 表示具体的一个java类型。
K V(key value) 分别代表java键值中的Key Value。
E(element) 代表Element。

怎么用泛型 

?无界通配符

有一个父类Animal和N个子类:
static int countLegs (List animals ) {
        int retVal = 0;
        for (Animal animal : animals){
        retVal += animal.countLegs();
        }
        return retVal;
        }

static int countLegs1 (List animals){
        int retVal = 0;
        for (Animal animal : animals ){
        retVal += animal.countLegs();
        }
        return retVal;
        }

public static void main(String[] args) {
        List dogs = new ArrayList<>();
        // 不会报错
        countLegs( dogs );
        // 报错
        countLegs1(dogs);
        }

对于不确定要操作的类型,可以使用无限制通配符(即 ),表示可以持有任何类型。像countLegs方法中,限定了上界,但是不关心具体类型是什么,所以对于传入的Animal的所有子类都可以支持,而countLegs1就不行。

上界通配符< ? extends E>

用extends关键字声明,表示参数化的类型可能是所指定的类型,或者是此类型的子类。在类型参数中使用extends表示这个泛型中的参数必须是E或者E的子类,这样有两个好处:

如果传入的类型不是E 或者 E 的子类,编译不成功
private  E test(K arg1, E arg2){
        E result = arg2;
        arg2.compareTo(arg1);
        //.....
        return result;
        }
类型参数列表中如果有多个类型参数上限,用逗号分开

下界通配符< ? super E>

用super进行声明,表示参数化的类型可能是所指定的类型,或者是此类型的父类型

private  void test(List dst, List src){
        for (T t : src) {
        dst.add(t);
        }
        }
public static void main(String[] args) {
        List dogs = new ArrayList<>();
        List animals = new ArrayList<>();
        new Test3().test(animals,dogs);
        }
// Dog 是 Animal 的子类
class Dog extends Animal {

}

dst类型 “大于等于” src 的类型,这里的“大于等于”是指 dst 表示的范围比 src 要大,因此装得下 dst 的容器也就能装 src 。

?和T的区别

T是一个确定的类型,通常用于泛型类和泛型方法的定义,?是一个 不确定 的类型,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。比如如下这种 :

通过T来确保泛型参数的一致性

public  void test(List dest, List src)
//通配符是不确定的,所以这个方法不能保证两个List具有相同的元素类型
public void test(List dest, List src)

类型参数可以多重限定而通配符不行

public class Multilimit implements MultilimitInterfaceA,MultilimitInterfaceB{
    //使用&符号设定多重边界
    public static void test(T t){
    }
}

interface MultilimitInterfaceA{}
interface MultilimitInterfaceB{}

通配符可以使用超类限定而类型参数不行 类型参数 T只具有一种类型限定方式:

T extends A

但是通配符?可以进行两种限定:

? extends A
? super A

Class和Class区别

常见的是在反射场景下的使用

// 通过反射的方式生成multiLimit对象
MultiLimit multiLimit = (MultiLimit)
                    Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();
对于上述代码,在运行期,如果反射的类型不是MultiLimit类,那么一定会报 
ava.lang.ClassCastException错误。

Class在实例化的时候,T 要替换成具体类。Class它是个通配泛型,? 可以代表任何类型,
所以主要用于声明时的限制情况。

你可能感兴趣的:(Java基础,java,开发语言)