2009-07-24 12 views
7

Mamy kilka testów jednostkowych, które kompilują się i działają dobrze w Eclipse 3.4, ale kiedy próbujemy je skompilować za pomocą javac, to zawiedzie. Udało mi się zredukować kod do czegoś małego i niezależnego, więc nie ma żadnych zewnętrznych zależności. Sam kod nie będzie większego sensu, bo to wszystko jest wyrwane z kontekstu, ale to nie ma znaczenia - po prostu trzeba dowiedzieć się, dlaczego javac nie podoba:Dlaczego Eclipse skompilował to, ale javac nie?

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; 
    } 
} 

Próbowałem już z JDK 1.5.0_10 i 1.6.0_13, z tym samym wynikiem:

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

Myślę, że to jest idealnie poprawna Java. Metoda SubMatcher.with() zwraca bardziej specyficzny typ niż BaseMatcher.with(), ale wydaje się, że kompilator uważa, że ​​typem zwracanym jest BaseMatcher. Jednak możliwe jest, że kompilator Eclipse nieprawidłowo dopuszcza coś, czym nie powinien być.

Wszelkie pomysły?

+1

Mogę odtworzyć ten błąd kompilatora z jdk 1.6 na Linuksie. Wygląda na to, że typy zmiennych kowariancyjnych wprowadzone za pomocą języka Java 1.5 nie działają poprawnie w tym przykładzie. – Mnementh

Odpowiedz

7

w BaseMatcher trzeba określić parametry Typ:

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

w celu umożliwienia javac dopasować metoda with

PS

imho jest bug Eclipse kompilator

+0

Ach, nie mogę uwierzyć, że nie zauważyłem tego ... – skaffman

+0

Ty i Greg obaj dostaliście odpowiedź, ale muszę komuś dać nagrodę, a ty byłeś trochę szybszy ... – skaffman

0

Sprawdź jre lub jdk, z którymi kompilujesz, zarówno w środowisku Eclipse, jak i terminalu. Może to może być problem z wersją.

+0

Eclipse używa środowiska JRE 1.5.0_10, tak samo jak javac, którego próbuję. – skaffman

+0

Eclipse ma swój własny kompilator, tzn. Nie używa javac – robinr

0

Działa dla mnie:

 
$ 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 
$ 

Niejasno pamiętam taki raport błędów, ale nie mogę teraz podać do niego odnośnika.

7

Zrobiłem to z powodzeniem zbudować dodając <?,?> do Matcher w SubMatcher.with:

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

bez tego, podpis metoda różni się od podstawy. Zastanawiam się, czy istnieje błąd w sprawdzaniu, którego nie zauważyłem.

+3

To jest interesująca sytuacja. Można argumentować, że javac jest winien tutaj winy, ponieważ dozwolona jest adnotacja @Override, ale wtedy używa ona metody podklasy, a nie przesłoniętej. Jest to niespójne, adnotacja ma na celu zapobieganie tego rodzaju problemom. Pytanie, czy metoda z parametrem typu surowego może zastąpić metodę nadklasy tego samego typu z skaffman

Powiązane problemy