2013-02-25 12 views
7

Betrachten Sie die UnaryFunction Schnittstelle definiert in Wirksame Java Generika Kapitel.Warum ist es sicher, diese ungeprüfte Warnung zu unterdrücken?

public interface UnaryFunction<T> { 
T apply(T arg); 
} 

und der folgende Code für die sichere UnaryFunction

// Generic singleton factory pattern 
private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() { 
    public Object apply(Object arg) { return arg; } 
}; 

// IDENTITY_FUNCTION is stateless and its type parameter is 
// unbounded so it's safe to share one instance across all types. 
@SuppressWarnings("unchecked") 
public static <T> UnaryFunction<T> identityFunction() { 
    return (UnaryFunction<T>) IDENTITY_FUNCTION; 
} 

Warum ist die Besetzung von IDENTITY_FUNCTION zu (UnaryFunction<T>) Rückkehr?

Das Buch sagt das über die Frage, die ich stelle, aber ich kann die Logik hier nicht folgen. Wo rufen wir die apply-Funktion auf, die die Identitätsoperation ausführt? Ich bin verwirrt, weil es diese Funktion ist, die das gleiche Objekt zurückgibt, ohne etwas zu verändern.

Die Besetzung von IDENTITY_FUNCTION zu (UnaryFunction<T>) erzeugt eine ungeprüften Guss Warnung, als UnaryFunction<Object> keine UnaryFunction<T> für jeden T ist. Aber die Identität Funktion ist speziell: es gibt sein Argument unverändert, so dass wir wissen, dass es typsicher es als UnaryFunction<T> was auch immer der Wert von T ist. Daher können wir die ungeprüfte Cast-Warnung unterdrücken, die von dieser Besetzung generiert wird. Sobald wir dies getan haben, kompiliert der Code ohne Fehler oder Warnung.

+0

Side Frage: Welches Buch verwenden Sie, und sagt es, was der Punkt dieses Codes ist? – asteri

+0

@Jeff Wirksames Java ist der Buchname und es ist dort im Kapitel Generika, speziell in dem Abschnitt, der generische Funktionen beschreibt. – Geek

Antwort

3

Die Besetzung ist sicher so sehr, nur als die Identitätsfunktion gibt das genaue Objekt, das es an erster Stelle geführt wurde. Daher gibt es zur Laufzeit keine Spezialisierung des generischen Parameters T, der die Besetzung verletzen kann.

Aka, Sie werfen ein Objekt als seinen eigenen Typ.

3

Mit Typ Löschung

T apply(T arg); 

tatsächlich ist

Object apply(Object arg); 

Jetzt für Identität

Abc x = ...; 
Abc y = IDENTITY.apply(x); 

man davon ausgehen kann, dass es immer richtig ist (entspricht y = x;).

(sehr pragmatisch.)

+0

Wo wird "apply" in dem betreffenden Code aufgerufen? – Geek

+0

Wenn identityFunction angewendet wird (.apply), wird dem Ergebnis 0 IDENTITY.apply (T) zugewiesen, was normalerweise nicht möglich ist, da das T des Parameters zur Laufzeit nicht da ist. –

1

identityFunction() gibt einfach die Funktion selbst zurück, die für verschiedene Objekte verwendet werden soll.

folgt ein Anwendungsbeispiel:

String result = identityFunction().apply("Hello"); 

Die Art Sicherheitswarnung ist wichtig. Es ist da, weil IDENTITY_FUNCTION so implementiert ist, dass der Compiler nicht garantieren kann, dass die Funktion den gleichen Typ wie die Eingabe zurückgibt. Betrachten Sie die folgende alternative Implementierung:

private static UnaryFunction<Object> CONST_FUNCTION = new UnaryFunction<Object>() { 
    public Object apply(Object arg) { return "Default"; } 
}; 

Diese Implementierung gibt immer einen String, so ist es natürlich nicht sicher es als eine einstellige Funktion auf einem generischen Datentyp zurück.

In unserem Fall (IDENTITY_FUNCTION) befindet sich der Beweis, dass der zurückgegebene Typ dem Eingabetyp entspricht, in der Implementierung. Wir geben die gleiche Instanz zurück, so dass der gleiche Typ garantiert ist. Wenn Sie Sicherheitswarnungen vom Typ unterdrücken, wird empfohlen, dies mit einem Beweis zu begründen.

+0

-1 Verwirrend. IdentityFunction() gibt die "Funktion selbst" nicht zurück, es gibt das _argument_ selbst zurück. Ich sehe keinen Grund, warum dieses Ergebnis vom Typ T "auf verschiedenen Objekten zu verwenden ist". In Ihrem Beispiel ist es eine Zeichenkette, die auf verschiedenen Objekten nicht _benützt _ werden kann. – user949300

+1

@ user949300: 'identityFunction()' gibt einen Verweis auf das Objekt zurück, das in der Variablen IDENTITY_FUNCTION gespeichert ist. Diese Referenz erlaubt Ihnen,'Alliv() 'aufzurufen, daher gibt' identityFunction() 'die Funktion selbst zurück. Es wäre besser gewesen, wenn die Namen nicht gleich wären. Ex 'getIdentityFunction() 'und' IDENTITY_FUNCTION'. Die erste Zeile der Antwort bezieht sich auf die Getter-Methode. – unholysampler

+0

danke - verstanden. Diese ganze Frage/System ist sehr verwirrend für etwas, das nichts tut :-). Ich kann meinen Downvote jedoch nicht rückgängig machen, bis Sie Ihre Antwort aufgrund von Einschränkungen in StackOverflow bearbeitet haben. – user949300

Verwandte Themen