现在有一个泛型类如下:
public abstract class Parent {
public int toInfo(T t){
return 0;
}
}
有个子类继承该泛型类:
public class Child extends Parent {
@Override
public int toInfo(String t) {
return super.toInfo(t);
}
}
现在我获取该子类的所有方法
public class Test {
public static void main(String[] args) {
Child c = new Child();
Method[] ms = c.getClass().getMethods();
}
}
发现有两个toInfo方法
1. public int Child.toInfo(java.lang.String)
2. public int Child.toInfo(java.lang.Object)
请问我该如何处理只会得到一个方法public int Child.toInfo(java.lang.String)?
首先,这个问题在《Java语言规范》中已经提到了,请参考 15.12.4.5 Create Frame, Synchronize, Transfer Control :
[quote]Discussion
As an example of such a situation, consider the declarations:
class C<T> { abstract T id(T x); }
class D extends C<String> { String id(String x) { return x; } }
Now, given an invocation
C c = new D();
c.id(new Object()); // fails with a ClassCastException
The erasure of the actual method being invoked, D.id(), differs in its signature from that of the compile-time method declaration, C.id(). The former takes an argument of type String while the latter takes an argument of type Object. The invocation fails with a ClassCastException before the body of the method is executed.
Such situations can only arise if the program gives rise to an unchecked warning (§5.1.9).
Implementations can enforce these semantics by creating bridge methods. In the above example, the following bridge method would be created in class D:
Object id(Object x) { return id((String) x); }
This is the method that would actually be invoked by the Java virtual machine in response to the call c.id(new Object()) shown above, and it will execute the cast and fail, as required.[/quote]
1、对于泛型形参 在实际运行时会进行泛型擦去:
如:
[code="java"]class Parent {
public T toInfo(T t){
return t;
}
}
class Child extends Parent {
@Override
public String toInfo(String t) {
return t;
}
} [/code]
实际方法的字节码如下:
[code="java"]public java.lang.String toInfo(java.lang.String);
Code:
Stack=1, Locals=2, Args_size=2
0: aload_1
1: areturn
LineNumberTable:
line 27: 0
public java.lang.Object toInfo(java.lang.Object);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: aload_1
2: checkcast #2; //class java/lang/String //保证类型是String的
5: invokevirtual #3; //Method toInfo:(Ljava/lang/String;)Ljava/lang/Strin
g;
8: areturn
LineNumberTable:
line 23: 0[/code]
此处我们可以看到多了一个 public java.lang.Object toInfo(java.lang.Object); 此方法叫做bridge方法;
Java虚拟机规范: 即bridge方法是由编译器产生的 不再源代码中存在的。
The ACC_BRIDGE flag is used to indicate a bridge method
generated by the compiler.
可以参考
[url]http://stackoverflow.com/questions/289731/what-java-lang-reflect-method-isbridge-used-for[/url]
Child实际对应的方法为(大体):
class Child extends Parent {
@Override
public String toInfo(String t) {
return t;
}
@Override
public Object toInfo(Object t) { //这是一个 bridge方法
return (String)t;
}
}
即public int Child.toInfo(java.lang.Object) 因为泛型信息在编译时要进行泛型擦出,因为为了保证那些如(class Child extends Parent )正常工作,由编译器产生的一个bridge方法。
提示 可以查一下Java的 synthetic 和 bridge 方法
下午解答 :D