【问题标题】:Why Hamcrest `matches` method uses Object as input type and does not use generic type as input为什么 Hamcrest `matches` 方法使用 Object 作为输入类型而不使用泛型类型作为输入
【发布时间】:2020-02-12 09:11:28
【问题描述】:

我是 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中的类型擦除是什么。但是我仍然不明白为什么 Hamcrest 的设计者认为将 Object 作为输入而不是声明为通用的接口的通用类型更好 public interface Matcher&lt;T&gt; extends SelfDescribing

【问题讨论】:

    标签: java generics matcher hamcrest


    【解决方案1】:

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

    类型擦除(转述自 Oracle):

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

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

    这样就不会产生运行时开销。

    【讨论】:

    • 是的,但是这样,如果我创建例如 类型的自定义匹配器,编译器不会警告我,并且我使用 Number 的输入调用 match 方法。
    • @EliyahuMachluf 我既不是 hamcrest 的开发者也不是贡献者,只能猜测其中的原因。唯一有效的来源是 hamcrest 团队的成员。您可能想通过them 提出您的问题。
    • 好的。谢谢,我会考虑在 Hamcrest 论坛上发布这个问题。
    【解决方案2】:

    问:

    我不明白为什么。

    答:(来自 JavaDocs)

    这是因为 Matcher 的调用者在运行时不知道类型是什么(因为 Java 泛型的类型擦除)。这取决于实施 检查正确的类型。

    同样来自 JavaDocs:

    使用 Hamcrest 时,无法保证调用 matches()describeMismatch() 的频率

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

    干杯!

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2015-05-14
      • 1970-01-01
      • 1970-01-01
      • 2013-02-26
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 2021-12-06
      相关资源
      最近更新 更多