Bridge Method in Java

Source: Internet
Author: User

Today, in Java, we found that the value of ACC_BRIDGE was set in access_flags in method_info. I searched it online and probably understood it. Remember it first.

 

First, under what circumstances will the bridge method be generated (2 ):

Bridge method may be created by the compiler when extending a parameterized type whose methods have parameterized arguments.

This is a post posted on the Internet, but it doesn't seem quite clear. First, the bridge method is generated by the compiler, so there is no bridge keyword in the source code. Then, the inherited generic class contains the generic method only when the specific type is inherited from a generic class. For example, see the following example:


Abstract class A <T> {
Public abstract T method1 (T arg );
Public abstract T method2 ();
}
 
Class B extends A <String> {
Public String method1 (String arg ){
Return arg;
}
Public String method2 (){
Return "abc ";
}
}
 
Class C <T> extends A <T> {
Public T method1 (T arg ){
Return arg;
}

Public T method2 (){
Return null;
}
}

 

The. class file they generated is as follows:

A. class

Abstract class org. levin. insidejvm. miscs. bridgemethod. {

Public abstract java. lang. Object method1 (java. lang. Object arg0 );

Public abstract java. lang. Object method2 ();

}

B. class

Class org. levin. insidejvm. miscs. bridgemethod. B extends org. levin. insidejvm. miscs. bridgemethod. {

Public java. lang. String method1 (java. lang. String arg );

0 aload_1 [arg]

1 areturn

Public java. lang. String method2 ();

0 ldc <String "abc"> [20]

2 areturn

Public bridge synthetic java. lang. Object method2 ();

0 aload_0 [this]

1 invokevirtual org. levin. insidejvm. miscs. bridgemethod. B. method2 (): java. lang. String [23]

4 areturn

Public bridge synthetic java. lang. Object method1 (java. lang. Object arg0 );

0 aload_0 [this]

1 aload_1 [arg0]

2 checkcast java. lang. String [26]

5 invokevirtual org. levin. insidejvm. miscs. bridgemethod. B. method1 (java. lang. String): java. lang. String [28]

8 areturn

}

C. class

Class org. levin. insidejvm. miscs. bridgemethod. C extends org. levin. insidejvm. miscs. bridgemethod. {

Public java. lang. Object method1 (java. lang. Object arg );

0 aload_1 [arg]

1 areturn

Public java. lang. Object method2 ();

0 aconst_null

1 areturn

}

We can see that B generates two bridge methods, but C does not. In fact, Java generics have an erasure mechanism, so when compiling Class A, all the methods defined in it are represented by the Object type. Therefore, if there is no bridge method, class B does not cover the abstract method in Class A at all. Because of the existence of the bridge method, Class B can be compiled. The C class implements the abstract method in Class A because all generics are expressed through the Object class during compilation, so the bridge method does not need to be generated.

 

In fact, the bridge method in Class B also has some differences in calling:


Public static void main (String [] args ){
B B = new B ();
B. method1 ("abc ");
A <String> a = new B ();
A. method1 ("abc ");
}

The bytecode of this method is as follows:

0 new org. levin. insidejvm. miscs. bridgemethod. B [16]

3 dup

4 invokespecial org. levin. insidejvm. miscs. bridgemethod. B () [18]

7 astore_1 [B]

8 aload_1 [B]

9 ldc <String "abc"> [19]

11 invokevirtual org. levin. insidejvm. miscs. bridgemethod. B. method1 (java. lang. String): java. lang. String [21]

14 pop

15 new org. levin. insidejvm. miscs. bridgemethod. B [16]

18 dup

19 invokespecial org. levin. insidejvm. miscs. bridgemethod. B () [18]

22 astore_2 [a]

23 aload_2 [a]

24 ldc <String "abc"> [19]

26 invokevirtual org. levin. insidejvm. miscs. bridgemethod. A. method1 (java. lang. Object): java. lang. Object [25]

29 pop

30 return

The above code shows the method1 (String) method called by variable B, while variable a calls the method1 (Object) method. This difference is also officially achieved by the support provided by the bridge method.

 

In fact, the bridge method will generate in another case (2 ):

In Java 1.4, to override a method of the parent class, the method signature of the subclass must be consistent with that of the parent class, including the method name, parameter type, and return value; in Java 1.5, this mechanism becomes: if the method name and parameter type of a method in the subclass are the same as that of a method in the parent class, in addition, if the return value of a subclass method is the type of the return value of the parent method or its subtype, The subclass method can also override the corresponding method in the parent class. See the following example:


Class E {

}
 
Class F extends E {

}
 
Class X {
Public E getE (){
Return new E ();
}
}
 
Class Y extends X {
@ Override
Public F getE (){
Return new F ();
}
}

The above code can be compiled. Let's take a look at the byte code of Y:

Class org. levin. insidejvm. miscs. bridgemethod. Y extends org. levin. insidejvm. miscs. bridgemethod. X {

Public org. levin. insidejvm. miscs. bridgemethod. F getE ();

0 new org. levin. insidejvm. miscs. bridgemethod. F [16]

3 dup

4 invokespecial org. levin. insidejvm. miscs. bridgemethod. F () [18]

7 areturn

Public bridge synthetic org. levin. insidejvm. miscs. bridgemethod. E getE ();

0 aload_0 [this]

1 invokevirtual org. levin. insidejvm. miscs. bridgemethod. Y. getE (): org. levin. insidejvm. miscs. bridgemethod. F [20]

4 areturn

}

From the bytecode, we can see that the syntax itself has not actually changed. The only difference is the support of the compiler. It re-generates a bridge method that returns E instead of F for the overload method.

From the byte code of the call, we can see that the syntax has not changed:


Public static void main (String [] args ){
X x = new Y ();
X. getE ();
}

The bytecode is as follows:

Public static void main (java. lang. String [] args );

0 new org. levin. insidejvm. miscs. bridgemethod. Y [16]

3 dup

4 invokespecial org. levin. insidejvm. miscs. bridgemethod. Y () [18]

7 astore_1 [x]

8 aload_1 [x]

9 invokevirtual org. levin. insidejvm. miscs. bridgemethod. X. getE (): org. levin. insidejvm. miscs. bridgemethod. E [19]

12 pop

13 return

In this bytecode, the x. getE () method actually calls the generated bridge method (E getE () instead of the User-Defined F getE () method.

In some cases, the return of a function of different subclasses

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.