【0】README

0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 Varargs 警告+不能实例化类型变量 的知识;


【1】 Varargs 警告

1.1)一个相关问题: 向参数个数可变的方法传递一个泛型类型的实例;

  • 1.1.1)考虑以下方法, 它的参数个数是可变的:
public static<T> void addAll(Collection<T) coll, T...ts)
{......
}
  • 1.1.2)应该记得, 实际上参数ts 是一个数组, 包含所有实参, 考虑以下调用:
Collection<Pair<String>> table = ......;
Pair<String> pair1 = ....;
Pair<String> pair2 = ....;
addAll(table, pair1, pair2);
  • 1.1.3)为了调用上述方法: java 虚拟机必须建立一个 Pair 数组, 这就违反了前面的规则, 不过, 对于这种case , 你只会得到一个警告, 而不是 错误;

1.4)可以采用以下两种方法来抑制这种警告(Methods):(解决方法)

  • M1)一种方法是 为 包含 addAll 调用的方法增加 标注
@SuppressWarnings("unchecked");
  • M2)在java se 7中, 还可以用 @SafeVarargs 直接标注addAll 方法:
@SafeVarargs
public static <T> void addAll(Collection<T> coll, T...ts);
  • 现在就可以用 泛型类型来调用这个方法了;

Annotation)

  • A1)可以使用 @SafeVarargs 标注来消除创建泛型数组的有关限制, 方法如下:
@SafeVarargs
static <E> E[] array(E... array)
{return array;
}
  • A2)现在可以调用:
Pair<String>[] table = array(pair1, pair2);
  • 这看起来方便, 不过隐藏着危险, 如下代码:
Object[] objarray = table;
objarray[0] = new Pair<Employee>();
  • 能顺利运行而不会出现 ArrayStoreException 异常 (因为数组存储只会检查擦除的类型), 但在处理 table[0] 时 你会在别处得到一个异常;

【2】不能实例化类型变量

2.1)不能使用像 new T(…), new T[…] 或 T.class 这样的表达式中的类型变量。

  • 2.1.1)看个荔枝:(下面的 Pair 构造器就是非法的)
public Pair()
{first = new T();second = new T(); // ERROR
}
  • 2.1.2)类型擦除将T 改变成 Object, 而且, 本意肯定不希望调用 new Object()。
  • 2.1.3)但是可以通过反射调用 Class.newInstance 方法来构造泛型对象:
然而,我们却不能调用: first = T.class.newInstance();//ERROR
  • 2.1.4)因为, 表达式 T.class 是不合法的, 必须像下面这样设计 API 以便可以支配Class 对象:
public static<T> Pair<T> makePair(Class<T> cl)
{try{ return new Pair<>(c1.newInstance(), c1.newInstance()) }catch(Exception ex) {return null;}
}
  • 2.1.5)以上方法可以按照下列方式调用:
Pair<String>p = Pair.makePair(String.class);
  • Attention) Class 类本身就是泛型, 如, String.class 是一个 class《String》 的实例(事实上, 它是唯一的实例)。 因此, makePair 方法能够推断出 pair 的类型;
  • 2.1.6) 不能构造一个 泛型数组:
public  static <T extends Comparable> T[] minmax(T[] a) { T[] mm = new T[2]; ...} //ERROR
  • 类型擦除会让这个方法永远构造 Object[2]数组;

2.2)如果数组仅仅是作为一个类的私有实例域, 就可以将这个数组声明为 Object[], 并且在获取元素时进行类型转换。

  • 2.2.1)看个荔枝: 如 ArrayLIst 可以这样实现:
public class ArrayList<E>
{private Object[] elements;...@SuppressWarnings("unchecked")public E get(int n){return (E) elements[n]; //获取元素时进行类型转换}pubic void set(int n, E e){elements[n] =e;}
}
  • 2.2.2)实际的实现没有这么清晰:
public class ArrayList<E>
{paivate E[] elements;...public ArrayList(){ elements = (E[])new Object[0]; }
}
  • 2.2.3)这里, 强制类型转换 E[] 是一个假想, 而类型 擦除使其无法察觉;

2.3)由于 minmax方法 返回 T[] 数组, 使得这一技术无法施展, 如果掩盖这个类型会有运行时错误。假设实现代码:

public static <T extends Comparable> T[] minmax(T...a)
{Object[] mm = new Object[2];...reutrn (T[]) mm;
}

