ошибка javac: необратимые типы с обобщениями? - PullRequest
23 голосов
/ 28 января 2011

Есть еще несколько вопросов SO, говорящих о обобщениях, компилирующих OK с компилятором Eclipse, но не javac (т. Е. Java: Обобщения обрабатываются по-разному в Eclipse, а javac и Generics компилируется и запускается в Eclipse, ноне компилируется в javac ) - однако это выглядит немного иначе.

У меня есть класс enum:

public class LogEvent {
   public enum Type {
       // ... values here ...
   }
   ...
}

, и у меня есть другой класс сметод, который принимает произвольные объекты типов, произошедших от Enum:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{
    if (code instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)code;
    ...

Это отлично работает в Eclipse, но когда я делаю чистую сборку с ant, я получаю пару ошибок,один на линии instanceof, другой на линии литья:

443: inconvertible types
    [javac] found   : E
    [javac] required: mypackage.LogEvent.Type
    [javac]         if (code instanceof LogEvent.Type)
    [javac]             ^

445: inconvertible types
    [javac] found   : E
    [javac] required: com.dekaresearch.tools.espdf.LogEvent.Type
    [javac]             LogEvent.Type scode = (LogEvent.Type)code;
    [javac]                                                  ^

Почему это происходит, и как я могу обойти эту проблему, чтобы она правильно компилировалась?

Ответы [ 4 ]

32 голосов
/ 28 января 2011

Я не знаю, почему это происходит, но обходной путь прост:

@Override public <E extends Enum<E>> void postEvent(
    Context context, E code, Object additionalData) 
{
    Object tmp = code;
    if (tmp instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)tmp;
    ...

Это уродливо, но работает ...

8 голосов
/ 28 января 2011

Возможно, это потому, что вы объявили E как нечто, расширяющее Enum . Я не могу сказать, что полностью понимаю, но похоже, что он ограничивает набор типов некоторым подмножеством, которое по какой-то причине не может включать LogEvent.Type. Или, может быть, это просто ошибка в компиляторе. Я был бы счастлив, если бы кто-то мог объяснить это более четко, но вот что вы можете сделать:

public <E extends Enum<?>> void postEvent(E code) 
{
    if (code instanceof LogEvent.Type)
    {
        LogEvent.Type scode = (LogEvent.Type)code;
        ...
    }
    ...

Это работает, и это более элегантно, чем просто приведение к объекту.

4 голосов
/ 03 мая 2011

У меня была похожая проблема, и я обновил ее с jdk1.6.0_16 до jdk1.6.0_23, и она ушла без каких-либо изменений кода.

0 голосов
/ 28 января 2011

Для использования instanceof оба операнда должны наследовать / реализовывать один и тот же класс / интерфейс.
E просто не может быть приведен к LogEvent.Type

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

public interface EventType { }
public class LogEvent  {
    public enum Type implements EventType {}
}

public void postEvent(Context context, EventType code, Object additionalData) {
    if(code instanceof LogEvent.Type) {
    }
}
...