java泛型——桥方法

【0】README

0.1)以下内容转自: http://www.cnblogs.com/ggjucheng/p/3352519.html


【1】泛型约束和局限性—— 类型擦除所带来的麻烦

1.1)继承泛型类型的多态麻烦。(—— 子类没有覆盖住父类的方法 )

  • 看看下面这个类SonPair
class SonPair extends Pair<String>{  public void setFirst(String fir){....}  
}
  • 很明显,程序员的本意是想在SonPair类中覆盖父类Pair的setFirst(T fir)这个方法。但事实上,SonPair中的setFirst(String fir)方法根本没有覆盖住Pair中的这个方法。
  • 原因很简单,Pair在编译阶段已经被类型擦除为Pair了,它的setFirst方法变成了setFirst(Object fir)。 那么SonPair中setFirst(String)当然无法覆盖住父类的setFirst(Object)了。
    这对于多态来说确实是个不小的麻烦,我们看看编译器是如何解决这个问题的。
  • 编译器 会自动在 SonPair中生成一个桥方法(bridge method ) :
public void setFirst(Object fir)
{setFirst((String) fir)
} 
  • 这样,SonPair的桥方法确实能够覆盖泛型父类的setFirst(Object) 了。而且桥方法内部其实调用的是子类字节setFirst(String)方法。对于多态来说就没问题了。

1.2)问题还没有完,多态中的方法覆盖是可以了,但是桥方法却带来了一个疑问:

  • 现在,假设 我们还想在 SonPair 中覆盖getFirst()方法呢?
class SonPair extends Pair<String>
{public String getFirst(){....}  
}  
  • 由于需要桥方法来覆盖父类中的getFirst,编译器会自动在SonPair中生成一个 public Object getFirst()桥方法。 (干货——引入了桥方法,该方法是编译器生成的,不是程序员码出来的)
  • 但是,疑问来了,SonPair中出现了两个方法签名一样的方法(只是返回类型不同):
    • ①String getFirst() // 自己定义的方法
    • ②Object getFirst() // 编译器生成的桥方法
  • 难道,编译器允许出现方法签名相同的多个方法存在于一个类中吗?事实上有一个知识点可能大家都不知道:
    • ① 方法签名 确实只有方法名+参数列表 。这毫无疑问!
    • ② 我们绝对不能编写出方法签名一样的多个方法 。如果这样写程序,编译器是不会放过的。这也毫无疑问!
    • ③ 最重要的一点是: JVM会用参数类型和返回类型来确定一个方法。 一旦编译器通某种方式自己编译出方法签名一样的两个方法 (只能编译器自己来创造这种奇迹,我们程序员却不能人为的编写这种代码)。JVM还是能够分清楚这些方法的,前提是需要返回类型不一样。

1.3) 泛型类型中的方法冲突

//在上面代码中加入equals方法  
public class Pair<T>{  public boolean equals(T value){  return (first.equals(value));  }  
} 
  • 这样看似乎没有问题的代码连编译器都通过不了:
    这里写图片描述
  • 【Error】 Name clash(命名冲突): The method equals(T) of type Pair has the same erasure as equals(Object) of type Object but does not override it。

编译器说你的方法与Object中的方法冲突了。这是为什么?

  • 开始我也不太明白这个问题,觉得好像编译器帮助我们使得equals(T)这样的方法覆盖上了Object中的equals(Object)。
  • 经过大家的讨论,我觉得应该这么解释这个问题?
    • 首先、我们都知道子类方法要覆盖,必须与父类方法具有相同的方法签名(方法名+参数列表)。而且必须保证子类的访问权限>=父类的访问权限。这是大家都知道的事实。
    • 然后、在上面的代码中,当编译器看到Pair中的equals(T)方法时,第一反应当然是equals(T)没有覆盖住父类Object中的equals(Object)了。
    • 接着、编译器将泛型代码中的T用Object替代(擦除)。突然发现擦除以后equals(T)变成了equals(Object),糟糕了,这个方法与Object类中的equals一样了。
  • 基于开始确定没有覆盖这样一个想法,编译器彻底的疯了(精神分裂)。
  • 然后得出两个结论:①坚持原来的思想:没有覆盖。但现在一样造成了方法冲突了。 ②写这程序的程序员疯了(哈哈)。
  • 再说了,拿Pair对象和T对象比较equals,就像牛头对比马嘴,哈哈,逻辑上也不通呀。

1.4)没有泛型数组一说

