Общий код Java компилируется в eclipse, но не в командной строке - PullRequest
3 голосов
/ 11 ноября 2011

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

В частности, я думаю, что ябыл в состоянии настроить eclipse для использования моего системного компилятора, но это все еще не решило проблему.

В настоящее время я проверяю: «Настройки -> Java -> Установленные JRE».

Это содержит только одну JRE, которая является моей системной.

Вот особенности проблемы

У меня есть универсальный класс Java, который принимаетв качестве аргумента тип Enum, например, так:

public class MyClass<T extends Enum<T>>

Где-то внутри класса я сравниваю известное значение перечисления со значениями T. Так, например, давайте предположим, что у меня есть это перечисление:

public enum OtherEnum{
 a,
 b
}

А потом я проверяю:

protected void foo(T enumVal){
    if(enumVal == OtherEnum.a){
        // do something
    }
    else if(enumVal == OtherEnum.b){
        // do something else
    }
}

Это без проблем компилируется в eclipse, но в командной строке javac я получаю эту ошибку:

несопоставимые типы: T и OtherEnum

Я пробовал это на двух системах, которые используют вариант Java 1.6 (1.6.0_26 и 1.6.0_16).Один - это Mac, другой - Linux.Они оба выдают одну и ту же ошибку, в то время как eclipse компилируется без проблем.

Итак:

  1. Как мне убедиться, какое затмение компилятора использует?

  2. В чем тут проблема?

Спасибо!

Ответы [ 4 ]

5 голосов
/ 11 ноября 2011

Это ошибка javac, исправленная в JDK 7.

См. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436

2 голосов
/ 11 ноября 2011

Очень интересный вопрос.

Следующий код не компилируется

    Integer x = null;
    String s = null;
    if(x==s){}   // error: incomparable types

JLS3 # 15.21.3 [1] говорит

Ошибка времени компиляции возникает, если невозможно преобразовать тип одного операнда в тип другого путем преобразования приведения (§5.5)

Очевидно, предыдущий пример выглядит как очевидная программная ошибка, поэтому спецификация пытается ее перехватить и предупредить программиста. Там не было бы никаких проблем, Java хотел бы позволить это. Обходной путь для примера должен привести одну сторону к Object.

Возвращаясь к вашему вопросу, нам нужно решить, можно ли OtherEnum привести к T или наоборот. Это удивительно сложный вопрос; следуя процедуре JLS3 # 5.5 [2], ответ - нет.

Все зависит от того, можно ли OtherEnum привести к Enum<T>; тогда мы можем найти супертипы X=Enum<OtherEnum> и Y=Enum<T>, которые являются доказуемо различными параметризованными типами. Так что приведение является незаконным.

Ну, такая спецификация слишком сложна, кого в здравом уме это волнует?

Вы можете обойти это, приведя один к Object, скажем (Object)enumVal == OtherEnum.a

Java 7 ведет себя по-другому, он компилирует ваш код. Я не знаю причину. Возможно, в Java7 появилась новая ошибка. Или у него есть новая спецификация, которая позволяет код (но у нас нет доступа к новой спецификации). Другая возможность состоит в том, что я неправильно понял термин «доказуемо отличные параметризованные типы»; однако без формального определения интуитивно понятно, что Enum<OtherEnum> и Enum<T> различны.

*

1035 исх *

[1] http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.21.3

[2] http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#20232

1 голос
/ 11 ноября 2011

Eclipse использует собственную реализацию компилятора Java (ECJ), не имеющую ничего общего с javac.

Eclipse Compiler для Java:

Инкрементный компилятор Java. Реализованный как Eclipse Builder, он основанный на технологии, развитой из VisualAge для компилятора Java. В в частности, он позволяет запускать и отлаживать код, который все еще содержит неразрешенные ошибки.

0 голосов
/ 11 ноября 2011

Отдельные компиляторы ... Использование == вызывает более строгую проверку времени компиляции, поэтому в CL он обеспечивает сравнение типов и ошибки.В Eclipse вы можете управлять настройками для времени компиляции и, так сказать, ослабить ограничения.

Вы можете попробовать Enum.equals (), и он может не обеспечить такое строгое сравнение типов времени компиляции.просто мысль.

...