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

【0】README

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


【1】翻译泛型表达式

1.1)当程序调用泛型方法时, 如果擦除了泛型返回类型, 编译器插入类型转换;

  • 1.1.1)看个荔枝:
Pair<Employee> buddies = ...
Employee buddy = buddies.getFirst();
  • 擦除getFirst的返回类型后将返回Object类型。 编译器自动插入 Employee 的强制类型转换。
  • 也就是说, 编译器吧这个方法调用翻译为两条虚拟机指令(Commands):
    • C1)对原始方法 Pair.getFirst 的调用;
    • C2)将返回的Object类型 强制转换为 Employee 类型;

1.2)当存取一个泛型域时也要插入强制类型转换。

  • 1.2.1)假设 Pair 类的first 域 和 second 域都是 公有的(这不是种好的编程风格, 但在java语法中,这是合法的)。
    表达式: Employee buddy = buddies.first; 也会在结果字节码中插入强制类型转换;

【2】翻译泛型方法

2.1)类型擦除也会出现在泛型方法中。

public static <T extends Comparable> T min(T[] a):是一个完整的方法族;
  • 2.1.1)擦除类型后, 只剩下一个方法:
public static Comparable min(Comparable[] a)
  • 注意, 类型参数T 已经被擦除了, 只留下了限定类型 Comparable;

2.2)方法擦除带来了两个复杂问题。

  • 2.2.1)看个荔枝:
class DateInterval extends Pair<Date>
{public void setSecond(Date second){if(second.compareTo(getFirst()) >= 0)super.setSecond(second);}
}

对以上代码的分析(Analysis):

  • A1)上述类的类型变量擦除后, 为
class DateInterval extends Pair // after erasure
{public void setSecond(Date second){if(second.compareTo(getFirst()) >=0)super.setSecond(second);}
}
  • A2)令人感到奇怪的是, 存在另一个从Pair 继承的setSecond方法, 即
public void setSecond(Object second)

这里写图片描述

  • Attention)此时要注意, DateInterval内部应该是重写了 Pair的 setSecond方法, 结果擦除类型参数后, 就不是重写了, 破坏了类的多态性;

A3)它们显然不是同一种方法, 因为有不同的类型参数, 一个是Object , 而另一个是 Date;(这里是干货)
A4)然而不应该不一样, 考虑下面的语句序列:

DateInterval interval = new DateInterval();
Pair<Date> pair = interval; // OK--assignment to superclass
pair.setSecond(aDate); // "那这条语句调用哪个 setSecond方法呢? 是 setSecond(Object) 还是 setSecond(Date) 呢?"
  • A5)这里, 希望对setSecond 的调用 具有多态性, 并调用最合适的那个方法。 由于pair 引用DateInterval 对象,所以应该调用 DateInterval.setSecond;
  • A6)出现的问题:在于类型擦除与多态发生了冲突, 确实, 如上面的Attention所说, 变量类型擦除破坏了类的多态性;
  • A7)解决方法: 就需要编译器在 DateInterval 类中生成一个桥方法(bridge method):
public void setSecond(Object second) //这里就调用了 重写的 父类 DateInterval(Object)
{setSecond((Date)second)}

2.3)上述引入了桥方法:要想了解他的工作过程, 跟踪下列语句 pair.setSecond(aDate);

  • 2.3.1)变量pair 已经说明为类型 Pair , 并且这个类型只有一个简单的方法叫做 setSecond, 即 setSecond(Object);
  • 2.3.2)虚拟机用 pair 引用的对象调用这个方法: 这个对象是 DateInterval 类型的, 因而将会调用 DateInterval.setSecond(Object) 方法;
  • 2.3.3)这个方法是合成的桥方法: 它调用 DateInterval.setSecond(Date)方法,在正是我们想要的;

2.4)桥方法也可以变得很奇怪, 如 DateInterval 方法覆盖了 getSecond()方法:

class DateInterval extends Pair<ate>
{public Date getSecond() {return (Date) super.getSecond().clone();}    
}

