javaseiten.de   |   Version 0.6
 

3.7. Wildcards

Typargumente können entweder Referenztypen wie z.B. Integer oder sogenannte Wildcards sein, wie die folgenden Ableitungsregeln verdeutlichen:

ActualTypeArgument:
        ReferenceType
        Wildcard
        
Wildcard:
        ? WildcardBounds_opt
        
WildcardBounds:
        extends ReferenceType
        super ReferenceType

Der Wildcard steht für alle möglichen Typen als Platzhalter. Beispiele von parametrisierten Typen, die als Typargument einen Wildcard enthalten, wären:

Vector<?>
Vector<? extends Number>
Vector<? super Integer>

Der Wildcard wird dabei durch ein Fragezeichen "?" repräsentiert und steht für eine Reihe von möglichen Typen. Die drei unterschiedlichen Möglichkeiten zur Verwendung von Wildcards sind:

  • ? : Ungebundener Wildcard. Der Platzhalter steht für alle möglichen Typen.

  • ? extends Type : Ein Wildcard mit einer oberen Schranke. Der Platzhalter steht für alle Typen, die Type erweitern und für Type selbst.

  • ? super Type : Ein Wildcard mit einer unteren Schranke. Der Platzhalter steht für alle Typen, die Supertypen von Type sind und für Type selbst.

Der Wildcard kann nur eine Schranke haben (entweder eine obere oder eine untere Schranke). Ein Typparamter kann im Gegensatz dazu mehrere Schranken besitzen. Eine untere Schranke für Typparamter gibt es jedoch nicht. Das folgende Listing besitzt drei unterschiedliche Methoden für die Konsolenausgabe der Elemente eines Vektors. Jede dieser Methoden hat einen Parameter v; gültige Typen für diesen Paramter sind jeweils unterschiedlich eingeschränkt. Die erste Methode lässt durch die Angabe Vector<?> zu, dass die Elemente des Vektors, der an sie übergeben wird, beliebig sein können.

public void printVector(Vector<?> v) { ... }

Die zweite Methode erzwingt durch den mit einem Wildcard parametrisierten Typen Vector<? extends Number>, dass die Elemente des Vektors die Klasse Number (obere Grenze) erweitern.

public void printVectorUB(Vector<? extends Number> v) { ... }

Würde diese Methode z.B. mit einem Argument vom parametrisierten Typ Vector<Object> aufgerufen, ist eine Fehlermeldung zu erwarten, da die Element des Vektors vom allgemeinen Typ Object wären (die Klasse Object erweitert Number nicht). Die dritte Methode setzt eine untere Schranke für die Elemente des Vektors, der an diese Methode übergeben werden kann.

public void printVectorLB(Vector<? super Integer> v) { ... }

Die Elemente müssten im Beispiel entweder vom Typ Integer sein oder sie müssten eine Superklasse von Integer sein (z.B. Number oder die Klasse Object). Der Aufruf der dritten Methode mit einem Argument vom parametrisierten Typ Vector<Byte> erzeugt eine Fehlermeldung, da die Klassen Byte und Integer auf derselben Ebene in der Vererbungshierarchie stehen (Byte ist keine Superklasse von Integer).

Listing 3.14. GenericWildcardExample.java. Verwendung den generischen Typs Vector<E>, der jeweils mit einem ungegbundenen Wildcard, einem Wildcard mit oberer Schranke und einem Wildcard mit einer unteren Schranke parametrisiert ist.

/* 
 * GenericWildcardExample.java 
 * JDK 5
 *
 */

import java.util.*;

public class GenericWildcardExample {
  
  public void printVector(Vector<?> v) {
    for (Object o : v) {
      System.out.print(o.toString() + " ");
    }  
    System.out.println();
  }  
  
  public void printVectorUB(Vector<? extends Number> v) {
    for (Object o : v) {
      System.out.print(o.toString() + " ");
    }  
    System.out.println();
  }
  
  public void printVectorLB(Vector<? super Integer> v) {
    for (Object o : v) {
      System.out.print(o.toString() + " ");
    }  
    System.out.println();
  }
   
  public static void main(String[] args) {
    GenericWildcardExample gwe = new GenericWildcardExample();
    
    Vector<Integer> vi = new Vector<Integer>();
    vi.add(new Integer("3"));
    vi.add(new Integer("4"));
    gwe.printVector(vi);
    gwe.printVectorUB(vi);
    gwe.printVectorLB(vi);
    
    Vector<Byte> vb = new Vector<Byte>();
    vb.add(new Byte("1"));
    vb.add(new Byte("2"));
    gwe.printVector(vb);
    gwe.printVectorUB(vb);
    //gwe.printVectorLB(vb);  // Fehler
    
    Vector<Object> vo = new Vector<Object>();
    vo.add("a");
    vo.add("b");
    vo.add(new Integer("5"));
    gwe.printVector(vo);
    //gwe.printVectorUB(vo);  // Fehler
    gwe.printVectorLB(vo);  
  }  
}

Das Beispiel führt zur folgenden Konsolenausgabe:

3 4 
3 4 
3 4 
1 2 
1 2 
a b 5 
a b 5

 

 

 

Diese Seite nutzt Google-Dienste - siehe dazu Datenschutz.

Copyright © 2006, 2007 Harald Roeder