文档章节

Java 泛型 泛型数组

商者
 商者
发布于 2017/07/25 21:06
字数 924
阅读 14
收藏 0

Java 泛型 泛型数组

  • 直接创建泛型数组不能通过编译,而转型对象数组通过编译但是不能在JVM运行
    • 复制代码

      复制代码

      public class ArrayOfGeneric{
          static Generic<Integer>[] gia;
          @SupperssWarnings("unchecked")
          public static void main(String[] args){
              gia = (Generic<Integer>[])new Generic[100]; // 通过类型转换匿名对象
              //! gia[0] = new Object(); //编译不通过,不能(直接)创建泛型数组实例
          }
      }

      复制代码

      复制代码

    • 问题在于数组将跟踪他们的实际类型,而这个类型是在数组被创建时确定的,因此,即使gia已经被转型为Generic<Integer>[],但这个信息只存在于编译期(并且如果没有@SuppressWarning("unchecked")注解,将得到这个转型的警告)。在运行时,它仍旧是Object数组
    • 因此,成功创建泛型数组的唯一方式就是创建一个被擦出类型的新数组,然后对其转型(而且是在运行时转型)
      •  直接对整个数组强制转型,在编译时依旧会被擦除掉类型!所以应该在运行时转型,而这时最好的办法就是使用一个泛型数组包装器,维护一个原始类型的数组,通过数组入口方法进行元素编译期的类型安全检测(对应返回值)和强制类型转换(对于运行时不重要),从而保证类型安全。

 

    • 对整个数组强制转型的例子(错误方法)
    • 复制代码

      复制代码

      public class GenericArray<T> {
          private T[] array;
          @SupperessWarning("unchecked")
          public GenericArray(int sz) {
              array = (T[]) new Object[sz];
          }
          public void put(int index, T item) {
              array[index] = item;
          }
          public T get(int index) { return array[index]; }
          public T[] rep() { return array; } //应该在运行时出口做文章
          public static void main (String[] args){
              GenericArray<Integer> gai = new GenericArray<Integer>(10);
              // Integer[] ia = gai.rep(); //ClassCastException
              Object[] oa = gai.rep(); //只能返回对象数组类型为Object[]

      复制代码

      复制代码

      • 实际的运行时对象数组是Object[],而实际的运行时数组对象可能是T类型。

 

    • 因此,应该在运行时,数组对象的出口做转型输出,入口方法在编译期已实现类型安全,所以出口方法可以放心强制类型转换,保证成功。如下
      • 复制代码

        复制代码

        public class GenericArray2<T> {
            private Object[] array;  //维护Object[]类型数组
            @SupperessWarning("unchecked")
            public GenericArray2(int sz) {
                array = new Object[sz];
            }
            public void put(int index, T item) {
                array[index] = item;
            }
            public T get(int index) { return (T)array[index]; }//数组对象出口强转
            public T[] rep() { return (T[])array; } //运行时无论怎样都是Object[]类型 
            public static void main (String[] args){
                GenericArray<Integer> gai = new GenericArray<Integer>(10);
                // Integer[] ia = gai.rep(); //依旧ClassCastException
                Object[] oa = gai.rep(); //只能返回对象数组类型为Object[]
                gai.put(0,11);
                System.out.println(gai.get(0)); // 11 ,出口成功转型
            }
        }

        复制代码

        复制代码

         

  •  通过反射在运行时构出实际类型为type[]的对象数组,避免了类型擦除,从而转换成功,无ClassCastException

复制代码

复制代码

import java.lang.reflect.*; 

public class GenericArrayWithTypeToken<T> {
    private T[] array;
    @SuppressWarning("unchecked")
    public GenericArrayWithTypeToken(Class<T> type, int sz) {
        array = (T[]) Array.newInstance(type, sz);//通过反射在运行时构出实际类型为type[]的对象数组,避免了类型擦除,从而转换成功,无ClassCastException
    }
    public void put(int index, T item){
        array[index] = item;
    }
    public T get(int index) { return array[index]; }
    public T[] rep() { return array; }  //能成功返回了~
    public static void main(String[] args) {
        GenericArrayWithTypeToken<Integer> gawtt = new GenericArrayWithTypeToken<>(Integer.class, 10);
        Integer[] ia = gawtt.rep(); //能成功返回了!
    }
}
  • 结论
    • 不能(直接)创建泛型数组
    • 泛型数组实际的运行时对象数组只能是原始类型( T[]为Object[],Pair<T>[]为Pair[] ),而实际的运行时数组对象可能是T类型( 虽然运行时会擦除成原始类型 )
    • 一般解决方案:(泛型数组包装器):使用ArrayList收集泛型数组对象的对象元素,如ArrayList<T>、ArrayList<Pair<String>>
      • 将获得数组的行为,以及由泛型提供的编译期的类型安全

复制代码

本文转载自:

共有 人打赏支持
商者

商者

粉丝 39
博文 141
码字总数 43255
作品 0
海淀
架构师
Java编程学习之泛型方法的了解 java开发

Java泛型方法和泛型类支持程序员使用一个方法指定一组相关方法,或者使用一个类指定一组相关的类型。 Java泛型是JDK 5中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序...

老男孩Linux培训
05/29
0
0
Java语言学习(十一):枚举类型和泛型

Java中一个重要的类型:枚举,它可以用来表示一组取值范围固定的变量,使用 enum 关键字定义枚举类型,其中元素不能重复,通常大写表示。利用Java的反射机制,可以在运行时分析类,如查看枚举...

海岸线的曙光
07/18
0
0
6-Java常用工具类-集合排序

本节内容转载自菜鸟教程,泛型就是c++里的模板技术,没什么新鲜的: http://www.runoob.com/java/java-generics.html Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型...

天涯明月笙
08/08
0
0
【J2SE】JAVA语法糖之-伪泛型

JAVA语法糖之-伪泛型 泛型即参数化类型 首先看一个泛型例子: public static void main(String[] args) {List<String> strList = new ArrayList<String>();strList.add("generic test!");fo......

磊神Ray
2011/09/28
0
0
Java深度历险 Java泛型

Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter)。声明的类型参数在使用时用具体的类型来替换。泛型最主要的应用是在JDK 5中的新集...

SeanCai
2011/03/03
0
2

没有更多内容

加载失败,请刷新页面

加载更多

下一页

又一个centos文件顺序导致的问题

背景 新的centos似乎对于文件顺序做了特别的优化 和文件顺序出现的问题确实多了不少 centos7导致的spring循环依赖【实际上和这个问题不一样 不过由此衍生出的问题】 某应用放在新的系统开始报...

Mr_Qi
17分钟前
0
0
阿里云国际版香港CN2测评 月付9美元/30M带宽/1T流量

市面上很多家香港VPS服务商,一直都说阿里云国际版香港CN2线路好,延迟低,速度快,价格便宜流量还多,那么这个香港线路到底怎么样呢?本文从性能、延时、路由、速度方面来全方面测评一下阿里...

flyzy2005
今天
0
0
撤销git commit --amend

it commit -amend之后想撤销 git reset HEAD@{1}

xiaomge
今天
0
0
有意思的TimeUnit

java.util.concurrent.TimeUnit 这个类,相信童鞋们都不陌生。它是一个enum: public enum TimeUnit 好吧,我一直把它当做一个枚举类来用。偶然看到还有别的用法,大吃一斤,原来 TimeUnit 并...

polly
今天
10
0
生成pyc

Python生成pyc文件 pyc文件是py文件编译后生成的字节码文件(byte code)。pyc文件经过python解释器最终会生成机器码运行。所以pyc文件是可以跨平台部署的,类似Java的.class文件。一般py文件改...

Mr_Tea伯奕
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部