Подтвердить что ты не робот

Почему я получаю "Недопустимый общий тип для instanceof"?

Дано:

public class C<T> {
    private class D {
        public boolean equals( Object o ) {
            if ( !(o instanceof D) )    // line 4
                return false;
            D other = (D)o;             // line 6
            return i == other.i;
        }
        int i;
    }
}

Я получаю:

C.java:4: illegal generic type for instanceof
          if ( !(o instanceof D) )
                              ^

Я также получаю предупреждение "непроверенный бросок" о строке 6. Почему? o не является общим типом - это просто обычный Object. Как я могу правильно реализовать equals() как для проверки, так и для приведения в экземпляр D?

Примечание. Очевидно, что этот пример кода представляет собой сокращенную версию моего фактического кода. Реальные классы для C и D намного больше, а D - внутренний <<29 > C, используемый его реализацией.

FYI: реальный D использует общий параметр T.

4b9b3361

Ответ 1

O не является общим типом - это просто простой объект.

Это не проблема. Проблема... и первопричина обеих ошибок компиляции... заключается в том, что D является общим классом. И это общее, потому что это нестатический вложенный класс в родовом классе. Его полное имя будет some.pkg.C<T>.D.

FYI: реальный D использует общий параметр T.

И тот факт, что он может использовать T, является тем, что делает D общий класс.

Причина, по которой вы не можете использовать instanceof D или (D), является стиранием общего типа. В принципе, среда выполнения не может различать типы (скажем) C<String>.D и C<Integer>.D. И поскольку он не может этого сделать, он не может определить, должен ли instanceof D возвращать true или false, или если (D) должен преуспеть или выбросить ClassCastException.

Одним из решений было бы объявить D статическим. Но это не будет работать с вашим "реальным D", потому что статический класс не может использовать параметр универсального типа из окружающего класса (ов). Ваш "FYI" говорит, что он это делает.

Другим решением является создание экземпляра внешнего класса C, передающего ему фактический тип T в качестве экземпляра java.lang.Class<T>. Затем используйте этот экземпляр Class для реализации проверок типов выполнения и выполнения при необходимости. Это, вероятно, будет грязным.

Третье решение - тщательно проанализировать код и определить, безопасно ли оно для аннотаций @SuppressWarning для подавления предупреждений о "небезопасных отбросах" и т.д.

Какое стирание стилей? 'o' имеет тип Object напрямую.

Фактически Object является объявленным типом переменной o. Фактический объект, скорее всего, будет иметь другой тип, и именно этот тип (если это экземпляр D, например) подвергнется стиранию типа.

Ответ 2

Если вы сделаете внутренний класс статическим, код компилируется отлично.

Пример:

private static class D{...}

Прочитайте здесь для разницы.

Вы также можете попробовать o.getClass() != D.class (после того, как, конечно, o не будет нулевого).

Ответ 3

@StephenC прав, поскольку проблема заключается в том, что D означает C<T>.D, который является параметризованным типом. Решение состоит в том, чтобы использовать тип raw или параметрический тип:

if ( !(o instanceof C.D) )

или

if ( !(o instanceof C<?>.D) )

Ответ 4

D.class.isInstance(o)

похоже, работает здесь.