Java泛型的一些限制
2023-09-14 09:10:06 时间
本文主要參考《Java编程思想(第4版)》的Java泛型章节,仅当一个简单的读书笔记。
和C++泛型对照,Java泛型仅仅是一种编译期间的擦拭机制。
这是因为考虑到和曾经的兼容而考虑的一种折中方案。
在编译好的泛型代码里,编译期间已经把全部的泛型信息给擦拭掉,因此无法获得不论什么有关泛型參数类型的信息。因此List<String>和List<Integer>实际上是同一类型。
參考下面代码:
//下面3个样例都无法通过编译 public <T> void testGeneric(Object arg) { if (arg instanceof T) {} //1 T var = new T(); //2 T[] array = new T[100]; //3 }
从以上代码能够看到,这样的擦拭机制的限制包含例如以下:
1、instanceof无法使用
2、无法实例化泛型类
3、无法实例化泛型数组
以上3种方法无法通过编译的主要原因是,泛型的擦拭机制把详细的类型信息都擦拭,无法在执行时知道确切的类型信息。只是Java提供了另外的方法去绕过这些限制。
解决1
对于第1种,无法使用instanceof语法。我们能够利用动态的isInstance():
//testInstance(String.class, "abc") == true public static <T> boolean testInstance(Class<T> c, Object arg) { return c.isInstance(arg); }<解决2
对于第2种。无法实例化泛型类。假设对于要实例化的泛型类。拥有无參默认构造函数,我们能够利用Class对象:
public static <T> T createGeneric(Class<T> c) { T x = null; try { x = c.newInstance(); } catch (Exception e) { throw new RuntimeException(e); //createGeneric<Integer.class>会抛出异常,因为Integer没有默认构造函数 } return x; }因为以上代码採用Class对象实例化拥有一定限制,因此我们还能够借助工厂方法,显示创建相应的类:
interface GenericFactory<T> { T create(); } class IntegerFactory implements GenericFactory<Integer> { @Override public Integer create() { return new Integer(0); } }解决3
对于第3种,无法实例化泛型数组。我们能够借助ArrayList<T>来取代,但假设一定要获得数组的行为,以及泛型提供的编译期的安全类型,
//GenericArray ga = new GenericArray<Integer>(10); //ga.put(3, 10); //int abc = (Integer) ga.get(3); //Integer[] aaa = (Integer[]) ga.array(); //抛出ClassCastException class GenericArrayEx<T> { private T[] array; public GenericArray(int size) { array = (T[]) new Object[size]; } public void put(int index, T item) { array[index] = item; } public T get(int index) { return array[index]; } public T[] array() { return array; } }对于以上代码。我们採用一个GenericArray的类进行包装,但内部实际还是一个Object[]的对象数组,在put和get的时候获得了编译期间的检查。但问题来了,假设我们使用array()方法企图获得内部数组并转型的时候,会抛出ClassCastException,这是因为数组实际还是Object[]对象!为了解决问题,我们能够使用Array.newInstance。
//GenericArrayEx ga = new GenericArrayEx<Integer>(Integer.class, 10); //ga.put(3, 10); //int abc = (Integer) ga.get(3); //Integer[] aaa = (Integer[]) ga.array(); //能够成功转型 class GenericArrayEx<T> { private T[] array; public GenericArrayEx(Class<T> type, int size) { array = (T[]) Array.newInstance(type, size); } public void put(int index, T item) { array[index] = item; } public T get(int index) { return array[index]; } public T[] array() { return array; } }这样,就能够使用T[]了。
相关文章
- Java泛型--通配符
- Java泛型--泛型入门
- Java 容器 & 泛型:五、HashMap 和 TreeMap的自白
- Java实现 蓝桥杯 算法训练 谁干的好事?
- java实现数字的值返回
- Java实现填符号凑算式
- Java实现 蓝桥杯VIP 算法训练 明明的随机数
- Java实现 蓝桥杯VIP 基础练习 回形取数
- Java泛型知识点全方位总结
- Java 容器 & 泛型:二、ArrayList 、LinkedList和Vector比较
- Java 容器 & 泛型:一、认识容器
- Trie树(字典树)的介绍及Java实现
- java.lang.IllegalArgumentException: View not attached to window manager
- (翻译)反射处理java泛型
- paip.元数据驱动的转换-读取文件行到个list理念 uapi java php python总结
- paip. 调试技术打印堆栈 uapi print stack java php python 总结.
- 【泛型】Java中的泛型,泛型类,泛型接口,泛型方法,泛型擦除
- Java 多线程实现的四种方式
- java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束
- Java豆瓣电影爬虫——模拟登录的前世今生与验证码的爱恨情仇
- Java基础 Day14 泛型
- Java如何获得运行线程的优先级?
- java学习笔记——Collection集合、迭代器、泛型、扑克牌案例