2013-02-25 11 views
7

Rozważmy interfejs UnaryFunction zdefiniowany w Efektywny rozdział dotyczący generics Java.Dlaczego można ukryć to niezaznaczone ostrzeżenie?

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

i następujący kod do zwrotu 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; 
} 

Dlaczego obsada IDENTITY_FUNCTION do (UnaryFunction<T>) bezpieczne?

Książka mówi o tym pytaniu, ale nie mogę podążać za logiką tutaj. Gdzie wywoływamy funkcję apply, która wykonuje operację tożsamości? jestem zdezorientowany, ponieważ jest to funkcja, która zwraca ten sam obiekt przekazany do niego bez modyfikowania czegokolwiek.

Obsada IDENTITY_FUNCTION do (UnaryFunction<T>) generuje ostrzeżenie niezaznaczone odlewu, jak UnaryFunction<Object> nie jest UnaryFunction<T> dla każdego T. Ale funkcja tożsamości jest wyjątkowa: to zwraca niezmienioną argumentację, więc wiemy, że jest to bezpieczne w użyciu przy użyciu jako UnaryFunction<T> niezależnie od wartości T. W związku z tym możemy z całą pewnością ukryć niezaznaczone ostrzeżenie, które zostało wygenerowane przez tę obsadę w postaci . Gdy to zrobimy, kod kompiluje się bezbłędnie lub ostrzeżenie .

+0

Side: jaka książka używasz, i to powiedzieć o co chodzi z tym kodem jest? – asteri

+0

@Jeff Efektywna Java jest nazwą książka i jest tam w generyków rozdziału, w szczególności w części opisującej funkcje generyczne. – Geek

Odpowiedz

3

W obsadzie jest o tyle bezpieczne tylko jako funkcja tożsamości zwraca obiekt dokładny, który został przekazany do niego w pierwszej kolejności. W związku z tym w czasie wykonywania nie ma specjalizacji ogólnego parametru T, który może naruszać obsadę.

Aka, rzucasz obiektem, ponieważ jest to jego własny typ.

3

z typem skasowaniem

T apply(T arg); 

faktycznie jest

Object apply(Object arg); 

Teraz tożsamości

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

jeden może zakładać, że zawsze jest poprawny (odpowiada y = x;).

(bardzo pragmatyczne.)

+0

Gdzie jest 'apply' zwany w kodzie w pytaniu? – Geek

+0

Kiedy identityFunction stosuje się (.apply) wynik jest przypisany T IDENTITY.apply (T), który zwykle nie może być wykonane, jako T parametr nie istnieje w czasie wykonywania. –

1

Funkcja identityFunction() po prostu zwraca samą funkcję, która ma być używana na różnych obiektach.

Poniżej znajduje się przykład użycia:

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

typu ostrzeżenie bezpieczeństwo jest ważne. Jest tam, ponieważ funkcja IDENTITY_FUNCTION jest zaimplementowana w taki sposób, że kompilator nie może zagwarantować, że funkcja zwróci ten sam typ, co dane wejściowe. Rozważmy następujący alternatywną implementację:

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

Ta implementacja zawsze zwraca ciąg znaków, więc nie jest to oczywiście bezpiecznie powrócić go jako jednoargumentowego funkcji na ogólny typ danych.

W naszym przypadku (IDENTITY_FUNCTION), dowód, że zwracany typ jest taki sam, jak typ wejścia jest wewnątrz realizacji. Zwracamy tę samą instancję, więc gwarantujemy ten sam typ. Podczas tłumienia ostrzeżeń o bezpieczeństwie typu zalecane jest uzasadnienie go za pomocą dowodu. Pytanie

+0

-1 Mylące. IdentityFunction() nie zwraca "samej funkcji", zwraca sam _argument_. Nie widzę powodu, dla którego ten wynik typu T miałby być "użyty na różnych obiektach". W twoim przykładzie jest to ciąg, którego _cannot_ nie może używać na różnych obiektach. – user949300

+1

@ user949300: 'identityFunction()' zwraca odniesienie do obiektu przechowywanego w zmiennej 'IDENTITY_FUNCTION'. Odwołanie to pozwala wywołać 'apply()', więc 'identityFunction()' skutecznie zwraca samą funkcję. Byłoby lepiej, gdyby nazwiska nie były takie same. Ex 'getIdentityFunction()' i 'IDENTITY_FUNCTION'. Pierwsza linia odpowiedzi dotyczy metody gettera. – unholysampler

+0

dzięki - rozumiesz. To całe pytanie/system jest bardzo mylące z powodu czegoś, co nic nie robi :-). Nie można „cofnąć” mój downvote choć aż edytować swoich odpowiedzi z powodu ograniczeń w StackOverflow. – user949300

Powiązane problemy