Erasure
Usually, it is not necessary
to know the details about how the Java compiler transforms your source code
into object code. However, in the case of generics, some general understanding
of the process is important because it explains why the generic features work
as they do— and why their behavior is sometimes a bit surprising. For this
reason, a brief discussion of how generics are implemented in Java is in order.
An important constraint that
governed the way that generics were added to Java was the need for
compatibility with previous versions of Java. Simply put, generic code had to
be compatible with preexisting, non-generic code. Thus, any changes to the
syntax of the Java language, or to the JVM, had to avoid breaking older code.
The way Java implements generics while satisfying this constraint is through
the use of erasure.
In general, here is how
erasure works. When your Java code is compiled, all generic type information is
removed (erased). This means replacing type parameters with their bound type,
which is Object if no explicit bound
is specified, and then applying the appropriate casts (as determined by the
type arguments) to maintain type compatibility with the types specified by the
type arguments. The compiler also enforces this type compatibility. This
approach to generics means that no type parameters exist at run time. They are
simply a source-code mechanism.
Bridge
Methods
Occasionally, the compiler
will need to add a bridge method to a
class to handle situations in which the type erasure of an overriding method in
a subclass does not produce the same erasure as the method in the superclass.
In this case, a method is generated that uses the type erasure of the
superclass, and this method calls the method that has the type erasure
specified by the subclass. Of course, bridge methods only occur at the bytecode
level, are not seen by you, and are not available for your use.
Although bridge methods are
not something that you will normally need to be concerned with, it is still
instructive to see a situation in which one is generated. Consider the
following program:
// A situation that creates a bridge method.
class Gen<T> {
T ob; // declare an object of type T
//Pass the constructor a reference to an object
of type T.
Gen(T o) { ob = o;
}
// Return ob.
T getob() { return ob;
}
}
// A subclass of Gen.
class Gen2 extends Gen<String> {
Gen2(String o) { super(o);
}
// A String-specific override of getob().
String getob() {
System.out.print("You called String
getob(): "); return ob;
}
}
// Demonstrate a situation that requires a
bridge method.
class BridgeDemo {
public static void main(String args[]) {
// Create a Gen2 object for Strings.
Gen2 strOb2 = new Gen2("Generics
Test");
System.out.println(strOb2.getob());
}
}
In the program, the subclass Gen2 extends Gen, but does so using a String-specific
version of Gen, as its declaration
shows:
class Gen2 extends Gen<String> {
Furthermore, inside Gen2, getob( ) is overridden with String
specified as the return type:
// A String-specific override of getob().
String getob() {
System.out.print("You called String
getob(): "); return ob;
}
All of this is perfectly
acceptable. The only trouble is that because of type erasure, the expected form
of getob( ) will be
Object getob() { // ...
To handle this problem, the
compiler generates a bridge method with the preceding signature that calls the String version. Thus, if you examine
the class file for Gen2 by using javap, you will see the following
methods:
class Gen2 extends Gen<java.lang.String>
{
Gen2(java.lang.String);
java.lang.String getob();
java.lang.Object getob(); // bridge method
}
As you can see, the bridge
method has been included. (The comment was added by the author and not by javap, and the precise output you see
may vary based on the version of Java that you are using.)
There is one last point to
make about this example. Notice that the only difference between the two getob( ) methods is their return type.
Normally, this would cause an error, but because this does not occur in your
source code, it does not cause a problem and is handled correctly by the JVM.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2023 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.