给定以下示例(将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)
然后编译工作。
所以三个问题:
assertThat
方法更改为有什么缺点Matcher<? extends T>
吗?如果这样做,还有其他情况会中断吗?assertThat
在JUnit
中通用化方法有什么意义吗?该Matcher
级似乎并不需要它,因为JUnit的调用matches
方法,它不与任何通用的,只是看起来像键入企图迫使一个类型安全这并不做任何事情,因为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());
}
}
首先-我必须将你定向到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
至于泛化assertThat,其想法是该方法可以确保Matcher传入适合结果类型的a 。
问题内容: 我收到一个错误,程序中有这个结构 错误指向Circle扩展Shapes < T >类,其中指出“ T无法解析为类型”。如果将T设置为字符串,错误将消失,但这也意味着我只能使用一种数据类型。我应该在<>中放入什么,以便可以使用任何数据类型(字符串,整数,双精度型等),或者这样做是错误的? 问题答案: 有两个不同的概念。当你写 这意味着您正在创建一个类,该类在实例化时将被某个类参数化。您不
问题内容: 我想知道Java中是否有特殊原因总是使用“ ”而不是“ ”来定义类型参数的界限。 例: 被禁止但是 是正确的。是什么原因呢? 问题答案: 在类“实现”还是“扩展”之间,通用约束语言没有语义差异。约束可能性是“扩展”和“超级”-也就是说,该类是可分配给其他类的对象(扩展),还是该类可从该类分配(超级)。
问题内容: 您如何进行这项工作: 不做 编辑 为什么这不起作用? 我正在将编译器消息标记为错误。 问题答案: Reimeus已经指出,您在编辑中要求的内容是不可能的。我只想扩展一下原因。 人们会认为您可以使用以下内容: 实际上,这就是我第一次看到这篇文章时想到的。但这实际上会导致编译器错误: 类型变量不能跟其他界限 为了帮助我解释原因,我想引用Victor Rudometov在OracleBlog
问题内容: 我使用 browserify 和 watchify ,并希望不是默认的扩展名的其他文件,并没有指定扩展名,比如: 我已经尝试按照 browserify 文档中的指定进行操作: 但是我看不到任何变化。这可能吗?正确的方法是什么? 问题答案: 编辑 (2015年4月27日):我刚刚注意到在问题中,我有一个无效的参数,例如: 应该是(请注意中的(点)): 原始答案 : 添加的选项,这样做是为
我使用的浏览器和Watchify,并希望文件以外的默认扩展名和没有指定的扩展名,例如: 我已经尝试了,如浏览器留档中指定的: 然而,我没有看到任何变化。这有可能吗?做这件事的正确方法是什么?
问题内容: 我正在尝试重构M类型确实扩展了任何内容的类和子类集,即使我们知道它必须是某种类型的子类也是如此。该类型已参数化,我希望其参数化类型可用于已经具有M值的子类。 有什么方法可以定义此类,而不必在参数列表中包括冗余的K和V泛型类型。我希望能够使编译器从子类映射到的M中推断出它们。 换句话说,我希望类声明看起来像这样: 从M的定义可以推断出K和V的类型。 问题答案: 问题在于,它们并没有真正地