Тип безопасности: Не проверено приведение от объекта - PullRequest
39 голосов
/ 07 апреля 2010

Я пытаюсь привести объект к своему классу Action, но это приводит к предупреждению:

Type safety: Unchecked cast from Object to Action<ClientInterface>

Action<ClientInterface> action = null;
try {
 Object o = c.newInstance();
 if (o instanceof Action<?>) {
  action = (Action<ClientInterface>) o;
 } else {
  // TODO 2 Auto-generated catch block
  throw new InstantiationException();
 }
 [...]

Спасибо за любую помощь

Ответы [ 6 ]

62 голосов
/ 07 апреля 2010

Да - это естественное следствие стирания типа . Если o на самом деле является экземпляром Action<String>, который не будет перехвачен приведением - вы увидите проблему только при попытке использовать его, передав ClientInterface вместо строки.

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

@SuppressWarnings("unchecked")

как аннотация функции, но вы не можете легко разобраться в основной проблеме: (

15 голосов
/ 07 апреля 2010

Как обычно, Джон Скит прав.

Чтобы уточнить непростую часть его ответа:

Дано

class ClientAction implements Action<ClientInterface> {}

Вы можете написать:

Class<? extends Action<ClientInterface>> c = ClientAction.class;
Action<ClientInterface> action = c.newInstance();

Это исключает как приведение, так и предупреждение за счет введения неуниверсального типа, поэтому вы можете использовать .class для получения достаточно точно набранного Class объекта.

6 голосов
/ 07 апреля 2010

Предупреждение означает, что компилятор не может гарантировать безопасность типов, даже если приведение работает нормально во время выполнения. Из-за стирания во время исполнения кастинг является просто кастом к действию. Вполне возможно, что базовый универсальный класс не имеет типа ClientInterface, как ожидалось. В этом случае проблема появится позже (возможно, даже намного позже), как ClassCastException.

В этом конкретном случае я рекомендую подавить это конкретное предупреждение с помощью следующей директивы компилятора:

@SuppressWarnings("unchecked")
2 голосов
/ 07 апреля 2010

Не беспокойся. Дело в том, что компилятор Java не может знать, каков реальный тип объекта.

1 голос
/ 07 апреля 2010

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

0 голосов
/ 26 марта 2018

Это удрученный.Это динамическое приведение, при котором компилятор не имеет представления о реальном объекте, на который указывает ссылка.

Вы получаете это предупреждение, потому что тип целевого объекта приведения Action<ClientInterface> является параметризованным типом , и компилятор не может гарантировать, что тип объекта, который будет приведен, имеет тот же тип.

Если вы не хотите подавлять это предупреждение и не заботитесь о параметре типа, вы можете изменить код на этот, используя подстановочные знаки:

Action<?> action = null;
try {
 Object o = c.newInstance();
 if (o instanceof Action<?>) {
  action = (Action<?>) o;
 } else {
  // TODO 2 Auto-generated catch block
  throw new InstantiationException();
 }
 [...]

Это намного безопаснее, потому что instanceof не может проверить, что o является объектом Action<ClientInterface>, он просто проверяет, является ли o объектом Action, поскольку дальнейшая информация общего типа будет стерта во время выполнения.

...