java泛型之桥方法

感觉泛型中的桥方法挺难理解的,写篇笔记记录一下(具体是core java第536页,我的理解可能会有偏差)。

如下面的两段代码:

public class Pair<T> {
	private T first;
	private T second;

	public Pair() { first = null; second = null; }
	public Pair(T first, T second) { this.first = first; this.second = second; }

	public T getFirst() { return first; }
	public T getSecond() { return second; }

	public void setFirst(T newValue) { first = newValue; }
	public void setSecond(T newValue) { second = newValue; }
}
class DateInterval extends Pair<Date> {
	public void setSecond(Date second) {}
}

由于类型擦除的原因,DateInterval存在两个setSecond方法,分别为:

public void setSecond(Date second)      //自身创建

public void setSecond(Object second)    //继承自Pair<Date>

考虑以下调用:

DateInterval interval = new DateInterval(...);

Pair<Date> pair = interval;

pair.setSecond(aDate);

由于java语言的多态性,pair理论上应该调用DateInterval.setSecond方法。但是根据上面的分析,DateInterval类存在两个setSecond方法,到底该如何调用呢?

JVM工作原理如下:

1.  变量pair声明为Pair<Date>,该类型只有一个setSecond(Object)方法,虚拟机用pair引用的对象去调用这个setSecond(Object)方法。

2.  pair引用的对象是DateInterval,所以将会调用DateInterval.setSecond(Object)方法,这个方法是桥方法。

3.  这个桥方法会调用DateInterval.setSecond(Date)方法。

桥方法代码:public void setSecond(Object second) { setSecond((Date) second); }      //仔细看方法内部的Date强制类型转换,使得桥方法调用了DateInterval.setSecond(Date)方法

桥方法有时候会变得十分奇怪,假设DateInterval方法也覆盖了getSecond方法:

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

擦除类型后,DateInterval有两个getSecond方法:

Date getSecond()      //自身创建

Object getSecond()   //继承自Pair<Date>

咦,方法的签名不是“方法名+参数”吗?为什么会存在签名一样,返回类型不一样的方法呢?实际上,在JVM中,返回类型是可以用来区分方法的,虚拟机能够正确处理这一情况。

时间: 2024-11-14 02:10:49

java泛型之桥方法的相关文章

java泛型反映调用方法体内类型引用问题

自个在写自动化测验工具有关thrift效劳自动化测验遇到的疑问首先给大家看一段代码 Java代码 保藏代码public static void test(Listlist){ System.out.println(list.get(0)); System.out.println(list.get(0) + 123); System.out.println(list.get(0).getClass()); } public static void bugTest1(){ 澳洲保健品http://w

java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题

java泛型(二).泛型的内部原理:类型擦除以及类型擦除带来的问题 参考:java核心技术 一.Java泛型的实现方法:类型擦除 前面已经说了,Java的泛型是伪泛型.为什么说Java的泛型是伪泛型呢?因为,在编译期间,所有的泛型信息都会被擦除掉.正确理解泛型概念的首要前提是理解类型擦出(type erasure). Java中的泛型基本上都是在编译器这个层次来实现的.在生成的Java字节码中是不包含泛型中的类型信息的.使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉.这个过程就称为类型

Java 泛型(Generics) 综述

一. 引子 一般的类和方法,只能使用具体类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 多态算是一种泛化机制,但对代码的约束还是太强(要么继承父类,要么实现接口). 有许多原因促成了泛型的出现,而最引人注目的一个原因,就是为了创造容器类.(泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性) 例如,在 Java 实现加入泛型前,ArrayList 只维护一个 Object 类型的数组: publ

Java中的类型擦除与桥方法

类型擦除 Java在语法中虽然存在泛型的概念,但是在虚拟机中却没有泛型的概念,虚拟机中所有的类型都是普通类.无论何时定义一个泛型类型,编译后类型会被都被自动转换成一个相应的原始类型. 比如这个类 public class Parent<T> { public void sayHello(T value) { System.out.println("This is Parent Class, value is " + value); } } 在编译后就变成了 public c

C++泛型 &amp;&amp; Java泛型实现机制

C++泛型 C++泛型跟虚函数的运行时多态机制不同,泛型支持的静态多态,当类型信息可得的时候,利用编译期多态能够获得最大的效率和灵活性.当具体的类型信息不可得,就必须诉诸运行期多态了,即虚函数支持的动态多态. 对于C++泛型,每个实际类型都已被指明的泛型都会有独立的编码产生,也就是说list<int>和list<string>生成的是不同的代码,编译程序会在此时确保类型安全性.由于知道对象确切的类型,所以编译器进行代码生成的时候就不用运用RTTI,这使得泛型效率跟手动编码一样高.

java泛型总结

什么是泛型 泛型是jdk5引入的类型机制,就是将类型参数化,它是早在1999年就制定的jsr14的实现. 泛型机制将类型转换时的类型检查从运行时提前到了编译时,使用泛型编写的代码比杂乱的使用object并在需要时再强制类型转换的机制具有更好的可读性和安全性. 泛型程序设计意味着程序可以被不同类型的对象重用,类似c++的模版. 泛型对于集合类尤其有用,如ArrayList.这里可能有疑问,既然泛型为了适应不同的对象,ArrayList本来就可以操作不同类型的对象呀?那是因为没有泛型之前采用继承机制

泛型方法与桥方法

Java泛型中有存在一种方式叫做类型擦除,也就是说泛型在编译期间进行类型检验上做到有效安全,但是在运行当中,会将该泛型类型用顶层父类(若无继承关系则用Object)代替,然后再进行强转换成目标类型,这种类型擦除也存在在泛型方法中,但是方法的擦除带来了两个复杂的问题. public class ParentString<String> { String src; public void setSrc(String src){ this.src=src; } } public class Chil

你真的懂Java泛型吗

泛型实现参数化类型的概念,使代码可以应用于多种类型,解除类或方法与所使用的类型之间的约束.在JDK 1.5开始引入了泛型,但Java实现泛型的方式与C++或C#差异很大.在平常写代码用到泛型时,仿佛一切都来得如此理所当然.但其实Java泛型还是有挺多tricky的东西的,编译器在背后为我们做了很多事.下面我们来看看有关Java泛型容易忽视的点. 泛型不支持协变 什么是协变?举个例子. class Fruit{} class Apple extends Fruit{} Fruit[] fruit

Java泛型解析(04):约束和局限性

Java泛型解析(04):约束和局限性 前两节,认识和学习了泛型的限定以及通配符,初学者可能需要一些时间去体会到泛型程序设计的好处和力量,特别是想成为库程序员的同学就需要下去体会通配符的运用了,应用程序员则需要掌握怎么使用泛型,这里针对泛型的使用中的约束和局限性做一个介绍性的讲解. 不能用基本类型实例化类型参数 这个很好理解,实例化泛型类时泛型参数不能使用基本类型,如List<int>这是不合法的,要存储基本类型则可以利用基本类型的包装类如List<Integer> .List&l