Bridge方法和泛型

看API的时候,发现java.lang.reflect.Method类里有个isBridge方法。那,什么是bridge呢?下面开始的是关于这个问题的学习。

 在JLS里对Bridge Method有这么一段描述

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, 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())

 

 

下面试写了两个简单的类,并对照查看了他们对应的class文件

 
Test.ava

 1 package bridgemethod;
 2 
 3 public class Test {}
 4 
 5 class Father<T>{
 6     
 7     T elm;
 8     
 9     T doSomething(T elm){
10         return elm;
11     }
12 }
13 
14 class Son extends Father<String>{
15     @Override
16     String doSomething(String elm){
17         return elm;
18     }
19 }


Father.class
 1 // Compiled from Test.java (version 1.6 : 50.0, super bit)
 2 // Signature: <T:Ljava/lang/Object;>Ljava/lang/Object;
 3 class bridgemethod.Father {
 4   
 5   // Field descriptor #6 Ljava/lang/Object;
 6   // Signature: TT;
 7   java.lang.Object elm;
 8   
 9   // Method descriptor #10 ()V
10   // Stack: 1, Locals: 1
11   Father();
12     0  aload_0 [this]
13     1  invokespecial java.lang.Object() [12]
14     4  return
15       Line numbers:
16         [pc: 0, line: 5]
17       Local variable table:
18         [pc: 0, pc: 5] local: this index: 0 type: bridgemethod.Father
19       Local variable type table:
20         [pc: 0, pc: 5] local: this index: 0 type: bridgemethod.Father<T>
21   
22   // Method descriptor #21 (Ljava/lang/Object;)Ljava/lang/Object;
23   // Signature: (TT;)TT;
24   // Stack: 1, Locals: 2
25   java.lang.Object doSomething(java.lang.Object elm);
26     0  aload_1 [elm]
27     1  areturn
28       Line numbers:
29         [pc: 0, line: 10]
30       Local variable table:
31         [pc: 0, pc: 2] local: this index: 0 type: bridgemethod.Father
32         [pc: 0, pc: 2] local: elm index: 1 type: java.lang.Object
33       Local variable type table:
34         [pc: 0, pc: 2] local: this index: 0 type: bridgemethod.Father<T>
35         [pc: 0, pc: 2] local: elm index: 1 type: T
36 }

注意:第七行原本的T elm被替换成了java.lang.Object elm。
注意:第二十五行doSomething的参数和返回值同样被替换了。

Son.class

 1 // Compiled from Test.java (version 1.6 : 50.0, super bit)
 2 // Signature: Lbridgemethod/Father<Ljava/lang/String;>;
 3 class bridgemethod.Son extends bridgemethod.Father {
 4   
 5   // Method descriptor #6 ()V
 6   // Stack: 1, Locals: 1
 7   Son();
 8     0  aload_0 [this]
 9     1  invokespecial bridgemethod.Father() [8]
10     4  return
11       Line numbers:
12         [pc: 0, line: 14]
13       Local variable table:
14         [pc: 0, pc: 5] local: this index: 0 type: bridgemethod.Son
15   
16   // Method descriptor #15 (Ljava/lang/String;)Ljava/lang/String;
17   // Stack: 1, Locals: 2
18   java.lang.String doSomething(java.lang.String elm);
19     0  aload_1 [elm]
20     1  areturn
21       Line numbers:
22         [pc: 0, line: 17]
23       Local variable table:
24         [pc: 0, pc: 2] local: this index: 0 type: bridgemethod.Son
25         [pc: 0, pc: 2] local: elm index: 1 type: java.lang.String
26   
27   // Method descriptor #18 (Ljava/lang/Object;)Ljava/lang/Object;
28   // Stack: 2, Locals: 2
29   bridge synthetic java.lang.Object doSomething(java.lang.Object arg0);
30     0  aload_0 [this]
31     1  aload_1 [arg0]
32     2  checkcast java.lang.String [19]
33     5  invokevirtual bridgemethod.Son.doSomething(java.lang.String) : java.lang.String [21]
34     8  areturn
35       Line numbers:
36         [pc: 0, line: 1]
37 }

注意:Song.class里有三个方法。多出来的是方法在第二十九行
posted @ 2011-07-24 15:04  倚楼无语F5  阅读(331)  评论(0编辑  收藏  举报