2016-12-05 1 views
1

Ich arbeite derzeit meinen Weg gründliche Java-Core-Buch und ich bin im generischen Kapitel. Ich kann hier eine Sache nicht erfassen. Als Buch heißt Sie nicht ein neues Objekt aus T in generische Klasse machen kann, so ist dies möglich, nichtJava-generisches Objekt mit Lambda-Ausdrücken

public foo() { first = new T(); second = new T(); } //ERROR 

Was Sie tun können, ist die funktionale Schnittstelle und Lambda-Ausdruck mit Bezug wie diese

foo<String> f = foo.makeFoo(String::new) 
Konstruktor
public static <T> foo<T> makeFoo(Supplier<T> constr) 
{ 
    return new foo<>(constr.get(), constr.get()); 
} 

Und es ist toll, wie erwartet funktionierte, aber nur mit String, wenn ich mit einem anderen Objekt verwendet werden soll, beispielsweise eingewickelt einfachen Typ Integer es nicht möglich ist. Es gibt mir diesen Fehler

Error:(35, 38) java: method makeFoo in class generic.foo<T> cannot be applied to given types; 
required: java.util.function.Supplier<T> 
found: Integer::new 
reason: cannot infer type-variable(s) T 
(argument mismatch; incompatible parameter types in method reference) 

Es scheint nur mit String arbeiten, und ich habe keine Ahnung, warum, dachte ich, dass es für

jedes Objekt funktionieren würde, ich versuche, all diese Objekte auf richtige Klassen zu erstellen

foo<String> fString = foo.makeFoo(String::new); //Works 
    foo<Integer> fInteger = foo.makeFoo(Integer::new); //Doesn't work 
    foo<Double> fDouble = foo.makeFoo(Double::new); //Doesn't work 

EDIT

Eigentlich funktioniert dies mit benutzerdefinierten Objekte, o nly gewickelt einfache Typen gibt es nicht

kompilieren
foo<MyCustomObject> fCustom = foo.makeFoo(MyCustomObject::new); //Works 
+1

Der Typ der Variablen 'f' ist' foo ', so offensichtlich erwartet, dass der Lieferant eine' String' Objekt zurückgibt. Ändern Sie es in 'foo ', wenn Sie ihm einen Lieferanten geben, der ein 'Ganzzahl'-Objekt zurückgibt. – Jesper

+0

Ich mache genau das und das gibt keinen Fehler. foo fInteger = foo.makeFoo (Ganzzahl :: neu); –

+1

@ MTomczyński Ich habe Ihre Bearbeitung meiner Antwort abgelehnt, da es zu viel Text/Code gab, den ich nicht geschrieben habe. Ich denke, es wäre besser, wenn Sie es als Ihre eigene Antwort auf Ihre Frage geschrieben hätten, das ist absolut angemessen. – lexicore

Antwort

3

Im Gegensatz zu String, nein nein argument Konstruktor Integer. Also Integer::new ist kein Supplier<Integer>. makeFoo(Object::new) würde funktionieren.

1

Als lexicore pointed können wir nicht den Ausdruck Integer :: new machen, weil kein no-arg Konstruktor des Integer Objekts existiert. Die korrekte Syntax mit integer kann dies so einfach sein, wobei arg int Variable

foo<Integer> f = foo.makeFoo(() -> (arg)); 

Wrapping in new Integer (ARG) ist hier nicht notwendig zu sein.

Mehr Informationen zum Thema: Java 8 Supplier with arguments in the constructor