ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java泛型和通配符:如何使此代码编译?

2019-10-23 21:12:36  阅读:243  来源: 互联网

标签:compiler-errors generics hamcrest java wildcard


我正在使用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&lt ;?的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是您发布的原始代码的完全修改版本,可以为我成功编译.

相关文章

点击查看更多相关文章

转载注明原文:Java泛型和通配符:如何使此代码编译? - 代码日志

解决方法:

is(T)匹配器返回签名为Matcher&lt ;?的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是您发布的原始代码的完全修改版本,可以为我成功编译.

标签:compiler-errors,generics,hamcrest,java,wildcard
来源: https://codeday.me/bug/20191023/1915748.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有