给定以下示例(将JUnit与Hamcrest匹配器一起使用):

Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));  

这不会使用JUnit assertThat方法签名编译:

public static <T> void assertThat(T actual, Matcher<T> matcher)

编译器错误消息为:

Error:Error:line (102)cannot find symbol method
assertThat(java.util.Map<java.lang.String,java.lang.Class<java.util.Date>>,
org.hamcrest.Matcher<java.util.Map<java.lang.String,java.lang.Class
    <? extends java.io.Serializable>>>)

但是,如果我将assertThat方法签名更改为:

public static <T> void assertThat(T result, Matcher<? extends T> matcher)

然后编辑工作开始了.

所以有三个问题:

  1. 为什么当前版本不能编译?虽然我模糊地理解了这里的协方差问题,但如果不得不解释的话,我当然无法解释.
  2. assertThat法改成Matcher<? extends T>法有什么坏处吗?如果你那样做,还有其他案子会破裂吗?
  3. 在JUnit中泛化assertThat方法有什么意义吗?Matcher类似乎不需要它,因为JUnit调用matches方法,该方法没有任何泛型类型,看起来只是试图强制执行类型安全性,而该安全性不起任何作用,因为Matcher实际上不会匹配,而且测试无论如何都会失败.没有涉及不安全的操作(或者看起来是这样).

以下是assertThat的JUnit实现供参考:

public static <T> void assertThat(T actual, Matcher<T> matcher) {
    assertThat("", actual, matcher);
}

public static <T> void assertThat(String reason, T actual, Matcher<T> matcher) {
    if (!matcher.matches(actual)) {
        Description description = new StringDescription();
        description.appendText(reason);
        description.appendText("\nExpected: ");
        matcher.describeTo(description);
        description
            .appendText("\n     got: ")
            .appendValue(actual)
            .appendText("\n");

        throw new java.lang.AssertionError(description.toString());
    }
}

推荐答案

首先,我得告诉你http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html号,她做得很好.

基本的 idea 是,您可以使用

<T extends SomeClass>

当实际参数可以是SomeClass或其任何子类型时.

在你的例子中,

Map<String, Class<? extends Serializable>> expected = null;
Map<String, Class<java.util.Date>> result = null;
assertThat(result, is(expected));

您的意思是expected可以包含表示实现Serializable的任何类的类对象.结果图显示它只能容纳Date个类对象.

当您传入结果时,您将T设置为StringDate个类对象中的恰好Map个,这与String中的Map个对象和Serializable个对象中的任何值都不匹配.

有一件事需要判断——你确定你想要Class<Date>而不是Date吗?StringClass<Date>的映射在总体上听上go 并不是非常有用(它所能容纳的只是Date.class作为值,而不是Date的实例)

至于泛化assertThat,其 idea 是该方法可以确保传入适合结果类型的Matcher.

Java相关问答推荐

Java字符串常数池困惑

JsonPath在多个线程中返回错误的值

最小拓Flutter 排序的时间复杂度是多少?

Spring Batch 5-不要让它在数据库中自动创建表

DTO到实体,反之亦然,控制器和服务之间的哪一层应该处理转换?

如何确定springboot在将json字段转换为Dto时如何处理它?

Java LocalTime.parse在本地PC上的Spring Boot中工作,但在Docker容器中不工作

JavaFX如何在MeshView中修复多个立方体?

如何使用带有谓词参数的方法,而不使用lambda表达式

把一条整型短裤和两条短裤装成一条长的

Spring Security不允许加载js

对字符串长度进行排序,但颠倒了顺序(最长字符串在前)

EXCEL中的公式单元格显示#NAME?

在JDK Flight Recorder中只记录单个线程

有没有办法知道在合并中执行了什么操作?

将基于实例编号的对象列表拆分为新的对象列表

在数组中查找素数时出现逻辑错误

当我try 返回可选时,Mock无法正常工作

@此处不能应用可为null的批注

在java中使用SevenZip.openArchive方法后无法删除文件