Кастинг от Объекта в Java, не получая предупреждение непроверенное

От Python FAQ:

Списки и кортежи, в то время как подобный во многих отношениях, обычно используются существенно различными способами. Кортежи могут думаться как являющийся подобным записям Паскаля или структурам C; они - небольшие коллекции связанных данных, которые могут иметь различные типы, на которых управляют как группа. Например, Декартова координата соответственно представлена как кортеж двух или трех чисел.

Списки, с другой стороны, больше похожи на массивы на других языках. Они имеют тенденцию содержать переменное количество объектов, все из которых имеют тот же тип и на которых управляют один за другим.

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

7
задан Thomas Jung 21 November 2009 в 06:47
поделиться

6 ответов

Отредактировано (на основе уточнения вопроса)

Приведение к HashMap (кстати, с использованием Map вместо HashMap , возможно, лучший выбор) - совсем другое дело. К сожалению, в этом случае невозможно избежать непроверенного предупреждения из-за стирания типа. Тем не менее, вы можете использовать его как неуниверсальную карту:

if (foo instanceof Map) {                                                                                                                                                                                                        
  ((Map) foo).put("a", 5);                                                                                                                                                                                    
}

Очевидно, что вам придется использовать «получает», и вы потеряете (воспринимаемую) безопасность типов, но не будет непроверенного предупреждения.


Должно быть подробнее к этой истории. Следующий код:

Map<String, Object> map = Maps.newHashMap(); // or new HashMap<String, Object>();
Object foo = map.get("bar");
if (foo instanceof Widget) {
  ((Widget) foo).spin();
}

НЕ генерирует для меня непроверенное предупреждение. Я также не могу представить, зачем это нужно. Если вы заранее знаете, что "bar" всегда будет возвращать виджет, сделайте следующее:

Widget widget = (Widget) map.get("bar");
widget.spin();

также будет работать отлично. Я что-то здесь упускаю?

4
ответ дан 7 December 2019 в 01:22
поделиться

Если ваша Карта содержит объекты одного типа (например, все виджеты), то вы можете использовать Map , чтобы исключить и приведение, и предупреждение.

Однако, если вы держите объекты произвольного типа, это показывает, что у вас более глубокая проблема дизайна. Если вы знаете, какой тип объекта будет основан на имени (например, «bar» всегда дает вам виджет), рассмотрите возможность использования объекта с методом под названием Widget getBar () , а не с Map .

Если вы не знаете, какой будет «полоса», когда вы получите ее с карты, у вас есть еще более серьезная проблема проектирования, и вам следует подумать об использовании некоторых объектно-ориентированных принципов для уменьшения сцепления.

1
ответ дан 7 December 2019 в 01:22
поделиться

Или, может быть, тот факт, что я получаю предупреждение, означает, что мне следует пересмотреть то, что я делаю.

Вы поняли. Логическим шагом было бы создание Map вместо Map . Если по какой-то причине это не вариант, вы можете сделать что-то вроде:

Widget w = Widget.class.cast(foo);
w.spin();

Это больше не выводит предупреждение компилятора, но это еще не обязательно означает, что ваша Карта смешанных объектов является хорошая практика.

Правка : как указал ChssPly76, на самом деле это не должно было генерировать предупреждение о "непроверенном приведении". Я тестировал его в Eclipse, и он действительно не выдавал особого предупреждения. Можете ли вы опубликовать SSCCE (класс с main () , чисто демонстрирующий проблему), чтобы мы могли лучше понять, что происходит?

Edit 2 : итак вы используете карту, которая может содержать общие структуры, такие как карты. Это немного объясняет. Что ж, кроме изменения структуры, я не вижу другого выхода, кроме как жить с аннотацией @SuppressWarnings ("unchecked") .

1
ответ дан 7 December 2019 в 01:22
поделиться

Я думаю, что основная проблема заключается в классе Object

HashMap<String, Object> map;

, если вы хотите удалить предупреждение о приведении, тогда вам нужно указать базовый класс / интерфейс.

1
ответ дан 7 December 2019 в 01:22
поделиться

Не знаю, как вы используете объекты, но есть:

for(Map.Entry<String, Widget> entry = map.entrySet())
{
     entry.getValue().spin();
}
0
ответ дан 7 December 2019 в 01:22
поделиться

Если все остальное (полиморфная реализация, приведение типов) не применимо, вы можете реализовать гетерогенный контейнер , как описано в Правило 33: Рассмотрите безопасные по типу гетерогенные контейнеры в «Эффективной Java», 3-е издание. Контейнер отвечает за безопасность типов.

public class Container{
  private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();
  public <T> void set(Class<T> klass, T thing) {
    favorites.put(klass, thing);
  }
  public <T> T get(Class<T> klass) {
    return klass.cast(favorites.get(klass));
  }
}

Проблема с вашим примером заключается в том, что вы используете HashMap в качестве типа записи. Это не может быть представлено литералом класса как токен типа . Таким образом, вы должны реализовать некоторую форму токена супертипа :

public abstract class TypeReference<T> {}

Затем ваш клиентский код расширит TypeReference для каждого необходимого токена типа:

TypeReference<?> typeToken = new TypeReference<HashMap<String, Integer>>{};

Информация о типе доступна во время выполнения. Реализация контейнера затем должна выполнить проверку типа на соответствие фактическим параметрам типа токена типа (подкласс TypeReference).

Это полное решение, но для его реализации предстоит много работы. Ни одна из известных мне библиотек коллекций не поддерживает контейнеры со ссылками на типы.

3
ответ дан 7 December 2019 в 01:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: