| Type Erasure ist ein Mechanismus, der bei der Übersetzung von generischem Java-Quellcode durch den Compiler zur Anwendung kommt. Type Erasure bezeichnet dabei eine Zuordnung (Mapping) von Typen zu anderen Typen. Der Quellcode enthält z.B. vor dem Type Erasure Typparamter und parametrisierte Typen. Nach dem Type Erasure sind jedoch keine Typparamter und parametrisierte Typen mehr vorhanden. Zusätzlich fügt der Compiler bei Bedarf in den Quellcode Typüberprüfungen, Typumwandlungen oder sogenannte Brückenmethoden ein. Type Erasure bewirkt sozusagen zunächst eine Übersetzung von generischem Quellcode in einen regulären Quellcode (keine generischen Elemente vorhanden), der anschließend in einen entsprechenden Bytecode compiliert wird. 
 Type Erasure bei parametrisierten Typen Als nächstes soll erläutert werden, wie sich der Mechanismus Type Erasure 
                     auf Typargumente auswirkt. Dazu soll Listing 3.1 zunächst 
                     mittels  // DeCompiled : GenericsExample.class
import java.util.*;
public class GenericsExample {
  public static void main(String args[]) {
    Vector v = new Vector();
    v.add(new Integer(3));
    Integer i = (Integer)v.get(0);
    System.out.println(i.toString());
  }
}Dabei wurden durch den Compiler die folgenden Änderungen vorgenommen (das aktuelle Typargument wurde entfernt und eine Typumwandlung wurde zusätlich eingefügt): vorher: Vector<Integer> v = new Vector<Integer>(); nachher: Vector v = new Vector(); vorher: Integer i = v.get(0); nachher: Integer i = (Integer)v.get(0); Type Erasure von parametrisierten Typen führt zu einem Typ ohne Typargumente (Raw Type). 
 Um das Verhalten des Compilers beim Auftreten von Typparamtern im Quellcode zu untersuchen, soll Listing 3.2 zunächst in Bytcode übersetzt werden und anschließend wieder decompiliert werden. Danach lautet der Quellcode: // DeCompiled : Holder.class public class Holder { private Object value; public void set(Object v) { value = v; } public Object get() { return value; } } Ein Vergleich zwischen dem Quellcode vorher und dem Quellcode nachher zeigt, dass durch den Java-Übersetzer folgendes modifiziert wurde (1.Saplte): Holder.java NumberHolder.java vorher: public class Holder<E> public class NumberHolder<E extends Number> nachher: public class Holder public class NumberHolder voher: private E value; private E value; nachher: private Object value; private Number value; voher: public void set(E v) public void set(E v) nachher: public void set(Object v) public void set(Number v) vorher: public E get() public E get() nachher: public Object get() public Number get() In der 2. Spalte wurde Listing 3.9 auch zunächst
                     compiliert und danach wieder decompiliert. Im Listing wurde die Schranke 
                      
 Brückenmethoden sind zusätzlich durch den Compiler erzeugte Methoden, die 
                     durch den Vorgang des Type Erasure benötigt werden, wenn z.B. eine Klasse eine 
                     parametrisierte Klasse erweitert. Zunächst soll die Klasse  /* HolderExtends.java */
public class HolderExtends extends Holder<String> {
  public String str;
  public void set(String s) {
    str = s;
  }  
}Die Datei  // DeCompiled : HolderExtends.class
public class HolderExtends extends Holder {
  public String str;
  public void set(String s) {
    str = s;
  }
  public volatile void set(Object obj) {  // Brueckenmethode!
    set((String)obj);
  }
}Dabei stellt sich die Frage: Warum wurde eine zusätzliche Methode (Brückenmethode) durch den Compiler generiert? Eine Antwort auf diese Frage liefert das Konzept des Type Erasure. Annahme: Holder<String>           -->    public void set(String v) { ... }
Real:    decompiled Holder.class  -->    public void set(Object v) { ... }
HolderExtends.java                -->    public void set(String s) { ... }Der Compiler fügt gegebenenfalls Brückenmethoden in Klassen ein, die von 
                     parametrisierten Typen abgeleitet wurden. Dadurch sollen die Regeln für die
                     Vererbung von Methoden nicht verletzt werden. Die Klasse  
 Subsignatur einer Methodensignatur Durch Type Erasure wird eine Erweiterung des Begriffes "Signatur einer Methode" 
                     nötig. Es wurde daher die Bezeichnung der Subsignatur einer 
                     Signatur eingeführt (siehe 
                     Java Language Specification 
                      
 Die folgenden zwei Beispiele zeigen Methodendeklarationen und die dazugehörigen Signaturen: Methode:  public String hansImGlueck(int anzahl, boolean b) { ... }
Signatur: hansImGlueck(int,boolean)
Methode:  public <E extends Number> E berechnung(Vector<E> v, S type, boolean mm) 
          { ... }
Signatur: <T1_extends_Number>berechnung(Vector<T1_extends_Number>,T2,boolean)Die konkreten Namensbezeichnungen von Typparametern werden zur Vereinfachung 
                     durch den Compiler einheitlich durchnummeriert (z.B.  
 Durch Type Erasure innerhalb von Methoden wird auch die Signatur dieser Methode verändert. In diesem Zusammenhang wird vom "Erasure einer Signatur" gesprochen. Der Begriff Subsignatur kann nun verwendet werden, um die Äquivalenz bezüglich Überschreibung (Override-Equivalence) zweier Methodensignaturen festzulegen: Zwei Methodensignaturen s1 und s2 sind override-equivalent, falls eine der beiden Bedingungen gilt: 
 Sind also zwei Methoden in unterschiedlichen Klassen und die eine Klasse 
                     erweitert die andere, kann die eine Methode die andere überschreiben auch wenn die 
                     beiden Methodensignaturen nicht identisch sind. Für eine Überlagerung reicht 
                     aus, dass die eine Methodensignatur eine Subsignatur der Signatur der anderen 
                     Methode ist. Dazu soll ein Beispiel betrachtet werden. Das anschließende Listing
                     enthält die beiden Methoden  Listing 3.15.  /* * GenericMethodOverrider.java * JDK 5 * */ import java.util.*; public class GenericMethodOverrider extends GenericMethodExample { public Vector paraVector() { Vector v = new Vector(); System.out.println("GenericMethodOverrider, paraVector"); return v; } public <E> E minmax(Vector<E> v, boolean mm) { Iterator<E> iter = v.iterator(); E a = iter.next(); System.out.println("GenericMethodOverrider, minmax"); return a; } public static void main(String[] args) { GenericMethodOverrider gmo = new GenericMethodOverrider(); Vector v = gmo.paraVector(); Vector<Integer> vi = new Vector<Integer>(); vi.add(new Integer("12")); vi.add(new Integer("4")); vi.add(new Integer("11")); Integer imin = gmo.minmax(vi, false); System.out.println(imin.toString()); Vector<String> vs = new Vector<String>(); vs.add("Hans im Glueck"); String str = gmo.minmax(vs, true); System.out.println(str); } } Die Ausgabe des Beispiels lautet wie folgt: GenericMethodOverrider, paraVector GenericMethodExample, minmax 4 GenericMethodOverrider, minmax Hans im Glueck Konkret an diesem Beispiel soll der Vorgang des Type Erasure und des Signature Erasure nachvollzogen werden: 
 An dieser Gegenüberstellung wird deutlich, dass folgendes gilt:
                     Die Methodensignaturen von GME: 
 Die Methode GME: | ||||||||||||||||||||||||||||||
| 
 | ||||||||||||||||||||||||||||||