Java 泛型 泛型数组
Java 泛型 泛型数组
@author ixenos
- 先给结论
- 不能(直接)创建泛型数组
- 泛型数组实际的运行时对象数组只能是原始类型( T[]为Object[],Pair<T>[]为Pair[] ),而实际的运行时数组对象可能是T类型( 虽然运行时会擦除成原始类型 )
- 一般解决方案:(泛型数组包装器):使用ArrayList收集泛型数组对象的对象元素,如ArrayList<T>、ArrayList<Pair<String>>
- 将获得数组的行为,以及由泛型提供的编译期的类型安全
- 直接创建泛型数组不能通过编译,而转型对象数组通过编译但是不能在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(); //能成功返回了!
}
}
Java 泛型 泛型数组的更多相关文章
- 《徐徐道来话Java》(2):泛型和数组,以及Java是如何实现泛型的
数组和泛型容器有什么区别 要区分数组和泛型容器的功能,这里先要理解三个概念:协变性(covariance).逆变性(contravariance)和无关性(invariant). 若类A是类B的子类, ...
- Java“禁止”泛型数组
Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...
- Java 泛型 五:泛型与数组
简介 上一篇文章介绍了泛型的基本用法以及类型擦除的问题,现在来看看泛型和数组的关系.数组相比于Java 类库中的容器类是比较特殊的,主要体现在三个方面: 数组创建后大小便固定,但效率更高 数组能追踪它 ...
- Java泛型与数组深入研究
Java中的泛型与数组平时开发用的很多,除了偶尔遇到"NullPointerException"和"IndexOutOfBoundsException"一般也不 ...
- (转载)Java里新建数组及ArrayList java不允许泛型数组
java中新建数组: String[] s;//定义的时候不需要设置大小 s = new String[5];//为数组分配空间时就要设置大小 对于ArrayList, ArrayList< ...
- Java笔记--泛型总结与详解
泛型简介: 在泛型没有出来之前,编写存储对象的数据结构是很不方便的.如果要针对每类型的对象写一个数据结构, 则当需要将其应用到其他对象上时,还需要重写这个数据结构.如果使用了Object类型, ...
- [改善Java代码]Java的泛型是类型擦除的
泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...
- Java 中泛型的全面解析(转)
Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在J ...
- Java中泛型 类型擦除
转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...
随机推荐
- nginx服务器上遇到了acces denied,报错是fastCGI只要好好修改配置就行了
猜想: 懵逼 实践: 首先通用的方法,并没有解决问题. 1.修改php-fpm配置文件vim /etc/php-fpm.d/www.confuser = nginx 编辑用户为nginx ...
- hdu 5997 rausen loves cakes(线段数合并+启发式修改)
题目链接:hdu 5997 rausen loves cakes 题意: 给你n个点,每个点有一个颜色,现在有两个操作,第一个操作,将颜色x改为颜色y,第二个操作,询问[x,y]区间有多少颜色段(颜色 ...
- Java学习笔记-Thread-线程
//2015年5月5日16:55:00 //Main package com.alfredsun.thread; public class Main { public static void main ...
- Jstatd方式远程监控Linux下 JVM运行情况
前言 最近一个项目部署在服务器上运行时出现了问题,经过排查发现是java内存溢出的问题,所以为了实时监控服务器java内存的情况,需要远程查看服务器上JVM内存的一些情况.另外服务器系统是CentOS ...
- Jquery Easyui与Jquery Bootstrap(Metronic Bootstrap)的简单比较
1,通常来看WEB前端用 bootstrap 比较好,后台用EASYUI比较好.Easyui适合工厂企业的管理系统如ERP,CRM之类的,Bootstrap适用于多屏跨设备浏览. 简言之,一个适合上班 ...
- SQL语句获取数据库中的表主键,自增列,所有列
SQL语句获取数据库中的表主键,自增列,所有列 获取表主键 1:SELECT TABLE_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_U ...
- HDU 5873 Football Games
随便判了几个条件就过了,也不知道对不对的. 正解应该是: $[1].$${s_1} + {s_2} + {s_3} + ...... + {s_n} = n(n - 1)$ $[2].$${s_1} ...
- js数组操作-打乱数组
<style> html, body { margin: 0; padding: 0;} div span { display: inline-block; width: 25px; he ...
- 真的了解JS么?
1.setTimeout setTimeout(function(){ }),1000) setTimeout(function(num){ alert(num) //弹123 },1000,1 ...
- 详细介绍Java垃圾回收机制
垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机 ...