2013-08-11 3 views
6

Я уверен, что это безопасный тип, но просто хотел проверить, как Eclipse просит меня поставить аннотацию @SuppressWarnings("unchecked").Является ли мой код безопасным?

Map<String, IFace> faces; 

public <T extends IFace> T getFace(String key) 
{ 
    return (T) faces.get(key); 
} 
+5

Отвечая на мой собственный вопрос: Нет, это не потому, что я могу иметь два РАЗНЫХ класса 'ClassA' и' ClassB', которые реализуют 'IFace' в' faces'. Во время выполнения 'T' может быть' ClassA' или 'ClassB'. – Cheetah

+0

Помечено, так как мне очень интересна аналогичная проблема –

+2

Почему здесь есть дженерики? Если вы просто ссылаетесь на вещи как «IFace», вам не нужны дженерики/литье. –

ответ

4

Это не безопасный тип. Вы повышаете рейтинг, поэтому, если вы примените несовместимый производный класс, в какой-то момент вы столкнетесь с ошибкой.

Например, если A_Face и B_Face оба выпускаются IFace. В какой-то момент вы можете лить B_Face в качестве A_Face, который не является безопасным для типа.

0

Посмотрите на крайний случай. Допустим, IFace является acutally Object, ваш код будет выглядеть следующим образом:

static Map<String, Object> myMap = new HashMap<>(); 

public static void main(String[] args) throws Exception { 
    myMap.put("ONE", 1); 
    myMap.put("TWO", "TWO"); 
    myMap.put("THREE", new Date()); 

    final Calendar calendar1 = getThing("ONE"); 
    final Calendar calendar2 = getThing("TWO"); 
    final Calendar calendar3 = getThing("THREE"); 
} 

public static <T> T getThing(String key) { 
    return (T) myMap.get(key); 
} 

Таким образом, вы ставите на class чем extends Object в вашу Map (так что любой class).

Но когда вы вызываете getThing, вы делаете неявный приведение к вашему желаемому типу. Должно быть достаточно очевидно, что я могу позвонить getThing с любым class, и он будет слепо пытаться применить к нему.

В приведенном выше примере я помещаю некоторые вещи в свой Map, а затем пытаюсь восстановить их все как Calendar.

0

Классический способ справиться с этим с «типизированной гетерогенной контейнер»:

Map<Class<?>, IFace> faces; 

public <T extends IFace> T getFace(Class<T> key) { 
    return t.cast(faces.get(key)); 
} 

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

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