Pair<String>[] stringPairs=new Pair<String>[10];
Pair<Integer>[] intPairs=new Pair<Integer>[10];
  • 这种写法编译器会指定一个Cannot create a generic array of Pair的错误
    • 我们说过泛型擦除之后,Pair[]会变成Pair[],进而又可以转换为Object[];
    • 假设泛型数组存在,那么
Object[0]=stringPairs[0]; Ok
Object[1]=intPairs[0]; Ok
  • 这就麻烦了,理论上将Object[]可以存储所有Pair对象,但这些Pair对象是泛型对象,他们的类型变量都不一样,那么调用每一个Object[]数组元素的对象方法可能都会得到不同的记过,也许是个字符串,也许是整形,这对于JVM可是无法预料的。
  • 记住: 数组必须牢记它的元素类型,也就是所有的元素对象都必须一个样,泛型类型恰恰做不到这一点。即使Pair< String>,Pair< Integer>… 都是Pair类型的,但他们还是不一样。

总结:泛型代码与JVM

  • 虚拟机中没有泛型,只有普通类和方法。
  • 在编译阶段,所有泛型类的类型参数都会被Object或者它们的限定边界来替换。(类型擦除)
  • 在继承泛型类型的时候,桥方法的合成是为了避免类型变量擦除所带来的多态灾难。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331667.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hibernate框架之入门配置

一、Hibernate导入相关的包参考&#xff1a;http://blog.csdn.net/tunni/article/details/54982160这些包包括相应数据库驱动、hibernate.zip下lib目录下的jar包&#xff0c;其中必须包是required目录下的.jar二、在项目classpath&#xff08;类路径&#xff0c;即src目录下&am…

annotations_Spring Annotations我从来没有机会使用第2部分:@ConfigurationProperties

annotations几天前&#xff0c;我在检查其他内容时不小心偶然发现了Spring Boot项目中的Spring注释。 我们都知道如何将带有“ Value”的属性值绑定到类&#xff0c;并且我们都知道如果要绑定多个属性&#xff0c;这可能会很麻烦。 Spring Boot可以为您提供帮助。 您可以使用“…

linux下检测硬盘,【转载】linux下硬盘监控诊断工具SmartTools

对于windwos下raid卡具备告警功能&#xff0c;当硬盘故障、raid卡告警时&#xff0c;可以发邮件给管理员。IBM、HP、Dell都支持。但在linux下&#xff0c;就没有找到相关的好工具了&#xff0c;今天到陈沙克的博客上到一篇关于linux下硬盘监控诊断工具SmartTools&#xff0c;感…

hibernate框架之主键生成

一、 hibernate 框架中主键的生成策略 (1)native: 表示由设置的方言决定采用什么数据库生成主键方式&#xff0c;根据底层数据库能力选择identity、sequence中的一个。 例如&#xff1a;在MySQL中会采用自增长的方式&#xff0c;主键字段必须都是整形类型&#xff1b;在Oracle数…

java泛型通配符

【0】README 0.1&#xff09;以下内容转自&#xff1a; http://blog.csdn.net/baple/article/details/25056169 0.2&#xff09; T 有类型 &#xff1f; 未知类型 一、通配符的上界&#xff08;extends关键字&#xff09; 既然知道List并不是List的子类型&#xff0c;那就需…

jdk 1.8 内存可见性_JDK 14中的常规,安全和确定性外部内存访问

jdk 1.8 内存可见性在“ JDK 14 Rampdown&#xff1a;Build 27 ”一文中&#xff0c;我总结了JDK 14 Early Access Build &#xff03;27中新增的许多针对JDK 14的功能。 已经存在另一种JDK 14 Early Access Build&#xff0c;并且此[ Build 28&#xff08;2019/12/18&#xff…

linux开启防火墙ping,如何在防火墙中放开ping

如何在防火墙中放开ping操作时需要注意的几项:1,注意iptables各版本间的区别我们的server os最旧的版本是redhat 7.3 kernel是2.4.20-18.7最新的server os最新的版本是centos 5, kernel是2.6.18-8差距很大iptables以模块形式运行在内核的空间,用lsmod可以看到所以它与内核的版本…

Hibernate: You have an error in your SQL syntax; check the manual that corresponds to your MySQL

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ...Hibernate 出现这样的错误是因为表中的字段名使用了sql的保留字&#xff0c;不要使用保留字 一、mysql的保留字主要有&#xff1…

java.io 包

