2013-02-25 2 views
7

Рассмотрите интерфейс UnaryFunction, определенный в Эффективная Java-концепция.Почему безопасно подавлять это непроверенное предупреждение?

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

и следующий код для возвращения 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; 
} 

Почему бросок IDENTITY_FUNCTION к (UnaryFunction<T>) безопасно?

В книге говорится об этом вопросе, который я задаю, но я не могу следовать логике здесь. Где мы вызываем функцию apply, которая выполняет операцию идентификации? я запутался, потому что именно эта функция возвращает тот же самый объект, который был передан в него, без изменения чего-либо.

Бросок IDENTITY_FUNCTION к (UnaryFunction<T>) генерирует предупреждение об бесконтрольно литой, а UnaryFunction<Object> не UnaryFunction<T> для каждого T. Но функция идентичности является специальной: она возвращает свой аргумент без изменений, поэтому мы знаем, что он использует тип как UnaryFunction<T> независимо от значения T. Таким образом, мы с уверенностью можем подавить предупреждение без предупреждения, которое генерируется . Как только мы это сделаем, код компилируется без предупреждения или .

+0

Боковой вопрос: какую книгу вы используете, и она говорит, что точка этого кода? – asteri

+0

@Jeff Эффективная java - это имя книги, и она есть в главе generics, особенно в разделе, описывающем общие функции. – Geek

ответ

3

Актерский безопасен настолько, только как тождественная функция возвращает объект точный, который был передан ему в первую очередь. Таким образом, во время выполнения нет специализации общего параметра T, который может нарушить приведение.

Ака, вы бросаете объект как свой собственный тип.

3

С типом стиранием

T apply(T arg); 

на самом деле

Object apply(Object arg); 

Теперь для идентичности

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

можно предположить, что это всегда правильно (эквивалентно y = x;).

(очень прагматичны.)

+0

Где находится 'apply', вызываемый в коде? – Geek

+0

Всякий раз, когда применяется функция identityFunction (.apply), назначается результат T IDENTITY.apply (T), который обычно не может быть выполнен, так как параметр T отсутствует во время выполнения. –

1

identityFunction() просто возвращает сама функция, которая будет использоваться для разных объектов.

Ниже приведен пример использования: Предупреждение безопасности

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

Тип имеет важное значение. Это происходит потому, что IDENTITY_FUNCTION реализован таким образом, что компилятор не может гарантировать, что функция возвращает тот же тип, что и вход. Рассмотрим следующую альтернативную реализацию:

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

Эта реализация всегда возвращает строку, так что это явно не безопасно, чтобы вернуть его в качестве одноместной функции на общий тип данных.

В нашем случае (IDENTITY_FUNCTION) доказательство того, что возвращаемый тип совпадает с типом ввода, находится внутри реализации. Мы возвращаем один и тот же экземпляр, поэтому он имеет одинаковый тип. Когда вы подавляете предупреждения о безопасности типа, рекомендуется обосновать это доказательством.

+0

-1 Смущает. IdentityFunction() не возвращает «сама функция», она возвращает сам _argument_. Я не вижу причины, почему этот результат типа T «используется для разных объектов». В вашем примере это строка, которая _cannot_ будет _used_ на разных объектах. – user949300

+1

@ user949300: 'identityFunction()' возвращает ссылку на объект, хранящийся в переменной 'IDENTITY_FUNCTION'. Эта ссылка позволяет вам вызвать 'apply()', поэтому 'identityFunction()' эффективно возвращает сама функция. Было бы лучше, если бы имена были не одинаковыми. Ex 'getIdentityFunction()' и 'IDENTITY_FUNCTION'. Первая строка ответа относится к методу геттера. – unholysampler

+0

спасибо - понял. Весь этот вопрос/система очень запутан для чего-то, что ничего не делает :-). Я не могу «отменить» мой downvote, пока вы не отредактируете свой ответ из-за ограничений в StackOverflow. – user949300

Смежные вопросы