2009-07-24 2 views
7

У нас есть некоторые модульные тесты, которые компилируются и выполняются отлично в Eclipse 3.4, но когда мы пытаемся скомпилировать их с помощью javac, это терпит неудачу. Мне удалось перевести код на что-то маленькое и автономное, поэтому он не имеет внешних зависимостей. Сам код не имеет особого смысла, потому что это все из контекста, но это не имеет значения, - мне просто нужно выяснить, почему Javac не нравится:Почему Eclipse компилирует это, но javac нет?

public class Test { 

    public void test() { 
     matchOn(someMatcher().with(anotherMatcher())); 
    } 

    void matchOn(SubMatcher matcher) {} 

    SubMatcher someMatcher() { 
     return new SubMatcher(); 
    } 

    Matcher anotherMatcher() { 
     return null; 
    } 
} 

interface Matcher <U, T> {} 

class BaseMatcher implements Matcher { 
    public BaseMatcher with(Matcher<?,?> matcher) { 
     return this; 
    } 
} 

class SubMatcher extends BaseMatcher { 
    @Override 
    public SubMatcher with(Matcher matcher) { 
     return this; 
    } 
} 

Я попытался с JDK 1.5.0_10 и 1.6.0_13, с тем же результатом:

Test.java:6: matchOn(test.SubMatcher) in test.Test cannot be applied to (test.BaseMatcher) 
       matchOn(someMatcher().with(anotherMatcher())); 
       ^
1 error 

Я думаю, что это вполне допустимо Java. Метод SubMatcher.with() возвращает более конкретный тип, чем BaseMatcher.with(), но, похоже, компилятор считает, что тип возврата - BaseMatcher. Однако возможно, что компилятор Eclipse неправильно разрешает то, чего он не должен.

Любые идеи?

+1

Я могу воспроизвести эту ошибку компилятора с помощью jdk 1.6 на Linux. Кажется, что ковариантные типы возвращаемых данных, введенные с Java 1.5, не работают корректно в этом примере. – Mnementh

ответ

7

в BaseMatcher вам необходимо указать параметры типа:

public SubMatcher with(Matcher<?, ?> matcher) { 

для того, чтобы позволить Javac, чтобы соответствовать вашему with метод

PS

имхо это ошибка Затмения компилятора

+0

Ach, я не могу поверить, что не заметил этого .... – skaffman

+0

Сам и Грег оба получили ответ, но я должен отдать приз кому-то, и вы были немного быстрее ... – skaffman

0

Проверьте, какие jre или jdk вы компилируете как на Eclipse, так и на терминале. Возможно, это может быть проблема с версией.

+0

Eclipse использует 1.5.0_10 JRE, как и javac, который я пытаюсь. – skaffman

+0

Eclipse имеет свой собственный компилятор, то есть он не использует javac – robinr

0

Работает для меня:

 
$ java -version 
openjdk version "1.7.0-internal" 
OpenJDK Runtime Environment (build 1.7.0-internal-****-2009_07_23_10_21-b00) 
OpenJDK 64-Bit Server VM (build 16.0-b06, mixed mode) 
$ javac -XDrawDiagnostics Test.java 
$ 

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

7

Я сделал это успешно построить путем добавления <?,?> к Matcher в SubMatcher.with:

class SubMatcher extends BaseMatcher { 
    @Override 
    public SubMatcher with(Matcher<?,?> matcher) { 
     return this; 
    } 
} 

Без этого метод подписи отличается от основания. Интересно, есть ли ошибка в проверке @Override, которая не замечает этого.

+3

Это интересная ситуация. Вы можете утверждать, что javac здесь виноват, потому что он разрешен аннотацией @Override, но затем он использует метод подкласса, а не переопределенный. Это противоречиво, аннотация там, чтобы предотвратить такую ​​проблему. Вопрос заключается в том, может ли метод с параметром raw type переопределять метод суперкласса с тем же типом с skaffman

Смежные вопросы