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