Я бы хотел по возможности избегать предупреждений Eclipse, поскольку теоретически они указывают, по крайней мере, на потенциальную проблему с кодом. Однако я пока не нашел хорошего способа устранить эту проблему. Я могу извлечь единственную строку, связанную с методом, отдельно и добавить @SuppressWarnings("unchecked") к этому методу, таким образом ограничивая влияние наличия блока кода, в котором я игнорирую предупреждения. Есть варианты получше? Я не хочу отключать эти предупреждения в Eclipse.
До того, как я пришел к коду, он был проще, но все равно вызывал предупреждения:
Type safety: The method put(Object, Object) belongs to the raw type HashMap. References to generic type HashMap<K,V> should be parameterized.
Переведено автоматически
Ответ 1
Очевидный ответ, конечно, не выполнять непроверенное приведение.
Если это абсолютно необходимо, то хотя бы попробуйте ограничить область применения @SuppressWarnings аннотации. Согласно его Javadocs, он может работать с локальными переменными; таким образом, это даже не влияет на весь метод.
Нет способа определить, Map действительно ли должен иметь общие параметры <String, String>. Вы должны заранее знать, какими должны быть параметры (или вы узнаете, когда получите ClassCastException). Вот почему код генерирует предупреждение, потому что компилятор не может знать, безопасно ли это.
Ответ 2
К сожалению, здесь нет хороших вариантов. Помните, цель всего этого - сохранить безопасность типов. "Java Generics" предлагает решение для работы с унаследованными библиотеками, не являющимися универсальными, и в разделе 8.2 есть одно, в частности, называемое "техникой пустого цикла". По сути, создайте небезопасное приведение и подавите предупреждение. Затем выполните цикл по карте следующим образом:
@SuppressWarnings("unchecked") Map<String, Number> map = getMap(); for (String s : map.keySet()); for (Number n : map.values());
Если обнаружится неожиданный тип, вы получите время выполнения ClassCastException, но, по крайней мере, это произойдет близко к источнику проблемы.
Ответ 3
Вау; Кажется, я нашел ответ на свой собственный вопрос. Я просто не уверен, что оно того стоит! :)
Проблема в том, что приведение не проверяется. Итак, вы должны проверить это самостоятельно. Вы не можете просто проверить параметризованный тип с помощью instanceof , потому что информация о параметризованном типе недоступна во время выполнения, поскольку была удалена во время компиляции.
Но вы можете выполнить проверку каждого элемента в хэше с помощью instanceof , и при этом вы можете создать новый типобезопасный хэш. И вы не вызовете никаких предупреждений.
Благодаря mmyers и Esko Luontola я параметризовал код, который изначально написал здесь, так что его можно обернуть где-нибудь в служебный класс и использовать для любой параметризованной хэш-карты. Если вы хотите лучше понять это и не очень знакомы с обобщениями, я рекомендую просмотреть историю редактирования этого ответа.
publicstatic <K, V> HashMap<K, V> castHash(HashMap input, Class<K> keyClass, Class<V> valueClass) { HashMap<K, V> output = newHashMap<K, V>(); if (input == null) return output; for (Object key: input.keySet().toArray()) { if ((key == null) || (keyClass.isAssignableFrom(key.getClass()))) { Objectvalue= input.get(key); if ((value == null) || (valueClass.isAssignableFrom(value.getClass()))) { Kk= keyClass.cast(key); Vv= valueClass.cast(value); output.put(k, v); } else { thrownewAssertionError( "Cannot cast to HashMap<"+ keyClass.getSimpleName() +", "+ valueClass.getSimpleName() +">" +", value "+ value +" is not a "+ valueClass.getSimpleName() ); } } else { thrownewAssertionError( "Cannot cast to HashMap<"+ keyClass.getSimpleName() +", "+ valueClass.getSimpleName() +">" +", key "+ key +" is not a " + keyClass.getSimpleName() ); } } return output; }
Это большая работа, возможно, за очень небольшое вознаграждение... Я не уверен, буду ли я использовать это или нет. Я был бы признателен за любые комментарии относительно того, считают ли люди, что оно того стоит или нет. Кроме того, я был бы признателен за предложения по улучшению: могу ли я сделать что-нибудь получше, кроме выдвижения AssertionErrors? Есть ли что-нибудь получше, что я мог бы выдать? Должен ли я сделать это проверяемым исключением?
Ответ 4
В настройках Eclipse перейдите в Java-> Компилятор-> Ошибки / предупреждения-> Универсальные типы и установите флажок Ignore unavoidable generic type problems.