【问题标题】:Generics Hell - How do I pass a joda.DateTime to Hamcrest Matcher.greaterThan?泛型地狱 - 我如何将 joda.DateTime 传递给 Hamcrest Matcher.greaterThan?
【发布时间】:2011-11-01 17:13:19
【问题描述】:

JodaTime 有

public final class DateTime extends BaseDateTime {...}

一直到

public interface ReadableInstant extends Comparable<ReadableInstant>

汉克雷斯特有

public static <T extends java.lang.Comparable<T>> org.hamcrest.Matcher<? super T>
    greaterThan(T value) {...}

如果我尝试

greaterThan(new DateTime());

然后我得到一个编译错误(Eclipse 提供了大部分线索)

Matchers 类型的泛型方法 GreaterThan(T) 不适用 对于参数(日期时间)。推断的类型 DateTime 不是有效的替代品 对于有界参数 >

我是否认为greaterThan 的签名实际上应该是

public static <T extends java.lang.Comparable<? super T>> org.hamcrest.Matcher<? super T>     
    greaterThan(T value)

?除了投射到原始Comparable 之外,有没有办法将这些组合在一起?

【问题讨论】:

标签: java generics jodatime hamcrest


【解决方案1】:

是的,在我看来这将是一个更好的签名。

您是否尝试过明确指定比较类型?

Matchers.<ReadableInstant>greaterThan(new DateTime());

不幸的是,我不相信您可以使用静态导入并指定类型参数来调用它 - 但这可能不会太困难。

当然,另一种方法是强制转换参数:

greaterThan((ReadableInstant) new DateTime());

我手边没有 Hamcrest,但在测试类型中使用您给我的签名,上述方法对我来说效果很好。

【讨论】:

  • 我不知道您可以“强制转换”该方法 - 这开启了 Java 语法的全新世界!
  • @Duncan 你没有强制转换方法。您指定方法类型参数,因此编译器不必从参数类型推断它。
  • 其实是Matchers,不是Matcher:(Matchers.greaterThan(DateTime.now())
【解决方案2】:

如果你经常使用它并且被转换困扰,你也可以像这样实现自己的Matcher:

public static Matcher<AbstractPartial> isAfter(final AbstractPartial partial) {
    return new BaseMatcher<AbstractPartial>(){

        @Override
        public void describeTo(final Description description) {
            description.appendText("after partial: ").appendValue(partial);
        }

        @Override
        public boolean matches(final Object object) {
            if (object instanceof AbstractPartial) {
                return ((LocalDate) object).isAfter(partial);
            }
            return false;
        }
    };
}

并像这样测试它:

    Set<LocalDate> dates = Sets.newHashSet(new LocalDate(2013, 1, 1), new LocalDate(2013, 1, 2), new LocalDate(
        2013, 1, 3));
    assertThat(
        CollectionUtils.isEqualCollection(filter(isAfter(new LocalDate(2013, 1, 1)), dates),
            Lists.newArrayList(new LocalDate(2013, 1, 2), new LocalDate(2013, 1, 3))), is(true));

如果您想使用 DateTime 而不是 LocalDate,只需在第一个清单中将 AbstractPartial 替换为 AbstractInstant。

【讨论】:

    猜你喜欢
    • 2019-01-21
    • 1970-01-01
    • 2013-06-07
    • 2011-10-26
    • 2013-08-21
    • 1970-01-01
    • 2016-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多