import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;public class Test {public static void main(String[] args) {
//        ErasureAndInheritance.test();
//        ArrayMaker.test();
        FilledListMaker.test();}
}/*15.7 擦除的神秘之处Class.getTypeParameters()将返回一个TypeVariable对象数组,表示有泛型声明所声明的类型参数。我之前确实有过这种需求,但是这个方法不可能给我想要的结果问题:因此,你可以知道诸如类型参数标识符和泛型类型边界这类的信息——你却无法知道用来创建某个特定实例的实际的类型参数。Java泛型是使用擦除来实现的,这意味着当你在使用泛型的时候,任何具体的类型信息都被擦除了,你唯一知道的就是你在使用一个对象因此List<String>和List<Integer>在运行时事实上是相同的类型。这两种类型都被擦除成了它们的“原生”类型,即List。理解擦除以及应该如何处理它,是你在学习Java泛型时面临的最大障碍。——既然被擦除了,为什么我们还能取到我们想要的类型——C++中如果你用了泛型,编译器就会对应的生成这个类,这一点还是蛮舒服的。*//*15.7.1 C++的方式C++:template<class T> class Manipulator{T obj;public:Manipulator(T x) { obj = x;}void manipulator() { obj.f();}}Java: 无法通过编译class Manipulator<T>{T obj;public Manipulator(T x) { obj = x; }void manipulator() { obj.f();}}解决问题:为了调用f(),我们必须协助泛型类,给定泛型类的边界,以此告知编译器只能接受这个边界的类型。这里重用了extends关键字<T extends HasF> : 声明T必须具有类型HasF或者从HasF导出的类型,我们说泛型类型参数将擦除到它的第一个边界(可能会有多个边界)。*/
class HasF {public void f() {}
}
class Manipulator<T extends HasF>
{T obj;public Manipulator(T x) { obj = x; }void manipulator() { obj.f();}
}/*在我们的案例中,泛型没有任何贡献。我们完全可以自己执行泛型擦除。这一点很重要:只有当你希望使用的类型参数比某个具体类型(以及它的所有子类型)更加“泛化”时——也就是说,当你希望代码能够跨多个类工作时,使用泛型才有所帮助。——额,为什么不用接口呢?接口不也是这种功能么,甚至比这个还有强大一点因此,类型参数和它们在有用的泛型代码中的应用,通常比简单的类替换要更复杂。但是,不能因此而认为<T extends HasF>形式的任何东西都是有缺陷的。例如,如果某个类有一个返回T的方法,那么泛型就有所帮助,因此它们之后将返回确切的类型。——我想知道,既然类型已经被擦除了,那返回时是如何返回成T的了,难道是编译器私下里进行了一次强制转换?*//*15.7.3 擦除的问题擦除的主要的正当理由是非泛型的代码到泛型到泛型代码的转变过程。擦除的代价是显著的。泛型不能用于显式的引用运行时类型的操作之中,例如转型、instanceof操作和new表达式。因为所有关于参数的类型的信息都丢失了。*/class GenericBase<T>{private T element;public void set(T arg) { element = arg;}public T get(){return  element;}
}class Dervied1<T> extends GenericBase<T> {}
class Dervied2 extends GenericBase {}class ErasureAndInheritance{static void test() {Dervied2 d = new Dervied2();Object obj = d.get();d.set(obj);}
}/*17.5.4 边界处的动作*//*编译器不会给出任何警告,尽管我们从擦除中知道在create()内部的new ArrayList<T>中的<T>被移除了——在运行时,这个类的内部没有任何的<T>。但是,即使编译无法知道有关create()中的T的任何信息,但是它仍旧可以在编译期间确保你放置到result中的对象具有T类型,使其适合ArrayList<T>。*/
class ArrayMaker<T>{//运行时实际保存的是Class<Object>private Class<T> kind;public ArrayMaker(Class<T> kind) {//这个地方在运行时,把一个Class<T>赋给了Class<Object>this.kind=kind;}@SuppressWarnings("unckecked")T[] create(int size) {return (T[]) Array.newInstance(kind,size);}public static void test() {ArrayMaker<String> s = new ArrayMaker<>(String.class);String[] stringArray = s.create(9);
//        System.out.println(Arrays.toString(stringArray));
    }
}
class ListMaker<T>{List<T> create(){return new ArrayList<T>();}public static void test() {ListMaker<String> s = new ListMaker<>();List<String> strs = s.create();}
}
class FilledListMaker<T> {List<T> create(T t, int n) {List<T> result = new ArrayList<T>();for (int i = 0; i < n; i++) {result.add(t);}return  result;}public static void test() {FilledListMaker<String> stringMaker = new FilledListMaker<>();List<String> list = stringMaker.create("Hello",4);System.out.println(list);}
}/*因为擦除在方法体中移除了类型信息,所以在运行时的问题就是边界:即对象进入和离开方法的地点。这些正是编译器在编译期执行类型检查并插入转型代码的地点。*/