对以上代码的分析(Analysis):

  • A1)在擦除的过程中, 有两个getSecond方法:
    • A1.1) Date getSecond() // defined in DateInterval
    • A1.2) Object getSecond() // overrides the method defined in Pair to call the first method
  • A2)不能这样编写代码(因为具有相同参数的两个方法是不合法的, 他们都没有参数)。
  • A3)但在虚拟机中, 用参数类型和返回类型确定一个方法, 因此, 编译器可能产生两个仅返回 类型不同的 方法字节码, 虚拟机能够正确处理这个情况;
    Annotation)

  • A1)桥方法不仅用于泛型类型; 还有, 在一个方法覆盖另一个方法时可以指定一个更严格的返回类型:

public class Employee implements Clonealbe
{public Employee clone() throws CloneNotSupportedException() {}
}

对以上代码的分析(Analysis):

  • A1) Object.clone 和 Employee.clone 方法被说成具有协变的返回类型;(具有协变的返回类型)
  • A2)实际上, Employee 类有两个克隆方法(Methods):
    • M1) Employee clone();// defined above
    • M2) Object clone() ; // synthesized bridge method, overrides Object.clone;
  • A3)合成的桥方法调用了新定义的方法;

Conclusion)总之, 需要记住有关java泛型转换的事实:

  • C1)虚拟机中没有泛型, 只有普通的类和方法;
  • C2)所有的类型参数都是用它们的限定类型替换;
  • C3)桥方法被合成来保持多态;
  • C4)为保持类型安全性, 必要时插入强制类型转换;

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

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

相关文章

redis 受攻击怎么办?_最受欢迎的6个最常用的Redis库

redis 受攻击怎么办?Redis当前是世界上最受欢迎的键值商店&#xff0c; 它通过提供高速度和低延迟以及针对应用程序开发人员的灵活功能集&#xff0c;赢得了广泛的采用率 。 Redis是一个内存中的数据结构存储&#xff0c;用作根据BSD许可分发的数据库&#xff0c;缓存和消息代…

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

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 调用遗留代码 的知识&#xff1b; 【1】调用遗留代码相关 1.1&#xff09;设计java 泛型的目的&#xff1a; 允许泛型代码和遗留代码间能够相互操作&#…

java oracle 字符_Oracle转义字符

1、oracle 特殊字符 转义关键词&#xff1a; oracle 转义环境&#xff1a;oracle 9i plsql在plsql里边执行:update userinfo set pageurlmyjsp?page1&pagesize10 where idtest这条sql语句往数据库的pageurl字段放进去了一个url地址&#xff0c;但是执行的时候却并非那…

jmeter进行性能测试_使用JMeter进行性能测试

jmeter进行性能测试在开发复杂的高可用性软件项目时&#xff0c;性能至关重要。 在当今这样的时代尤其如此&#xff0c;除了闪电般的实时数据可访问性之外&#xff0c;其他任何事情都受到惩罚。 当谈论有时需要的大量数据时&#xff0c;这并非总是一件容易的事。 在本文中&…

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

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 约束与局限性 的知识&#xff1b; 【1】 不能用基本类型实例化类型参数 1.1&#xff09;不能用类型参数代替基本类型&#xff0c; 因此&#xff0c;没有 Pa…

python简单菜单_创建一个简单的python菜单

修正和评论&#xff0c;它们主要是语法错误。menulist 1. Print the list,2. Add a name to the list,3. Remove a name from the list,4. Change an item in the list,9. Quit #assuming you want to display menulist, having it as a tuple is uselesslst("johny"…

郎溪 溪流_到无限(溪流)和超越!

郎溪 溪流Java允许您处理集合或流中的数据。 将流视为将一个集合转换为另一个集合的技术非常容易。 这可能会导致一些相当随意的代码&#xff0c;其中流数据被重复收集到某种类型的集合中&#xff0c;作为一个整体集合传递&#xff0c;然后再进行更多处理。 对于6个元素&#…

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

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 Varargs 警告不能实例化类型变量 的知识&#xff1b; 【1】 Varargs 警告 1.1&#xff09;一个相关问题&#xff1a; 向参数个数可变的方法传递一个泛型类型…

