gpt4 book ai didi

junit - 测试 Java 6 和 Java 8 中的类型匹配差异

转载 作者:行者123 更新时间:2023-12-01 20:02:43 25 4
gpt4 key购买 nike

我将应用程序 JDK 从 1.6 更新到 1.8,但在 IntelliJ 中保留了语言级别 1.6。

更新后,在检查对象类型的 assertThat 语句中的一些测试中,我遇到了编译错误。代码是这样的:

assertThat((Class) myList.get(0).getMyClassType(), is(equalTo(MySubclass.class)));

myList 看起来像这样:

  List<MyClassDefinition> myList = myClassDefinition.getMyClassDefinitions(reader);

MyClassDefinition 和 getMyClassType() 的定义如下:

public class MyClassDefinition {
private Class<? extends MyClass> classType;

public Class<? extends MyClass> getMyClassType() {
return classType;
}
}

MySubclass 是 Myclass 的子类:

  public class MySubclass extends MyClass {
@Override
public void initialise() {
// some action here!
}
}

MyClass的定义是

public abstract class MyClass extends AnotherClass<AnotherType>{
//Definitions
}

Assert is and equals 库的导入是这样的:

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

hamcrest 版本是 hamcrest-all-1-3

将项目 SDK 更改为 jdk 1.8 后,我收到此错误消息:

Error:(136, 9) java: no suitable method found for assertThat(java.lang.Class,org.hamcrest.Matcher<java.lang.Class<MySubClass>>)
method org.hamcrest.MatcherAssert.assertThat(java.lang.String,boolean) is not applicable
(argument mismatch; java.lang.Class cannot be converted to java.lang.String)
method org.hamcrest.MatcherAssert.<T>assertThat(java.lang.String,T,org.hamcrest.Matcher<? super T>) is not applicable
(cannot infer type-variable(s) T
(actual and formal argument lists differ in length))
method org.hamcrest.MatcherAssert.<T>assertThat(T,org.hamcrest.Matcher<? super T>) is not applicable
(cannot infer type-variable(s) T
(argument mismatch; org.hamcrest.Matcher<java.lang.Class<MySubClass>> cannot be converted to org.hamcrest.Matcher<? super java.lang.Class>))

应用程序是使用Ant构建的,并且我们已将hamcrest jar文件添加到类文件中,因此当我们更改项目中的JDK时不会发生任何变化。所以我的问题是,为什么当我使用相同级别的语言(1.6)进行编译时,这段代码可以在 JDK 1.6 上运行,但不能在 1.8 上运行?它是否依赖于不同的库?

最佳答案

显然,您遇到了泛型类型签名问题,您可以通过将类型转换插入到原始类型 Class 来解决该问题。 ,这会导致编译器将整个语句视为仅使用原始类型未检查操作。

从编译器消息中可以看到,org.hamcrest.Matcher<java.lang.Class<MySubClass>> cannot be converted to org.hamcrest.Matcher<? super java.lang.Class> ,它现在执行了通用类型检查,但(正确地)失败了,但恕我直言,它不应该根据 Java 6 语言规则执行该类型检查。问题源于 JDK8 不包含原始 Java 6 编译器,而是让新编译器尝试使用旧规则进行编译,这可能不那么精确。

但无论该行为是否正确,我都不希望对其进行修复,因为模拟旧的 Java 6 语言规则并不是一个高优先级。

请注意,使用源级别 1.8 时,即使没有原始类型 转换,代码编译也不会出现问题。最初的问题源于 CoreMatchers.equalTo(…) 的限制性签名。独立表达式 equalTo(InstanceOfFoo)返回 Matcher<Foo> ,它被传递到 assertThat允许仅测试 Foo 的实例(使用 isA(Foo.class) 时情况更糟,它也只能测试 Foo 的实例,这使得测试毫无意义)。

使用 Java 8,可以进行目标类型推断,例如
Matcher<Object> m = equalTo(InstanceOfFoo); ,这将推断 Object对于 <T>并通过,如 InstanceOfFoo也可分配给 Object 。这也可以与化合物 assertThat 一起使用。陈述您的问题,推断合适的类型。

这引导我们找到适用于所有语言级别的通用解决方案。只需使用

assertThat(myList.get(0).getMyClassType(), is(equalTo((Object)MySubclass.class)));

Class<MySubclass>当然,可以分配给 Object这使得强制转换成为无操作。但随后,得到 Matcher<Object> ,您可以检查您喜欢的每个对象,包括 myList.get(0).getMyClassType() 的结果,当然也可以分配给 Object 。与您原来的解决方法不同,这不承担任何原始类型使用或未经检查操作。

您还可以使用显式类型而不是强制转换,CoreMatchers.<Object>equalTo(MySubclass.class) ,但这消除了 import static 的好处.

顺便说一下,匹配Class时对象,您可以使用 sameInstance而不是equalTo .

关于junit - 测试 Java 6 和 Java 8 中的类型匹配差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48581763/

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