廖雪峰Java4反射与泛型-3范型-4擦拭法

1.擦拭法是Java泛型的实现方式。

  • 编译器把类型视为Object。
    * 泛型代码编译的时候,编译器实际上把所有的泛型类型T统一视为Object类型。换句话说,虚拟机对泛型一无所知,所有的工作都是编译器做的。
  • 编译器根据实现安全的强制转型。
    * Java的范型实际是有Java在编译时进行的。编译器内容永远把T视为Object处理,只是在需要转型的时候,根据T的类型实行安全的强制转型。

2.java的泛型是由擦拭法实现的,因此有一些局限:

2.1.不能是基本类型,例如int

  • 编译器把T视为Object,Object是无法持有基本类型的

    2.2.无法取得带泛型的Class

    无论T的类型是什么,返回的永远是范型类。如Pair和Pair反射获取Class,获取的都是同一个Class:Pair。

  1. public class Main {
  2. public static void main(String[] args){
  3. Pair<String> s = new Pair<>("xiaoming","xiaohong");
  4. Pair<Integer> i = new Pair<>(4,5);
  5. Class c1 = s.getClass();
  6. Class c2 = i.getClass();
  7. System.out.println("c1:"+c1);
  8. System.out.println("c2:"+c2);
  9. System.out.print("c1==c2:");
  10. System.out.println(c1==c2);
  11. System.out.print("c1 == Pair.class:");
  12. System.out.println(c1 == Pair.class);
  13. }
  14. }

2.3.无法判断带泛型的Class


  1. //判断instance只能使用Pair
  2. public class Main {
  3. public static void main(String[] args){
  4. Pair<String> s = new Pair<>("xiaoming","xiaohong");
  5. Pair<Integer> i = new Pair<>(4,5);
  6. if(s instanceof Pair){
  7. System.out.println("true");
  8. }
  9. }
  10. }

2.4.不能实例化T类型,因为擦拭后实际上是new Object()

  1. 实例化T类型必须借助Class<T>
  2. public class Pair<T> {
  3. private T first;
  4. private T last;
  5. public Pair(Class<T> clazz) throws IllegalAccessException,InstantiationException{
  6. first = clazz.newInstance();
  7. last = clazz.newInstance();
  8. }
  9. public T getFisrt(){
  10. return first;
  11. }
  12. public T getLast(){
  13. return last;
  14. }
  15. public void setFirst(T first){
  16. this.first = first;
  17. }
  18. public void setLast(T last){
  19. this.last = last;
  20. }
  21. public String toString(){
  22. return "Pari("+first+","+last+")";
  23. }
  24. }

2.5注意编写的泛型类的方法不要与Object的方法重名

  1. public class Pair<T> {
  2. private T first;
  3. private T last;
  4. public Pair(T first,T last){
  5. this.first = first;
  6. this.last = last;
  7. }
  8. public T getFirst(){
  9. return first;
  10. }
  11. public void setFirst(){
  12. this.first = first;
  13. }
  14. public T getLast(){
  15. return last;
  16. }
  17. public void setLast(){
  18. this.last = last;
  19. }
  20. public String toString(){
  21. return "Pair("+first+", "+last+")";
  22. }
  23. /**提示与java.lang.Object的equals方法重名。因为范型采用了擦拭法,T擦拭后变成了Object。因此要注意与Object的重名问题
  24. * 'equals(T)' in 'com.testArray.pair' clashs with 'equals(Object)' in 'java.lang.Object';both methods have same erasure,yet neither overides the other
  25. public boolean equals(T pair){
  26. return true;
  27. }*/
  28. }

3.泛型继承:

可以继承子泛型类
父类的类型是Pair
子类的类型是IntPair
Pari.java

  1. package com.testArray;
  2. public class Pair<T> {
  3. private T first;
  4. private T last;
  5. public Pair(T first,T last){
  6. this.first = first;
  7. this.last = last;
  8. }
  9. }

IntPair.java

  1. package com.testArray;
  2. public class IntPair extends Pair<Integer>{
  3. public IntPair(Integer first,Integer last){
  4. super(first,last);
  5. }
  6. }
  7. package com.testArray;
  8. import java.lang.reflect.ParameterizedType;
  9. import java.lang.reflect.Type;
  10. public class Main {
  11. public static void main(String[] args){
  12. Pair<String> p = new Pair<>("xiao","ming");
  13. IntPair ip = new IntPair(1,2);
  14. System.out.println(p instanceof Pair);
  15. System.out.println(ip instanceof Pair);
  16. System.out.println(ip instanceof IntPair);
  17. //getSuperClass()获得该类的父类
  18. //getGenericSuperclass()获得带有泛型的父类
  19. //Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
  20. Type type = IntPair.class.getGenericSuperclass();
  21. //ParameterizedType参数化类型,即泛型
  22. ParameterizedType pt = (ParameterizedType) type;
  23. //getActualTypeArguments获取参数化类型的数组,泛型可能有多个
  24. Type[] types = pt.getActualTypeArguments();
  25. Class<?> clazz = (Class<?>) types[0];
  26. /**
  27. * ? 表示不确定的java类型。
  28. * T 表示java类型。
  29. * K V 分别代表java键值中的Key Value。
  30. * E 代表Element。
  31. */
  32. System.out.println(clazz);
  33. }
  34. }

总结:

  1. * Java的泛型是采用擦拭法实现的
  2. * 擦拭法决定了泛型<T>:
  3. * 不能是基本类型,例如int
  4. * 不能获取带泛型类型的Class,例如Pair<String>.class
  5. * 不能判断带泛型类型的类型,例如: x instanceof Pair<String>
  6. * 不能实例化T类型,例如new T()
  7. * 泛型方法要防止重复定义方法,例如public boolean equals(T obj)
  8. * 子类可以获取父类的泛型类型<T>

