前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >0001_Java泛型

0001_Java泛型

原创
作者头像
云台大树
修改2022-05-21 23:29:36
2840
修改2022-05-21 23:29:36
举报

泛型类

泛型类声明时,在类名后面的尖括号内,放置一个或多个类型参数

代码语言:javascript
复制
class GenericMemoryCall<AnyType> {
    private AnyType storedValue;
    
    public AnyType read() {
        return storedValue;
    }
    
    public void write( AnyType x ) {
        storedValue = x;
    }
}

泛型接口

泛型接口的声明方式同泛型类是一致的,在接口名后紧跟一个尖括号,里面放置类型参数

代码语言:javascript
复制
interface Comparable<AnyType> {
    public int compareTo( AnyType other );
}

泛型方法

显示泛型方法的声明同普通方法类似,唯一不同:在方法声明处执行一个泛型类型,显示的表明该方法是泛型方法

代码语言:javascript
复制
public static <AnyType> boolean contains( AnyType[] arr, AnyType x ) {
    for( AnyType val : arr ) {
        if( x.equals( val ) ) {
            return true;
        }
    }
    return false;
}

<AnyType>显示表明该方法是泛型方法, 且该泛型类型还可以指定泛型类型界限

这个例子里要求:泛型必须实现了Comparable<?>接口,且该接口里的类型必须是泛型类型及其超类

代码语言:javascript
复制
public static <AnyType extends Comparable<? super AnyType>> AnyType findMax( AnyType[] arr ) {
    int maxIndex = 0;
    for( int i = 1; i < arr.length; i++ ) {
        if( arr[i].compareTo( arr[ maxIndex ] ) > 0 ) {
            maxIndex = i;
        }
    }
    return arr[ maxIndex ];
}

泛型通配符 - ?

通配符表示参数类型的子类(或超类):extends表示子类, super表示超类

代码语言:javascript
复制
// 子类 - 只能接收Shape类及其子类
public static double totalArea( Collection<? extends Shape> arr ) {
    double total = 0;
    for( Shape s : arr ) {
        if( s != null ) {
            total += s.area();
        }
    }
    return total;
}

// 父类 - 只能接收Shape类及其父类
public static double totalArea( Collection<? super Shape> arr ) {}

类型擦除

泛型类可以由编译器通过所谓的类型擦除(type erasure)过程而转变成非泛型类。编译器生成一种与泛型类同名的原始类(raw class),但是类型参数都被删去了。类型变量由它们的类型界限来代替,当一个具有擦除返回类型的泛型方法被调用的时候,一些特性自动被插入。如果使用一个泛型类而不带类型参数,那么使用的是原始类

由于类型擦除的存在,有以下的限制需要遵守:

  • 基本类型 - 基本类型不能用做类型参数,如GenericMemoryCell<int>就是错误的,必须使用基本类型的包装类
  • instanceof检测 instanceof检测和类型转换工作只对原始类进行。下面的例子里,所有的类型转换都是成功的,因为所有的类型都是GenericMemoryCell(编译器生成的与泛型类同名的原始类,但是删去了参数类型!) 但是最后一行中,由于对read()的调用企图返回一个String对象会产生一个运行时错误,该方法在运行时只能返回类型边界值 - 此例中为______Object
代码语言:javascript
复制

public void instanceofLimitation() {     GenericMemoryCell<Integer> cell_int = new GenericMemoryCell<>();     cell_int.write( 4 );     Object cell_obj = cell_int;     GenericMemoryCell<String> cell_str = (GenericMemoryCell<String>) cell_int;     String s = cell_str.read( ); }

  • static的语境 在泛型类中,static方法和static域都不可引用类的类型变量,因为在类型擦除后,类型变量就不存在了。由于实际上只存在一个原始类,因此static域在该类的诸泛型实例之间是共享的
  • 泛型类型的实例化 不能创建泛型类型的实例,注意是泛型类型的实例,而不是泛型类的实例。 T obj = new T(); 中右边的实例化是非法的
  • 泛型数组对象 也不能创建一个泛型类型的数组,注意是泛型类型的数组,而不是泛型类的数组 T[] arr = new T[10];中右边的数组实例化是非法的
  • 参数化类型的数组 参数化类型的数组的实例化时非法的 - 下面的例子中,最后一行会产生一个ClassCastException异常,原因见instanceof检测
代码语言:javascript
复制

public void f() {     GenericMemoryCell<String>[] arr_str = new GenericMemoryCell<> 10 ;     GenericMemoryCell<Double> cell_double = new GenericMemoryCell<>();     cell_double.write( 4.5 );     Object[] arr_obj = arr_str;     arr_obj 0  = cell;     String s = arr_str 0 .read(); }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 泛型类
  • 泛型接口
  • 泛型方法
  • 泛型通配符 - ?
  • 类型擦除
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档