为什么Eclipse编译这个,但javac不编译?

ska*_*man 7 java compiler-construction jls

我们有一些单元测试可以在Eclipse 3.4中编译和运行,但是当我们尝试使用javac编译它们时,它会失败.我已经设法将代码缩减为小而自包含的东西,因此它没有外部依赖性.代码本身没有多大意义,因为它完全脱离了上下文,但这并不重要 - 我只需要找出为什么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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我试着JDK 1.5.0_101.6.0_13,与相同的结果:

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

我认为这是完全有效的Java.SubMatcher.with()方法返回一个比BaseMatcher.with()更具体的类型,但编译器似乎认为返回类型是BaseMatcher.但是,Eclipse编译器可能错误地允许它不应该存在的东西.

有任何想法吗?

dfa*_*dfa 7

在BaseMatcher中,您需要指定类型参数:

public SubMatcher with(Matcher<?, ?> matcher) {
Run Code Online (Sandbox Code Playgroud)

为了让javac与你的with方法 相匹配

PS

imho是eclipse编译器的一个bug


Gre*_*ill 6

我把它通过添加成功构建<?,?>MatcherSubMatcher.with:

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

如果没有这个,方法签名就不同于基础.我想知道@Override检查中是否有一个错误没有注意到这一点.

  • 这是一个有趣的情况.你可能会认为javac在这里有问题,因为它允许@Override注释,但是它使用子类方法而不是覆盖方法.这是不一致的,注释是为了防止这种问题.问题是具有原始类型参数的方法是否可以覆盖与<?>具有相同类型的超类方法 (3认同)