https://blog.csdn.net/liang5630/article/details/40185591
https://www.cnblogs.com/skyislimit/p/5665853.html

廖雪峰Java4反射与泛型-3范型-4擦拭法的更多相关文章

  1. 廖雪峰Java4反射与泛型-3范型-3编写泛型

    编写泛型类比普通的类要麻烦,而且很少编写泛型类. 1.编写一个泛型类: 按照某种类型(例如String)编写类 标记所有的特定类型例如String 把特定类型替换为T,并申明 Pair.java pa ...

  2. 廖雪峰Java4反射与泛型-3范型-6super通配符

    1.super通配符 1.1super通配符第一种用法 泛型的继承关系 Pair<Integer>不是Pair<Number>的子类,如 static void set(Pai ...

  3. 廖雪峰Java4反射与泛型-3范型-5extends通配符

    1.泛型的继承关系: Pair<Integer>不是Pair<Number>的子类 add()不接受Pair<Integer> Pair.java package ...

  4. 廖雪峰Java4反射与泛型-3泛型-7泛型和反射

    1.部分反射API是泛型 1.1获取反射API的泛型 部分反射API是泛型,如Class<T>是泛型 //如果使用Class,不带泛型,出现compile warning编译警告 Clas ...

  5. 廖雪峰Java4反射与泛型-2注解-3处理注解

    1.处理注解 注解本身对对代码逻辑没有任何影响 SOURCE类型的注解在编译期就被丢掉了 CLASS类型的注解仅保存在class文件中 RUNTIME类型的注解在运行期可以被读取 如何使用注解由工具决 ...

  6. 廖雪峰Java4反射与泛型-1反射-2访问字段Field和3调用方法Method

    2.字段Field 2.1.通过Class实例获取字段field信息: getField(name): 获取某个public的field,包括父类 getDeclaredField(name): 获取 ...

  7. 廖雪峰Java4反射与泛型-1反射-1Class类

    1.Class类与反射定义 Class类本身是一种数据类型(Type),class/interface的数据类型是Class,JVM为每个加载的class创建了唯一的Class实例. Class实例包 ...

  8. 廖雪峰Java4反射与泛型-2注解-2定义注解

    1.定义注解 使用@interface定义注解Annotation 注解的参数类似无参数方法 可以设定一个默认值(推荐) 把最常用的参数命名为value(推荐) 2.元注解 2.1Target使用方式 ...

  9. 廖雪峰Java4反射与泛型-2注解-1使用注解

    1.Annotation定义 注解是放在Java源码的类.方法.字段.参数前的一种标签.如下 package com.reflection; import org.apache.logging.log ...

随机推荐

  1. cordova填坑

    cordova填坑

  2. 【转】Linux下svn常用指令

    转自: http://blog.csdn.net/myarrow/article/details/8110858 1.将文件checkout到本地目录svn checkout path(path是服务 ...

  3. [OFBiz]简介 二

    1. 执行ant run-install后,生成了55个ofbiz的jar.加上最初的E:\apache-ofbiz-10.04\framework\entity\lib\ofbiz-minerva. ...

  4. [Effective C++ --019]设计class犹如设计type

    前言 我们在编写程序的时候,无论哪一种语言,总是会告诉你这种语言应该有的类型.我们将它们直接拿来使用,可是从来没有考虑过这些类到底是怎么设计出来的! 所幸的是:在OOP中,每当我们定义一个新的clas ...

  5. 在Oracle 11.2的数据库中建表时遇到 RESULT_CACHE (MODE DEFAULT) ORA-00922: missing or invalid option

    在Oracle 11.2的数据库中建表时遇到 RESULT_CACHE (MODE DEFAULT)  ORA-00922: missing or invalid option hostdr:[/ho ...

  6. Win7搭建Django开发环境

    1.官网下载并安装python 2.7.5 2.配置python 环境变量 在Path中加入python安装目录: PATH=PATH;c:\python26 在PATHEXT中加入以下变量,可以直接 ...

  7. poj 2689 Prime Distance(大区间素数)

    题目链接:poj 2689 Prime Distance 题意: 给你一个很大的区间(区间差不超过100w),让你找出这个区间的相邻最大和最小的两对素数 题解: 正向去找这个区间的素数会超时,我们考虑 ...

  8. U813.0操作员功能权限和数据权限的设置

    操作员的权限有功能权限.数据权限.金额权限. 1. 给操作员设置功能权限,操作员才能进入系统进行相关业务操作. Admin用户登录无法修改账套,但可以新建.引入.输出.Demo用户每次只能进入一个账套 ...

  9. 剑指offer例题分享--4

    前言:搁置许久的更新要继续开始了!前一段时间一直在忙项目和C++的学习,所以搁置了!要改变注意了,要用C++进行编写了,因为要不断练习C++! 面试题15: 书中要求只能遍历链表一次,所以代码如下: ...

  10. c#简易学生信息管理系统

    在近期的学习中,我们学习了泛型及泛型集合的概念和使用,泛型是c#中的一个重要概念,为了巩固我们学习的成果,我们可以使用一个实例来进行练习 题目及要求 要求使用Windows窗体应用程序,制作出如上图的 ...


Original url: Access
Created at: 2019-12-10 12:36:19
Category: default
Tags: none

请先后发表评论
  • 最新评论
  • 总共0条评论