rabbitmq怎么停止_Windows环境下RabbitMQ的启动和停止命令

Windows环境下RabbitMQ的启动和停止命令原创lockie_zou 最后发布于2018-05-24 15:34:21 阅读数 36514 收藏展开首先windows下安装好了erlang和rabbitmq。如下地址同时下载和安装&#xff1a;Erlang&#xff1a;http://www.erlang.org/download.htmlRabbitMQ &#xff1a;http:…

elk入门_ELK堆栈入门

elk入门朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户&#xff1f; 立即尝试Okta的API和Java SDK。 数分钟之内即可在任何应用程序中对用户进行身份验证&#xff0c;管理和保护。 好的设计原则要求微服务架构是可观察的&#xff0c;并提供集中的监视工具。 该工具使开…

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

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 泛型类的静态上下文中类型变量无效不能抛出或捕获泛型类的实例 的知识&#xff1b; 【1】泛型类的静态上下文中类型变量无效 1.1&#xff09;不能在静态域或…

android ril.java_Android RIL学习

1.Android RIL概念Android RIL是基于telephony服务和raido硬件层的抽象层。Android的rild库是介于HAL接口与baseband modem之间&#xff0c;它提供了语音、数据、短信、SIM卡管理以及STK应用的功能。它把标准的GSM27.007中常用的如dial这些做主动请求的操作称之为request&#…

netty java_Netty Java快速指南

netty java使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证&#xff0c;管理和保护。 今天尝试Okta。 Netty是一个无阻塞输入/输出&#xff08;NIO&#xff09;框架&#xff0c;它使开发低级网络服务器和客户端…

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

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 注意擦除后的冲突 的知识&#xff1b; 1.1&#xff09;当泛型类型被 擦除时&#xff0c; 无法创建引发冲突的条件。 1.1.1&#xff09;看个荔枝&#xff…

java的Swing里怎么new一条线_java – 在JFrame上绘制一条线

我正在尝试使用图形2D绘制一条线,但然后该线出现在所有的线上JFrame中的其他组件因此使它们不可见.我该如何解决这个问题&#xff1f;这是代码&#xff1a;import javax.swing.*;import java.awt.*;import java.awt.geom.*;class Success extends JFrame{public Success(){JPan…

java –cp_Java –缺少字体–崩溃的应用程序!

java –cpEclipse MAT和Heaphero都是分析大型堆转储的流行Java工具。 最近&#xff0c;当我们尝试在Eclipse MAT中分析堆转储文件时遇到了一个有趣的问题。 工具因缺少字体crash而崩溃。 我们认为我们将与您分享发现的结果。 CompositeStrike.getStrikeForSlot&#xff08;&am…

java泛型程序设计——泛型类型的继承原则

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 泛型类型的继承原则 的知识&#xff1b; 【1】泛型类型的继承原则相关 1.1&#xff09;考虑一个类 Employee 和一个Employee子类 Manger &#xff0c; 问&a…

用java代码写美国时间_如何衡量Java代码所用的时间?

本问题已经有最佳答案&#xff0c;请猛点这里访问。我需要分析Java中的一些算法的复杂性。为此&#xff0c;我计划提供大量的输入&#xff0c;并测量Java实现所花费的时间。检查某些代码行之间的时间最精确和准确的方法是什么&#xff1f;我需要精确到毫秒…不完全是&#xff0…

reactor使用方法_Project Reactor展开方法

reactor使用方法最近&#xff0c;我的一位同事向我介绍了Project Reactor类型的expand运算符&#xff0c;在这篇文章中&#xff0c;我想介绍几种使用它的方式。 展开分页结果 考虑在名为City的模型上基于Spring Data的存储库&#xff1a; import org.springframework.data.jpa…

java泛型程序设计——通配符类型+通配符的超类型限定

【0】README 0.1&#xff09; 本文描述源代码均 转自 core java volume 1&#xff0c; 旨在理解 java泛型程序设计 的 通配符类型通配符的超类型限定 的知识&#xff1b; 【1】通配符类型相关 1.1&#xff09;通配符类型&#xff1a; Pair < ? extends Employee> 表示…