为什么<t> Matcher <t>作为Hamcrest instanceOf方法中的返回类型</t> </t>

时间:2015-01-21 21:43:42

标签: java generics hamcrest

我无法理解&#39; instanceOf&#39;的方法签名。 hamcrest包中的方法。这是方法

public static <T> Matcher<T> instanceOf(Class<?> type) {
    return (Matcher<T>) new IsInstanceOf(type);
}

我可以理解返回类型是Matcher <T>,第一个<T>声明泛型。但是T永远不会在方法中推断出来。请注意,我们不会将T作为参数类型传递。

出现了一个问题:它是否意味着T是无界的,我们可以动态地将Matcher返回到任何类型?

2 个答案:

答案 0 :(得分:1)

Matcher返回的instanceOf类型实际上没有用,直到你实际......好吧,使用它。

是的,您可以将结果Matcher分配给任何类型。

例如,您可以这样做:

// <T> is inferred to be 'Object' here
Matcher<Object> objectMatcher = instanceOf(Integer.class); 

或者

// <T> is inferred to be 'Integer' here
Matcher<Integer> integerMatcher = instanceOf(Integer.class);

并尝试以Matcher方式使用assertThat

// succeeds and expectedly so
// Integer.class.isInstance(5) is true
assertThat(5, objectMatcher);

// succeeds and expectedly so 
// Integer.class.isInstance(5) is true
assertThat(5, integerMatcher);

// fails, but only after asserting, by throwing an AssertionError at runtime
// Integer.class.isInstance(Double) is false; 
// but we wouldn't have gotten this far had we used the right matcher
assertThat(5.5d, objectMatcher);

 // fails at compile time; exactly what we want generics to offer us - compile time safety
assertThat(5.5d, integerMatcher);

// you can also do it this way 
// if you wanted to force T instead of 
// expecting the compiler to infer it for you based on the context
assertThat(5, IsInstanceOf.<Integer>instanceOf(Integer.class));

将这些调用与assertThat的签名进行比较,以了解T(与T使用的instanceOf不同的? super Tpublic static <T> void assertThat(T actual, Matcher<? super T> matcher) // actual would be Integer and matcher would be Matcher<Object> assertThat(5, objectMatcher); // actual would be Integer and matcher would be Matcher<Integer> assertThat(5, integerMatcher); // actual would be Double and matcher would be Matcher<Object> assertThat(5.5d, objectMatcher); // actual would be Double and matcher would be Matcher<Integer>; see the mismatch? assertThat(5.5d, integerMatcher); 在每种情况下:

{{1}}

答案 1 :(得分:0)

我认为这个问题的答案很简单。由于类型参数T未在instanceOf方法的任何参数中使用,因此允许编译器推断任何类型以用作该方法的类型参数呼叫。因此,编译器总是可以推断出&#34;工作的类型&#34;在方法调用的上下文中(简单来说)。

这一切只意味着像

这样的一行
assertThat(something, instanceOf(Some.class));

将始终键入check,无论something的静态类型如何,因为编译器会将T推断为something的静态类型,assertThat以及instanceOf电话。

这是一件好事,因为该行的重点是检查something动态类型,这是静态不知道的。如果something的确切类型是静态知道的,那么这个断言甚至是不必要的。