小编典典

Java泛型什么时候需要而不是切换有什么缺点吗?

all

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

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

这不与以下的 JUnitassertThat方法签名一起编译:

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. assertThatJUnit中方法的泛化有什么意义吗?该类Matcher似乎不需要它,因为 JUnit 调用了 match 方法,该方法没有使用任何泛型进行类型化,并且看起来像是在尝试强制不做任何事情的类型安全,因为Matcher实际上不会匹配,无论如何测试都会失败。不涉及不安全的操作(或者看起来如此)。

作为参考,这里是 JUnit 的实现assertThat

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());
    }
}

阅读 63

收藏
2022-05-31

共1个答案

小编典典

首先 -
我必须引导您访问http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
- 她做得非常出色。

基本思想是你使用

<T extends SomeClass>

当实际参数可以是SomeClass它的任何子类型时。

在你的例子中,

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

您是说expected可以包含代表任何实现的类的 Class 对象Serializable。你的结果图说它只能保存Date类对象。

当您传递结果时,您将设置为T完全Map的类对象,这与任何.String``Date``Map``String``Serializable

要检查的一件事 -
你确定你想要Class<Date>而不是DateStringto的映射Class<Date>通常听起来不是很有用(它只能Date.class作为值而不是
的实例Date

至于泛化assertThat,想法是方法可以确保Matcher传入适合结果类型的a。

2022-05-31