为什么 Hamcrest `matches` 方法使用 Object 作为输入类型而不使用泛型类型作为输入

Why Hamcrest `matches` method uses Object as input type and does not use generic type as input

我是 Java 的新手,正在学习 Hamcrest 框架。

我看过Matcher接口的代码,我看不懂matches(Object actual)的注释和方法签名。我希望它是 matches(T actual),并使用通用类型 T 而不是接受所有内容的 Object

这是源代码: https://github.com/hamcrest/JavaHamcrest/blob/master/hamcrest/src/main/java/org/hamcrest/Matcher.java

对于 matches 方法:

public interface Matcher<T> extends SelfDescribing {

/**
     * Evaluates the matcher for argument <var>item</var>.
     *
     * This method matches against Object, instead of the generic type T. This is
     * because the caller of the Matcher does not know at runtime what the type is
     * (because of type erasure with Java generics). It is down to the implementations
     * to check the correct type.
     *
     * @param actual the object against which the matcher is evaluated.
     * @return <code>true</code> if <var>item</var> matches, otherwise <code>false</code>.
     *
     * @see BaseMatcher
     */
    boolean matches(Object actual);

看了方法上面的评论,说明这是故意的,我不明白为什么。我知道 java 中的 type erasure 是什么。但是我仍然不明白为什么 Hamcrest 的设计者认为将 Object 作为输入而不是声明为通用的接口的通用类型更好 public interface Matcher<T> extends SelfDescribing

你是对的,一开始你会期望 T 而不是 Object,但是你知道泛型是一个编译时特性并且在运行时不可用(当测试运行并需要匹配器)(请参阅类型擦除)强调这样一个事实是有意义的,即从技术上讲它可能不是 T,因此迫使您检查以在这种情况下创建更清晰的错误消息。

类型擦除(转述自Oracle):

类型擦除确保不会为不同的泛型生成额外的 类。它

  • 用边界或对象替换所有泛型类型。
  • 引入自动转换
  • 创建适配器方法以保留多态性。

这样就没有运行时开销。

问:

I don't understand why.

答:(来自 JavaDocs)

This is because the caller of the Matcher does not know at runtime what the type is (because of type erasure with Java generics). It is down to the implementations to check the correct type.

也来自 JavaDocs:

When using Hamcrest, there is no guarantee as to how often matches() or describeMismatch() will be called

您必须看一下 Hamcrest-Libs 实现。
因此,您的 matches() 实现被 Hamcrest 内部 调用(使用任何对象)。在运行时,Hamcrest 没有机会知道(并找到!)正确的 matches(...) 方法,因为泛型被清除了。您需要检查自己,如果对象(由 Hamcrest 传递)真的匹配。这和Hamcrest没有太大关系。

干杯!