范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

互联网大厂面试什么是Java语言中的类型擦除?

  什么是泛型?
  首先来讲泛型操作是从JDK5开始引入Java语言的一个新特性,其允许在定义类或者是接口的时候使用一个类型参数,并且这个类型参数可以在使用的时候被替换成一个具体的参数。使用泛型最大的好处就是可以极大的提升代码的复用性。
  以List为例,我们可以在List集合中放入任何的数据类型例如String、Integer等等,当然也可以放入对象类型。如果不使用泛型那么就会出现想要使用String类型的List集合的时候需要定义一个String类型的List集合,需要使用Integer类型的List的集合的时候就需要定义相应类型的集合,这样做就有点复杂了,为了解决这样的问题,就出现了我们的泛型操作。各种语言对泛型操作的处理机制?
  通常情况下,编译器需要通过如下的几种方式来对泛型数据类型进行处理。在实例化一个泛型类或者是一个泛型类型的方法的时候,对于每一种数据类型都产生一份新的代码来进行具体的支撑,例如针对List的泛型操作,如果使用了String类型,就生成一份String类型的List代码,使用Integer就生成一份Integer的List代码。对于每个使用泛型操作的类或者方法来讲生成的代码都是唯一的一份,并且将所有的类型通过映射都映射到泛型上,在需要具体使用的时候对类型进行判断进行转换,使得泛型能够正常的操作。
  在C++语言中的泛型就是通过第一种方式来实现的,也就是说C++语言的编译器会为每个泛型都生成一份对应的执行代码,在代码中String类型与Integer类型对应的泛型类是不一样的。而这样带来的后果就是在编译后的代码中会存在大量的冗余代码。
  在C#语言中泛型操作无论是在源码中还是在编译后的中间代码中或者是在运行时期的代码中都是存在不同类型的数据代码,唯一不同的是这些代码是在运行期间生成的,并且有自己的虚地址表示,这种方式被称为是类型膨胀。而基于这种方式所实现的泛型操作被称为是真实泛型。
  在Java语言中的泛型与前面两者是不一样的,它只在源代码中存在,在编译之后的字节码中就会被替换成原生类,并且在相应的代码中加入了强制类型转换。所以对于Java语言而言,ArrayList和ArrayList其实就是同一个类型,对于Java来讲泛型操作可以称之为Java语言的优势,而在Java语言中使用到的对泛型的操作则是被称为是类型擦除,而基于这种方法实现的泛型操作被称为是伪泛型。
  C++和C#是使用Code specialization的处理机制,前面提到,他有一个缺点,那就是会导致代码膨胀。另外一个弊端是在引用类型系统中,浪费空间,因为引用类型集合中元素本质上都是一个指针。没必要为每个类型都产生一份执行代码。而这也是Java编译器中采用Code sharing方式处理泛型的主要原因。
  Java编译器通过Code sharing方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。将多种泛型类型实例映射到唯一的字节码表示是通过类型擦除(type erasure)实现的。什么是Java语言的类型擦除?
  什么是类型擦除?类型擦除是指通过类型参数组合的方式,将泛型类型的实例对象关联到同一份字节码文件上。编译器最终只会为泛型类型提供一份统一的字节码,并且将相关的实例对象关联到这一份字节码文件上。
  类型擦除的关键就是在于从泛型类型中清除类型参数的信息,并且在使用的时候需要对传入的真实参数进行类型检查和类型转换。可以简单的理解为将泛型类型的代码转换成了普通类型的代码,只不过对于Java编译器来讲,是将对应的字节码文件进行了转换。
  类型擦除器过程主要分为如下两个步骤将所有的泛型有关的参数用最顶级的父类进行替换移除所有的具体类型相关的参数Java语言泛型处理过程
  首先来看一段简单的代码public static void main(String[] args) {       Map map = new HashMap();       map.put("name", "nihui");       map.put("age", "22");       System.out.println(map.get("name"));       System.out.println(map.get("age"));   }
  经过反编译之后的结果如下public static void main(String[] args) {       Map map = new HashMap();       map.put("name", "nihui");       map.put("age", "22");      System.out.println((String) map.get("name"));       System.out.println((String) map.get("age"));   }
  从反编译的结果来看,我们对于KV键值对的处理都已经不存在了,只留下了我们想要实现的部分的代码,就是直接进行类型的存储。interface Comparable {     public int compareTo(A that); }  public final class NumericValue implements Comparable {     private byte value;      public NumericValue(byte value) {         this.value = value;     }      public byte getValue() {         return value;     }      public int compareTo(NumericValue that) {         return this.value - that.value;     } }
  反编译之后的结果 interface Comparable {   public int compareTo( Object that); }   public final class NumericValue     implements Comparable {     public NumericValue(byte value)     {         this.value = value;     }     public byte getValue()     {         return value;     }     public int compareTo(NumericValue that)     {         return value - that.value;     }     public volatile int compareTo(Object obj)     {         return compareTo((NumericValue)obj);     }     private byte value; }
  编译之前的代码public class Collections {     public static > A max(Collection xs) {         Iterator xi = xs.iterator();         A w = xi.next();         while (xi.hasNext()) {             A x = xi.next();             if (w.compareTo(x) < 0)                 w = x;         }         return w;     } }
  反编译之后的代码public class Collections {     public Collections()     {     }     public static Comparable max(Collection xs)     {         Iterator xi = xs.iterator();         Comparable w = (Comparable)xi.next();         while(xi.hasNext())         {             Comparable x = (Comparable)xi.next();             if(w.compareTo(x) < 0)                 w = x;         }         return w;     } }
  第2个泛型类Comparable 擦除后 A被替换为最左边界Object。Comparable的类型参数NumericValue被擦除掉,但是这直 接导致NumericValue没有实现接口Comparable的compareTo(Object that)方法,
  于是编译器在其中添加了一个桥接方法。 从第3个示例中限定了类型参数的边界>A,A必须为Comparable的子类,按照类型擦除的过程,先讲所有的类型参数 ti换为最左边界Comparable,然后去掉参数类型A,得到最终的擦除后结果。泛型带来的问题有哪些?
  一、泛型方法的重载public class GenericTypes {        public static void method(List list) {           System.out.println("invoke method(List list)");       }        public static void method(List list) {           System.out.println("invoke method(List list)");       }   }
  从上面这段代码中我们可以看到两个方法由于参数类型不同形成了方法的重载,但是这段代码在实际编译的过程中是没法通过的,因为在之前的内容中我们提到过List和List在Java语言来看由于类型擦除会将其认定为同一个类型,这样就会变成两个参数一样并且方法名一样的方法,这个在Java操作中是不被允许的。
  二、遇到Catch
  我们都知道在Java语言中会经常遇到异常捕获,如果我们在开发过程中自定义了一个通用的异常处理,那么就会有各种各样的异常被通用的异常处理捕获,这个时候如果想要实现不同的异常进行不同的处理那就非常难了
  三、当泛型类型包含静态变量public class StaticTest{     public static void main(String[] args){         GT gti = new GT();         gti.var=1;         GT gts = new GT();         gts.var=2;         System.out.println(gti.var);     } } class GT{     public static int var=0;     public void nothing(T x){} }
  如上面代码所示,如果在泛型中遇到的静态变量,会出现什么样的结果呢?我们都知道静态变量是与类的存在是有关的,也就是说对于一个泛型如果与到了一个静态变量,那么这个静态变量就是对于所有的泛型类所共享的。而上面的代码执行结果也就显而易见了。输出的结果应该是2。因为对于第一个操作来讲,将泛型中的静态变量改成了1,但是由于静态变量是共享的,在第二个操作中就会将对应的值改成2,所以最终的输出结果应该是2。总结
  综上所述,在虚拟机中没有泛型的概念,只有普通类与普通方法的概念,所有泛型类型在编译之后都会被进行类型擦除操作,也就是说泛型并没有自己独立存在的对象进行存储,也就不会有反射等一些高级操作。在使用泛型操作的时候一定要提前的去对类型做处理让编译器提前就知道需要处理的类型的是什么。这样可以在提升编译器处理效率的同时也可以避免带来各种各样的问题。

