ZhongXiaoHong / Javagenericity

Java泛型编程

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Javagenericity

泛型定义

jdk1.5开始引入的一种参数化类型特性,参数化类型就是把类型当参数一样传递

举个例子:

Test "T"类型参数,“Test”泛型类型

Test "String" 实际类型参数,Test参数化类型 ParameterizedType

泛型好处

  1. 代码健壮(只要编译器没警告,运行期就不会出现类型转换异常错误)
  2. 代码更加简洁不用强转
  3. 代码灵活增加复用

泛型在Java中使用

  1. 泛型类

    class Test<T>{
        T  t;
        
        
        public T getKey(){ //TODO 不是泛型方法没有<T>
            return t;
        }
    }
  2. 泛型接口

    interface Test<T>{
    
    }
  3. 泛型方法

    <T> T fun(){  //TODO <T>  表明是泛型方法
    
    }

在泛型类中声明一个泛型方法,使用泛型T,注意这个T是一种全新的类型,可以与泛型类中声明的T不是同一种类型。

泛型extends多个限定类型,限定类型排放有要求,先类后接口

public class Test1 {

    static class A {
    }

    interface B {
    }

    interface C {
    }

    //TODO  A 属于类必须放在前面
    //TODO 而且不能多继承类,放了A就不能放其他泛型类了
    static class D<T extends A & C & B> {
    }

}

630648

以上不按类优先排放会报错

泛型原理

泛型是Jdk1.5才引入的,为了向下兼容,虚拟机实际上是不支持泛型的,java泛型实际上是一种伪泛型机制,

在编译器会被擦除所有的泛型信息,所有的泛型类型最终都是一种原始类型,Java运行时不存在泛型

编译器具体时如何作泛型擦除的

  1. 擦除泛型变量替换成限定类型

    如果泛型类型没有限定如 Test则使用Object替换

    如果有如Test则使用String替换

    如果有多个则用第一个替换如Test<T extends String & XXInterface>则使用String替换

  2. 必要时插入类型转换确保类型安全

  3. 生成桥方法保持扩展时的多态性

泛型擦除带来的副作用

  1. 不能使用List list;导致基础类型不能作泛型参数,因为类型擦除之后直接替换成Object,Object不能存放基础类型

2.不能使用instanceof运算

630726

3.不能使用泛型静态变量

630730

630726

3.不能使用泛型静态变量

630730

4.泛型类型导致方法冲突

5.可以定义泛型数组,不能创建泛型数组

6.不能捕获泛型对象,可以抛出泛型对象

630730

5.静态域不能使用泛型

总结结论

  • 在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除)
  • 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。 无论我们如何定义一个泛型类型,相应的都会有一个原始类型被自动提供。原始类型的名字就是擦除类型参数的泛型类型的名字

在编译时期泛型不是已经被擦除了吗? 为何通过反射还可以获取到T的实际类型

为什么静态域不能使用泛型

比如

class  Test<T>{

private  static  T instance
}

为什么如此设计?就上例而言泛型要在创建Test对象的时候才确定,而static T instance在加载类的时候已经要确定了,所以不能使用泛型,但是静态方法本身就是泛型方法的除外,如:

class  Test<T>{

private  static  <T> T getInstance(){

}
}

多类型限定符注意点

泛型数组

可以定义泛型数组,不能创建泛型数组实例

泛型与异常

泛型类不能 extends Exception/Throwable

不能捕获泛型对象

泛型类型的继承规则

练习题1

 public static void main(String[] args) {
        List<String> strs = new ArrayList<>();
        List<Double> doubles = new ArrayList<>();
        System.out.println(strs.getClass()==doubles.getClass());

    }
输出的结果是true

About

Java泛型编程


Languages

Language:Java 100.0%