2015-07-02 10 views
5

Ich habe eine Klasse mit einem Konstruktor Signatur wie folgt:Java generische Typen Mismatch Fehler

public class MyClass <U>{ 
    public <T> MyClass(Set<T> data, Function<T,U> func)... 
} 

ist das in Ordnung. Aber ich möchte den Konstruktor überladen, für den Fall, dass, wenn Sie die Funktion func nicht bereitstellen, wird einfach (item)->{return item;} verwendet. Ich habe einen anderen Konstruktor geschrieben, die wie folgt aussieht:

public <T> MyClass(Set<T> data){ 
    this(
     data, 
     (item)->{return item;} 
    ); 
} 

Dies ist eine Art Konfliktfehler verursacht, weil die Funktion, die ich als Argument an meinem Konstruktor bin mit einem Wert vom Typ nimmt T und gibt das gleiche Wert, der ein U sein sollte. Ich verstehe nicht, warum das algebraische System nicht sieht, dass in diesem Fall U und T gleich sind und das ist ok?

+0

Sie haben nicht eine ungeschickte Syntax wie '(item) müssen -> {return Artikel;}', schreiben Sie einfach 'Artikel -> Artikel '. Oder, naja, 'Function.identity()' ... – Holger

+0

Danke @Holger, ich wechselte zu 'Function.identity()' –

Antwort

7

Das System muss annehmen, dass T und U zwei verschiedene Typen sind, da Sie ihnen zwei verschiedene Namen gegeben haben. Sie können jedoch nur die zusätzliche generische Art von Ihrem zweiten Ctor so entfernen:

public class MyClass <U>{ 
    public <T> MyClass(Set<T> data, Function<T,U> func) {...} 
    public MyClass(Set<U> data){ 
     this(
      data, 
      (item)->{return item;} 
     ); 
    } 
} 
+0

Ah ja, ich bin ein Idiot. Hoppla. Ich nahm an, dass der Typ-Mismatch zwischen U und T lag, ohne zu realisieren, dass ich tatsächlich zwei verschiedene Ts in verschiedenen Bereichen gemacht hatte. Das hat es perfekt sortiert, vielen Dank! :) –

3

Lassen Sie uns versuchen, eine Instanz der Klasse zu erstellen, die zweite Konstruktor:

Set<Integer> ints = new HashSet<>(); 
MyClass<String> myobj = new <Integer> MyClass (ints); 

Ihre erste Konstruktor wäre erwarten Set<Integer> und Function<Integer,String> Parameter, aber Ihr zweiter Konstruktor würde versuchen, ihm eine Function<Integer,Integer> zu übergeben. Das ist der Grund, warum Ihr Code die Kompilierung nicht besteht.

Wenn Sie generische Klassen und Methoden definieren, müssen sie für jede Kombination von Typen gültig sein, die ihre Typparameter ersetzen können.

0

Da Sie zwei verschiedene Typen T und U deklariert haben, denkt der Compiler vernünftigerweise, dass sie unterschiedlich sind. Wenn sie gleich sind, nicht T deklarieren und verwenden nur U:

public MyClass(Set<U> data){ 
    this(
     data, 
     (item)->{return item;} 
    ); 
}