我正在使用Hamcrest 1.2库编写一些匹配器,但Java通配符却很难.当我尝试编译以下代码时
public class GenericsTest {
public void doesNotCompile() {
Container<String> container = new Container<String>();
// this is the desired assertion syntax
assertThat(container, hasSomethingWhich(is("foo")));
}
// these two are a custom made class and matcher; they can be changed
public static class Container<T> {
public boolean hasSomethingMatching(Matcher<T> matcher) {
T something = null; // here is some application logic
return matcher.matches(something);
}
}
public static <T> Matcher<Container<T>> hasSomethingWhich(final Matcher<T> matcher) {
return new TypeSafeMatcher<Container<T>>() {
@Override
protected boolean matchesSafely(Container<T> container) {
return container.hasSomethingMatching(matcher);
}
};
}
// the following signatures are from the Hamcrest 1.2 library; they cannot be changed
public static <T> void assertThat(T actual, Matcher<? super T> matcher) {
}
public static <T> Matcher<? super T> is(T value) {
return null;
}
public interface Matcher<T> {
boolean matches(Object item);
}
public static abstract class TypeSafeMatcher<T> implements Matcher<T> {
@SuppressWarnings({"unchecked"})
@Override
public final boolean matches(Object item) {
return matchesSafely((T) item);
}
protected abstract boolean matchesSafely(T item);
}
}
它产生编译错误
$javac GenericsTest.java
GenericsTest.java:7: <T>assertThat(T,GenericsTest.Matcher<? super T>) in GenericsTest cannot be applied to (GenericsTest
.Container<java.lang.String>,GenericsTest.Matcher<GenericsTest.Container<capture#928 of ? super java.lang.String>>)
assertThat(container, hasSomethingWhich(is("foo")));
^
1 error
如何修改代码使其可以编译?我尝试过不同的组合吗?超级和?扩展了Container类和hasSomethingWhich方法的签名,但无法使其进行编译(不使用显式方法类型参数,但是会产生难看的代码:GenericsTest. is(T)匹配器返回签名为Matcher< ;?的Matcher.超级T. 因此,如果您对行assertThat(container,hasSomethingWhich(is(“ foo”)))进行解构,您真正拥有的是: 第二行出现编译错误,因为hasSomethingWhich方法的签名需要Matcher< T>参数.为了匹配hamcrest的is(T)的返回类型,您的签名应该是: (区别在于将参数从Matcher< T>更改为Matcher< super T>. 然后,这将迫使您将hasSomethingWhich()的签名更改为也接受Matcher<?.超级T像这样:
Here是您发布的原始代码的完全修改版本,可以为我成功编译. 相关文章 转载注明原文:Java泛型和通配符:如何使此代码编译? - 代码日志Matcher<? super String> matcher = is("foo");
assertThat(container, hasSomethingWhich(matcher));
public static <T> Matcher<Container<T>> hasSomethingWhich(final Matcher<? super T> matcher)
public boolean hasSomethingMatching(Matcher<? super T> matcher)
点击查看更多相关文章
解决方法:
is(T)匹配器返回签名为Matcher< ;?的Matcher.超级T.
因此,如果您对行assertThat(container,hasSomethingWhich(is(“ foo”)))进行解构,您真正拥有的是:
Matcher<? super String> matcher = is("foo");
assertThat(container, hasSomethingWhich(matcher));
第二行出现编译错误,因为hasSomethingWhich方法的签名需要Matcher< T>参数.为了匹配hamcrest的is(T)的返回类型,您的签名应该是:
public static <T> Matcher<Container<T>> hasSomethingWhich(final Matcher<? super T> matcher)
(区别在于将参数从Matcher< T>更改为Matcher< super T>.
然后,这将迫使您将hasSomethingWhich()的签名更改为也接受Matcher<?.超级T像这样:
public boolean hasSomethingMatching(Matcher<? super T> matcher)
Here是您发布的原始代码的完全修改版本,可以为我成功编译.