Этой установке напоминает типизированных Гетерогенного Контейнер идиомов Блохи из Effective Java, пункта 29. Это также описано в статье Нила Гафтера по адресу Super Type Tokens.
Предупреждение происходит в этом фрагменте кода (обратите внимание на небольшую коррекцию):
<T> Handler<? extends T> getHandler(Class<T> type) {
// warning produced here "uses unchecked or unsafe operations."
return (Handler<? extends T>)handlers.get(type);
}
Код из Effective Java (также в статье Gafter в) хранит экземпляры типа T
как значения карты. Это позволяет избежать непроверенные предупреждения с помощью
return type.cast(map.get(type));
То есть, он использует Class.cast()
сделать отливку. У этого есть возвращаемое значение правильного типа, поэтому вам не нужно его бросать. Но, конечно, это просто делает литье внутри, и оно аннотируется с @SuppressWarnings("unchecked")
. Беспорядок все еще существует, но, по крайней мере, он скрыт.
Это не работает в вашем случае, по крайней мере, не напрямую, поскольку значения карты не относятся к типу T
, они относятся к типу Handler<? extends T>
. Было бы неплохо, если бы мы могли написать литерал класса для этого, что-то вроде Handler<? extends T>.class
, но это не сработает.
Для этого можно было бы использовать маркеры типа Super Gafter. В принципе создать анонимный подкласс Handler<T>
и называют getClass()
на нем:
<T> Handler<? extends T> getHandler(Class<T> type) {
Class<? extends Handler<T>> clazz = new Handler<T>() {
public T handle(HandlerArgument arg) { return null; }
}.getClass();
return clazz.cast(handlers.get(type));
}
Однако это НЕ РАБОТАЕТ. Это дает нам объект Class
правого статического типа, а затем мы можем вызвать его метод cast()
для выполнения кастинга для нас. Это позволяет избежать неконтролируемого предупреждения. Однако, как отметил Хольгер в этом комментарии, этот не может работать во время выполнения, поскольку обработчик, предоставляемый вызывающим пользователем, никогда не является экземпляром этого анонимного подкласса. В самом деле, это всегда с ошибкой ClassCastException
во время выполнения.
Это явно не решение. Тем не менее, это немного интересно в том, что он избегает предупреждений компилятора. Я оставлю это здесь, так как это может помочь указать путь к реальному решению.
В методе 'getHandler (класс type)', 'handlers.get (type, handler);' должен быть изменен на 'handlers.get (type);' –
Ian2thedv
К сожалению, правильно. Я обвиняю лишение сна. Я исправлю. – Daniel
Итак, похоже, что я был прав, думая, что не было «элегантного» решения, просто подталкивая «проблему» к другому уровню. Java Generics - это не C++-шаблоны, в конце концов. – Daniel