转载于:https://www.cnblogs.com/junjie2019/p/10551961.html

Java编程思想:擦除的神秘之处相关推荐

  1. Java中的泛型 --- Java 编程思想

    前言 ​ 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...

  2. 《Java编程思想》读书笔记

    前言:三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第十七章到第十八章的内容,这一次 ...

  3. Java编程思想翻译勘误

    总的来说,Java编程思想是一本好书:但是因为译者可能不懂计算机,很多地方都有严重错误. 之前和朋友抱怨过,朋友提议抱怨无用不如干点实事.遂决定边看边将自己找到的翻译错误贴出来,希望能给别人一些帮助. ...

  4. 《Java编程思想》读书笔记(二)

    三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第一章到第十章的内容,这一次记录的是第 ...

  5. 【java】《java编程思想》 读书笔记

    之前主要用的C++的比较多,之前花了快2个月的实际认真系统全面的学习了以下java的基础语法,<java编程思想>这本书翻译水平确实不是很好,很多话读着会比较拗口.推荐读之前,先去网上搜索 ...

  6. java编程思想--概述

    之前主要用的C++的比较多,之前花了快2个月的实际认真系统全面的学习了以下java的基础语法,<java编程思想>这本书翻译水平确实不是很好,很多话读着会比较拗口.推荐读之前,先去网上搜索 ...

  7. 《JAVA编程思想》学习笔记:第19章(枚举)

    目录 Java编程思想(一)第1~4章:概述 Java编程思想(二)第5章:初始化和清理 Java编程思想(三)第6章:访问权限 Java编程思想(四)第7章:复用类 Java编程思想(五)第8章:多 ...

  8. Java编程思想学习(一)----对象导论中多态的理解

    1.1抽象过程 1)万物皆对象. 2)程序是对象的集合,他们通过发送消息来告知彼此所要求做的. 3)每个对象都有自己的由其他对象所构成的存储. 4)每个对象都拥有其类型. 5)某一特定类型的所有对象都 ...

  9. java编程思想怎么样_读完java编程思想后的思考?

    谢邀,这本书真的给我带来很多思考. 我的java入门不是java编程思想,学校的教材是一本紫色的书,已经忘了叫什么名字了,里面内容倒挺新还讲了些javafx.但那本书实在是太浅并且结构混乱,以至于我和 ...

最新文章

  1. OpenGL(glut)模拟太阳系:太阳,地球,月球,火星
  2. JetsonTX2上安装tensorflow的心酸史
  3. thinkcmf安装模板需要点击右键打开新页面的解决办法
  4. How to use USB to do charger detection instead of PMIC?
  5. matlab 里try用法,matlab在整个程序(全局)中使用try-catch来报告错误
  6. 【渝粤题库】陕西师范大学800006 世界地理
  7. 伍楼阁使用的WordPress代码高亮插件使用说明
  8. sql2000 数据库置疑解决办法
  9. 电力电子仿真软件Plecs数据类型
  10. 扬州大学复试1301软件工程【自制题库个人复习用】
  11. unix源码分析_UNIX网络分析
  12. python制作的简单程序_Python如何制作简易收银小程序
  13. 如何使用计算机上合并计算方法,excel合并计算的方法步骤详解
  14. 【R语言技巧】apply篇 sumNotes
  15. matlab零状态响应幅度频谱,matlab零状态、零输入响应
  16. 【7月cocos学习笔记】
  17. Java代码给csv文件加水印_如何给文件加上水印?
  18. Kafka原理+操作+实战
  19. 吴佳怡最新街拍曝光  潮酷girl演绎初秋时尚
  20. java工程师主要是做什么的?我来聊聊如何提高自身的工作水平

热门文章

  1. 倪光南:中国网络安全为何要强调“自主可控”?
  2. kuberbetes的架构与kubernetets集群搭建
  3. Linux下mysql备份
  4. HTML中引入CSS的方法
  5. 程序员,你想不想进大厂?
  6. 看看这些大龄程序员都做了些什么
  7. 是什么影响了MySQL性能?
  8. 剑指offer:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
  9. 【Python】青少年蓝桥杯_每日一题_2.03_绘制菱形和圆
  10. Android --- SDK 和 API 是什么意思