2014-10-04 7 views
6

Java Konstrukteure können generisch sein: http://docs.oracle.com/javase/tutorial/java/generics/methods.htmlJava generische Konstrukteure Syntax und Zweck

Allerdings kann ich nicht ein gutes Beispiel dafür finden, wie generische Konstruktor deklarieren und aufrufen. Außerdem verstehe ich nicht den Zweck des generischen Konstruktors, da der Geltungsbereich des Typparameters auf den Konstruktor beschränkt ist.

Mit Klasse mit generischen Konstruktor:

public class MyClass { 

    public <T> MyClass(T data) { 
     // ... 
    } 

} 

wir rufen Sie es wie:

MyClass obj = new <Integer>MyClass(12); 

Also meine Fragen sind:

  1. Was ist der Zweck des generischen Konstruktor? Können Sie ein Beispiel aus JDK oder Ihrem eigenen Beispiel zeigen?

  2. Warum Aussage wie

    Integer val = new <String>Integer(100); 
    

ohne Fehler kompiliert, auch wenn Klasse Integer nicht generischen Konstruktor hat?

+0

nur eine wilde Vermutung, aber ich denke, es kompiliert, weil der Typ ist falsch platziert. Der korrekte Weg wäre 'new Integer (100);' oder 'new MyClass (12);'. – Tom

+2

@Tom 'neue MyClass ' würde verwendet werden, wenn * die Klasse selbst * einen Parameter hätte, wie 'class MyClass '. Aber in diesem Fall ist es der Konstruktor, der den Parameter besitzt, und das Schreiben auf diese Weise ist die Standardmethode zum Aufrufen generischer Methoden oder Konstruktoren. – Marco13

Antwort

6

Ein Zweck eines generischen Konstruktors kann derselbe wie für einige generische Methoden sein: Um sicherzustellen, dass mehrere Argumente auf denselben Typ verweisen.

Betrachten Sie das folgende Beispiel (ja, es ist ein bisschen gekünstelt ist, sollte aber den Punkt zeigen):

import java.util.ArrayList; 
import java.util.Collection; 

public class GenericConstructorTest 
{ 
    public static void main(String[] args) 
    { 
     Collection<String> strings = new ArrayList<String>(); 
     ClassWithParam c0 = new <String>ClassWithParam("String", strings); 
    } 
} 

class ClassWithParam 
{ 
    public <T> ClassWithParam(T data, Collection<T> collection) 
    { 
     collection.add(data); 
    } 
} 

Es spielt keine Rolle für die Klasse oder den Konstruktor die Typ genau dort verwendet wird. Es ist nur wichtig zu wissen, dass die Sammlung, die als zweites Argument angegeben wurde, Elemente des Typs annehmen kann, der als erstes Argument angegeben wurde.

(Ich möchte ein realistischeres, praktisches Beispiel zeigen, denke aber, dass es eher selten notwendig ist, einen Konstruktor auf diese Weise zu parametrisieren, und man könnte sogar meinen, dass dies nur ein "Nebeneffekt" der Möglichkeit ist parametrieren Methoden, und die Tatsache, dass es keinen Grund gibt explizit - diese für den Bau nicht zulassen ...)


EDIT Wie pro Antrag in den Kommentar, und Beispiel, wo die angegebenen Argumente sind atually verwendet. Es ist immer noch ziemlich erfunden. Realistischere Beispiele könnten strukturell ähnlich sein und, auf einige Arten von Zuhörer beziehen sich aber viel mehr Code würde bedeuten:

public class GenericConstructorTest 
{ 
    public static void main(String[] args) 
    { 
     Callback<String> callback = new Callback<String>(); 
     ClassWithParam c0 = new <String>ClassWithParam("String", callback); 
     c0.execute(); 
    } 
} 

class ClassWithParam 
{ 
    private Runnable runnable; 

    public <T> ClassWithParam(final T data, final Callback<T> callback) 
    { 
     runnable = new Runnable() 
     { 
      @Override 
      public void run() 
      { 
       callback.call(data); 
      } 
     }; 
    } 

    void execute() 
    { 
     runnable.run(); 
    } 
} 

class Callback<T> 
{ 
    void call(T t) 
    { 
     System.out.println("Called with "+t); 
    } 
} 

Das zweite Beispiel, das Sie

Integer val = new <String>Integer(100); 

kompiliert nicht veröffentlicht in Eclipse mit Java 7.Es klagt

Der Konstruktor Integer (int) vom Typ Integer ist nicht generisch; es kann nicht mit Argumenten

In Java 8, ist dies erlaubt parametriert werden, obwohl es immer noch eine Warnung ausgibt:

Ungenutzte Typargumente für den nicht generischen Konstruktor Integer (int) vom Typ Integer; es sollte nicht mit Argumenten

parametriert werden (Wenn diese Differenz ist, was Sie in wirklich interessiert sind, sollten Sie überlegen, das als eine separate Frage zu stellen)

+3

FWIW, kompiliert es * mit dem Sun Java 7 Compiler. Ich weiß allerdings nicht, ob es der Sun-Compiler oder der Eclipse-Compiler ist. –

+0

@OliverCharlesworth Interessant, ich hätte das testen sollen. Es wird nicht einmal eine Warnung ausgegeben. Vielleicht werde ich durch die JLS graben, um zu sehen, ob dies als ein Fehler im Eclipse-Compiler betrachtet werden kann (von einem kurzen Websuche scheinen es * verwandte * Bugs zu geben, aber noch keinen gefunden zu haben, der genau * diesem * Fall entspricht) – Marco13

+0

Es ist schwer vorstellbar, dass ein solcher Konstruktor praktisch verwendet werden kann: Er ändert die Eingabesammlung, kann sie aber nicht im Klassenfeld speichern oder einfach zurückgeben. – ako