文档章节

Java 泛型 泛型数组

商者
 商者
发布于 2017/07/25 21:06
字数 924
阅读 14
收藏 0
点赞 0
评论 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

Kotlin 泛型 VS Java 泛型

建议先阅读我的上一篇文章 -- Java 泛型 和 Java 泛型一样,Kotlin 泛型也是 Kotlin 语言中较难理解的一个部分。Kotlin 泛型的本质也是参数化类型,并且提供了编译时强类型检查,实际上也是伪...

JohnnyShieh ⋅ 06/11 ⋅ 0

一文搞懂Java泛型到底是什么东东

对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下。 本文参考java 泛型详解、Java中的泛型方法、 java泛型详解 1. 概述 泛型在j...

qq_39521554 ⋅ 04/17 ⋅ 0

Kotlin语言中的泛型设计哲学

Kotlin语言的泛型设计很有意思,但并不容易看懂。关于这个部分的官方文档,我反复看了好几次,终于弄明白Kotlin语言泛型设计的背后哲学。这篇文章将讲述Kotlin泛型设计的整个思考过程及其背后...

欧阳锋 ⋅ 04/16 ⋅ 0

Kotlin泛型-你可能需要知道这些

本博文主要讲解一些Kotlin泛型的问题,中间会对比穿插Java泛型。 1. 泛型类型参数 1.1 形式 我们使用泛型的形式无非是类、借口、方法几种,我们先看两个例子。 1.2 声明泛型类 和Java一样,我...

24K男 ⋅ 04/21 ⋅ 0

Java 泛型,你了解类型擦除吗?

泛型,一个孤独的守门者。 大家可能会有疑问,我为什么叫做泛型是一个守门者。这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇。泛型是 Java 中一个...

xiaomin0322 ⋅ 06/06 ⋅ 0

GSON使用笔记(3) -- 如何反序列化出List

GSON使用笔记(3) -- 如何反序列化出List 时间 2014-06-26 17:57:06 CSDN博客原文 http://blog.csdn.net/zxhoo/article/details/34856061 本文通过3个问题来讨论如何使用 GSON 把JSON反序列...

thinkyoung ⋅ 2015/03/24 ⋅ 0

java集合入门和深入学习,看这篇就差不多了

集合框架: Java中的集合框架大类可分为Collection和Map;两者的区别: Collection是单列集合;Map是双列集合 Collection中只有Set系列要求元素唯一;Map中键需要唯一,值可以重复 Collecti...

sihailoveyan ⋅ 05/04 ⋅ 0

14、Java并发性和多线程-Java ThreadLocal

以下内容转自http://ifeve.com/java-theadlocal/: Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作。因此,尽管有两个线程同时执行一段相同的代码,而且这段代码又有...

easonjim ⋅ 2017/06/16 ⋅ 0

Java编程语言高级特性入门学习——泛型、反射和注解!

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互...

Java小辰 ⋅ 06/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

OSChina 周三乱弹 —— 这样的女人私生活太混乱了

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ 胖达panda :你经历过体验到人生的大起大落吗?我一朋友在10秒内体验了,哈哈。@小小编辑 请点一首《almost lover》送给他。 《almost love...

小小编辑 ⋅ 20分钟前 ⋅ 4

自己动手写一个单链表

文章有不当之处,欢迎指正,如果喜欢微信阅读,你也可以关注我的微信公众号:好好学java,获取优质学习资源。 一、概述 单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对...

公众号_好好学java ⋅ 25分钟前 ⋅ 0

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 今天 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 2

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部