2.4)调用String[] ss = minmax(“tom”, “dick”, “Harry”);
对上述代码的分析(Analysis):

  • A1)编译时不会有任何警告。 但Object[] 引用赋给 String[] 变量时, 将会发生 ClassCastException 异常;
  • A2)在这种case下, 利用反射,调用 Array.newIntance;
public static <T extemds Comparable> T[] minmax(T... a)
{T[] mm = (T[])mm.newInstance(a.getClass().getComponentType(), 2);
}    
  • A3)ArrayList 类的toArray方法就没有这么幸运了。 它需要生成一个 T[] 数组, 但没有成分类类型。 因此, 有下面两种不同的形式:
Object[] toArray();
T[] toArray(T[] result);
  • 第二个方法接收一个数组参数。 如果数组足够大, 就是用这个数组。 否则, 用result 的成分类型构造一个足够大的 新数组;

java泛型程序设计——Varargs 警告+不能实例化类型变量相关推荐

  1. java泛型程序设计——泛型类的静态上下文中类型变量无效+不能抛出或捕获泛型类的实例

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 泛型类的静态上下文中类型变量无效+不能抛出或捕获泛型类的实例 的知识 ...

  2. java泛型程序设计——类型变量限定 + 泛型代码和虚拟机

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 类型变量限定 + 泛型代码和虚拟机 的知识: [1]类型变量的限定 ...

  3. java泛型程序设计——约束与局限性

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 约束与局限性 的知识: [1] 不能用基本类型实例化类型参数 1.1 ...

  4. java泛型程序设计——调用遗留代码

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 调用遗留代码 的知识: [1]调用遗留代码相关 1.1)设计java ...

  5. java泛型程序设计——反射和泛型

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 反射和泛型 的相关知识: [1]反射和泛型相关 1.1)现在, Cl ...

  6. java泛型程序设计——无限定通配符+通配符捕获

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 无限定通配符+通配符捕获 的相关知识: [1]无限定通配符相关 1. ...

  7. java泛型程序设计——注意擦除后的冲突

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 注意擦除后的冲突 的知识: 1.1)当泛型类型被 擦除时, 无法创建 ...

  8. java泛型程序设计——翻译泛型表达式+翻译泛型方法

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 翻译泛型表达式+翻译泛型方法 的知识: [1]翻译泛型表达式 1.1 ...

  9. java泛型程序设计——定义简单泛型类+泛型方法

    [0]README 0.1) 本文描述+源代码均 转自 core java volume 1, 旨在理解 java泛型程序设计 的 定义泛型类+泛型方法的知识: [1]一个泛型类: 就是具有一个或多个 ...

最新文章

  1. 塔勒布: 2019-nCoV的系统风险:一份笔记
  2. [codevs 1034] 家园
  3. 大规模数据处理开源软件
  4. SpringBoot 集成Nacos报错(一)
  5. java泛型一定用包装类_你不知道的基本数据类型和包装类
  6. yolov5 deepsort 行人车辆 双向计数 跟踪检测
  7. Linux系统调用过程(Linux0.11内核实验)
  8. 13个Excel动图小技巧,快速提高工作效率?建议收藏!
  9. 中国自研数据库超越Oracle登顶全球第一
  10. 52. N皇后 II
  11. java 前端及后台轮询方法总结
  12. C语言 文件读写 ftell 函数 - C语言零基础入门教程
  13. 线索二叉树的建立和遍历
  14. 数据分析——从入门到精通(十二)
  15. 聚合数据--汇率接口调用
  16. php中的implode,php里implode是什么意思
  17. 新型肺炎疫情蔓延下的游戏行业会更火爆吗?
  18. xp系统链接不上宽带连接服务器,XP系统网络连接正常却上不了网怎么解决
  19. 计算机网络和因特网--分组交换网中的时延,丢包和吞吐量
  20. 关于数据库事务隔离级别的介绍

热门文章

  1. cf1555B. Two Tables
  2. AGC056E-Cheese【dp】
  3. P1912-[NOI2009]诗人小G【四边形不等式,单调队列】
  4. P4091-[HEOI2016/TJOI2016]求和【斯特林数,NTT】
  5. YbtOJ#20236-[冲刺NOIP2020模拟赛Day9]红点蓝点【线段树,堆】
  6. jzoj6288-旋转子段【优雅的暴力】
  7. P2048-[NOI2010]超级钢琴【RMQ,堆】
  8. [BZOJ1095][ZJOI2007]捉迷藏 Query on a tree IV(树链剖分)
  9. SpringCloud Greenwich(六)集成dubbo与openfeign的feignTargeter报错,cannot access its superinterface Targeter
  10. 最通俗易懂的乐观锁与悲观锁原理及实现