gpt4 book ai didi

java - Java泛型什么时候需要<?扩展 T> 而不是 ,切换有什么缺点吗?

转载 作者:太空宇宙 更新时间:2023-11-04 14:27:58 25 4
gpt4 key购买 nike

给出以下示例(使用 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. assertThat进行泛化有什么意义吗? JUnit 中的方法? Matcher class 似乎不需要它,因为 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 ——她做得非常出色。

基本思想是你使用

<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 的类的 Class 对象。你的结果图说它只能容纳 Date类对象。

当您传递结果时,您正在设置 T正好MapStringDate类对象,与 Map 不匹配的String任何 Serializable .

需要检查一件事 - 您确定要 Class<Date>而不是DateString的 map 至Class<Date>一般来说,听起来不太有用(它所能保存的只是 Date.class 作为值而不是 Date 的实例)

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

关于java - Java泛型什么时候需要<?扩展 T> 而不是 <T> ,切换有什么缺点吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26463281/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com