佟丽娅近态曝光粉红色长发差别大,网友直呼认不出有网友晒出了佟丽娅最新的照片,照片中的佟丽娅穿着蓝绿色的雪纺波纹紧身裙搭配浅蓝色风衣,乌黑的长发染成了粉红色。佟丽娅的妆发的变化之大,让网友们感到十分惊讶,这也算是突破了佟丽娅以前张常宁大婚后回门宴抢镜!女排传奇露面没郎平,网友礼服三万多北京时间8月8日,中国体坛轰动大事还在继续,张常宁和吴冠希的世纪婚礼带来的余波也同样没有散去。一位是中国女排的三大王牌巨头之一,还有一个则是中国男篮的前任国手,也是现在江苏队的顶薪WNBA传奇球星即将落幕!苏伯德发表退役演讲詹姆斯连续发声致敬北京时间8月8日,WNBA常规赛继续进行,西雅图风暴迎来常规赛主场的最后一场比赛。球队传奇球星苏伯德在此前已经宣布,这将是她职业生涯的最后一个赛季,赛季结束后将会退役。因此,这是苏孙怡董子健发文官宣离婚,今后将共同抚养女儿,5年婚姻就此结束就在今天上午,演员董子健在自己的社交平台,一反常态地发布了一条动态咱都好好的。并且在动态中了自己的妻子孙怡。而孙怡在一分钟后也在社交平台发布动态从前祝我们,今后祝你我。同样也了董子好突然!董子健孙怡离了这一脚踢开了周一疲惫,什么情况啊啊啊啊!关键都这时候了,cf粉还在嗑。那啥,断头饭也是饭。然后查了查两人的微博互动,原来,今年6月孙怡过生日,董子健对她的称呼是大福妈。划重点了哈,京圈太子董子健孙怡高调官宣离婚提起董子健和孙怡相信很多不关注娱乐圈的朋友,根本就不知道他们是谁。对娱乐圈有了解的人可能会听说京圈太子爷的尊称,可见在娱乐圈背景人脉是多么广,但论作品演技在十八线以外了吧,没有响当孙怡董子健离婚,真的太意外了,网友再也不相信爱情了孙怡董子健离婚,真的太意外了,他俩在我印象中一直感情不错,目前双方工作室均已发布离婚声明。从前他们官宣在一起的时候,小编还觉得他俩不太般配,但是后来看他俩挺好的,就硬是看顺眼了,这陈亚男再次直播征婚,却被闺蜜抢风头后,发大招逼网友让自己带货自从陈亚男和朱小伟离婚后,她的名声可谓是呈直线下降,不管是直播还是发布的动态,评论底下也都是骂声一片。陈亚男再次直播征婚之后,陈亚男也尝试了很多的不同的风格,甚至还重新注册了新的账佟丽娅近态曝光粉红色长发差别大,网友直呼认不出有网友晒出了佟丽娅最新的照片,照片中的佟丽娅穿着蓝绿色的雪纺波纹紧身裙搭配浅蓝色风衣,乌黑的长发染成了粉红色。佟丽娅的妆发的变化之大,让网友们感到十分惊讶,这也算是突破了佟丽娅以前张常宁大婚后回门宴抢镜!女排传奇露面没郎平,网友礼服三万多北京时间8月8日,中国体坛轰动大事还在继续,张常宁和吴冠希的世纪婚礼带来的余波也同样没有散去。一位是中国女排的三大王牌巨头之一,还有一个则是中国男篮的前任国手,也是现在江苏队的顶薪过去11年,勇士选了10名首轮秀!2人已无球可打,仅1人拿千万年薪NBA三十支球队,每年都会基于战绩高低,得到不同顺位的首轮选秀权。勇士队也不例外,过去十一年里,金州总共得到了十个首轮签。这十个首轮,有些是规则内自动获取的,有些则是通过交易得到的
山间小城津和野,这里是文豪森鸥外的故乡徐静波编者按日本有不少有趣的小镇,值得细细品味。津和野就是如此,它位于日本西部日本海沿岸的岛根县境内,人口只有六千多,自然风光秀丽,也保留着江户时代的古朴韵味。同时,这里也人才辈出口罩在手,端午这样出门旅游,房子侄女住,回来一看房子不敢认随着疫情的好转,很多长期在家工作的朋友一定准备好规划一份go上路的出行指南,而像go上路这样的好车显然是必不可少的。今天就趁热打铁,推荐一款非常适合去公路旅行的SUV。它们外观出众长寿专家活不过六十岁?养生是否是个伪命题?前几天读到一篇文章,讲的是中国一些养生专家因为养生过度,年纪不大就去世的事情,比如2008年,同仁堂董事长张生瑜因心脏病突发去世,享年39岁2019年6月14日,著名养生专家梅墨生林心如牵着女儿外出逛街!5岁小海豚太像妈,母女俩跟不上霍建华林心如是大家比较喜欢的女演员之一了,可以说是最早的偶像女演员,不管是出演紫薇这个角色还是在男才女貌中的精彩表现,都让大家对林心如有一个深刻的了解,林心如的古装和现代装都很好看,小编我与海豚的第一次大自然之旅小满,一切皆圆满,喜爱旅游的人,大致都是喜欢自由行走的人,徒步有徒步的快乐,自驾游有自驾游的开心,以往总是因为路途相对遥远,公共交通工具不算很便利,所以我的脚步到不了的地方,就让我看春日迟迟再出发大结局没有复婚的郭柯宇,很好,很美01hr春日迟迟再出发大结局,我等这一期等很久了,就是为了看郭柯宇。一袭白裙,郭柯宇披散着头发,好美。所有的嘉宾看到郭柯宇的时候都惊呆了,她怎么可以这么美,舞台上的她真的好迷人。郭海豚会算加法?企鹅和北极熊做邻居?圣亚海洋世界满足你好奇心行游大连儿时生活像一个五彩斑斓的梦,使人恋恋不舍,使人憧憬,儿时生活中产生的一件件有意思的事,经常将我带到难忘的回忆中。小时候总缠着父母带我去主题乐园玩,但是他们总是没时间,今天我快乐假期,在路上的春色毫无疑问五一假期是最舒适的时刻,温暖的天气普照大地,五一假期又可以放松一下,每当无聊假期的时候,我们都想爱出去游玩,看看外面精彩的世界,看看在路上的旅行景色,这就是假期里最好的时光10万级纯电动小车,最高续航超400km,比亚迪海豚和零跑S01该选谁在电动汽车快速发展的当下,不少的品牌都推出了价格亲民的纯电动车型,并拥有不错的空间和实用性,例如比亚迪去年上市的海豚,以及零跑S01。两款纯电小车价格都在10万级,非常适合家庭代步爷青回!上美影首个穿越式VR动画直播于儿童节上线6月1日,QQ浏览器联合上海美术电影制片厂推出浏览中国动画百年系列活动,QQ浏览器于儿童节当晚联合上美影推出首个穿越式VR动画直播,持续6个小时播放13部经典动画片。此外,用户从Q阳光正好,微风不燥,在这个初夏走进美景中吧阳光正好,微风不燥光影落在那一方醉绿的田野林草间云雾炊烟笼盖乡居萌动的虫鸟平添生机在初夏时光边走边拍收获的是惬意的满足香港中国旅游出版社每周精选图片(05。2305。292022)