java.io 通过数据流、序列化和文件系统提供系统输入和输出。 请参见&#xff1a; 接口摘要CloseableCloseable 是可以关闭的数据源或目标。DataInputDataInput 接口用于从二进制流中读取字节&#xff0c;并根据所有 Java 基本类型数据进行重构。DataOutputDataOutput 接口用…

linux系统怎么安装pr,Linux安装后的配置

系统:CentOS-6.31.NVIDIA驱动的安装与配置Linux本身的显卡驱动是能够满足平常应用的&#xff0c;但是有时候我们为了获得3D效果&#xff0c;或者更流畅的视频体验&#xff0c;我们会安装新的显卡驱动。这时候就需要安装闭源驱动了&#xff0c;个人认为闭源的驱动更为好一些&…

java第三阶段源代码_有效Java第三版的源代码已更新为使用较新的功能

java第三阶段源代码那些已经阅读了有效Java 第三版的人可能知道与该书相关的源代码可以在GitHub上获得 。 jbloch / effective-java-3e-source-code项目拥有1700多个星星&#xff0c;截至撰写本文时&#xff0c;它已被分叉了近800次。 在有效Java的第三版中&#xff0c; Java的…

《线性代数及其应用》

【0】README 0.1&#xff09;以下内容转自&#xff1a; http://blog.csdn.net/ljbkiss/article/details/7194719 【1】正文干货 1.1&#xff09; 断断续续的终于把 《线性代数及其应用&#xff08;Linear Algebra and Its Application&#xff09; David C.Lay》 这本书看完了…

micrometer_具有InlfuxDB的Spring Boot和Micrometer第1部分:基础项目

micrometer对于那些关注此博客的人来说&#xff0c;难怪我会经常使用InfluxDB。 我喜欢这样一个事实&#xff0c;它是一个真正的单一用途的数据库&#xff08;时间序列&#xff09;&#xff0c;具有许多功能&#xff0c;并且还带有企业支持。 Spring也是我选择的工具之一。 因…

如何在win7(xp)home version下安装 rose 32 bit

【0】README 0.1&#xff09; 以下部分内容转自 http://blog.csdn.net/encienqi/article/details/5578725 【1】 干货开始 如果是家庭版(win7 or WindowsXPHomeEdition)请先按以下步骤修改部分文件后再安装&#xff1a; 1.1&#xff09;安装Microsoft Orca工具 step1&#x…

接口 Closeable

java.io 接口 Closeable public interface Closeable Closeable 是可以关闭的数据源或目标。调用 close 方法可释放对象保存的资源&#xff08;如打开文件&#xff09;。 从以下版本开始&#xff1a;1.5方法摘要 void close() 关闭此流并释放与此流关联的所有系统资源。 方法详…

Linux下python包放在哪,在alpinlinux中使用apk安装的Python包

我想用apk在Alpine Linux中安装一些Python包。我用numpy作为下面的例子。文档文件FROM python:3-alpineRUN apk add --update py3-numpy我建立我的码头形象$ docker build -t python-numpy .Sending build context to Docker daemon 2.048kBStep 1/2 : FROM python:3-alpine---…

spring 消息传递机制_Spring再次涵盖了您:继续进行消费者驱动的消息传递合同测试...

spring 消息传递机制在上一篇文章中&#xff0c;我们已经开始讨论基于消息的通信中的消费者驱动的合同测试 。 在今天的帖子中&#xff0c;我们将在测试工具箱中包含另一个工具&#xff0c;但是在此之前&#xff0c;让我对显微镜下的系统进行快速回顾。 它有两项服务&#xff0…

接口 DataInput

java.io接口 DataInput 所有已知子接口&#xff1a;ImageInputStream, ImageOutputStream, ObjectInput所有已知实现类&#xff1a;DataInputStream, FileCacheImageInputStream, FileCacheImageOutputStream, FileImageInputStream, FileImageOutputStream, ImageInputStreamI…

java反射机制总结

【0】README 0.1&#xff09;以下内容转自&#xff1a; http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html 0.2&#xff09;for source code, please visit &#xff08;1~14 source code : https://github.com/pacosonTang/core-java-volume/blob/master…

c语言系统时间的作用,C语言得到当前系统时间

void getTime(){//获取当前系统时间time_t tTime;//距离1900年1月1日的秒数char str[80];struct tm* stTim;//时间结构time(&tTime);stTim localtime(&tTime);strftime(str,sizeof(str),"%Y%m%d%T",stTim);//格式化时间printf(str);}格式化时间的格式%a 星期…