指定方法参数的泛型类型

时间:2016-02-17 12:43:57

标签: java generics

扩展我的部门私有Libary我试图实现一个isBetween方法。此方法是通用的,并且期望Comparable类型T表示其最小值,最大值以及varargs值。其目的是检查所有值是否在指定范围内。

 public static void main(String[] args) {
    System.out.print(isBetween(1, 100, 200, 100, 1, 2));
  }


  @SafeVarargs
  public static <T extends Comparable> boolean isBetween(T minimum, T maximum, T... values) {
    for (T value : values) {
      if (!(value.compareTo(minimum) >= 0 && value.compareTo(maximum) <= 0))
        return false;
    }
    return true;
  }

这很好用。但是类型T可以包含任何Comparable对象。方法调用:

System.out.print(isBetween(1, 100, 200, 100, "How awkward", 2));

也将在编译时被接受。 这根本不是类型安全的,不能被接受。

我想到了两个解决方案:

1。按以下方式调用方法

System.out.print(Class.<Integer>isBetween(1, 100, 200, 100, 1, 2));

2。制作U类型的方法参数之一,并将类型T扩展为键入U

两种“解决方案”似乎都不是很优雅。第一个需要在调用方法之前编写其他代码,而第二个代码似乎是一个黑客。

有没有更优雅的方法来解决我的问题?

4 个答案:

答案 0 :(得分:3)

嗯,这可以通过avoiding raw types轻松解决。

让我们来看看你的代码:

public static <T extends Comparable> boolean isBetween(T minimum, T maximum, T... values) {
    // ...
}

T是一个很好的通用,但Comparable是原始类型。您需要Comparable<T>,因此您的方法应如下所示:

public static <T extends Comparable<T>> boolean isBetween(T minimum, T maximum, T... values) {
    // ...
}

然后isBetween(1, 100, 200, 100, "How awkward", 2)将不再可能。

isBetween方法允许“相等”参数类型,如果它们具有实现Comparable的相等超类。

例如,使用java.util.Datejava.sql.Date(用户fge有这个好主意):

isBetween(new java.util.Date(1L), new java.util.Date(4L), new java.sql.Date(5L))

这将导致“false”,因为第三个参数比上限更“大”。并且java.sql.Date被接受,因为它扩展了java.util.Date并将T推断为“实现Comparable的公共父类”。

答案 1 :(得分:1)

将其设为<T extends Comparable<T>>

@SafeVarargs
public static <T extends Comparable<T>> boolean isBetween(T minimum, T maximum, T... values) {
    for (T value : values) {
        if (!(value.compareTo(minimum) >= 0 && value.compareTo(maximum) <= 0))
            return false;
    }
    return true;
}

这将在编译时失败。

答案 2 :(得分:1)

另一种方法是传递Comparator,而不是要求TComparable

public static <T> boolean isBetween(Comparator<? super T> comparator, 
        T minimum, T maximum, T... values) {
    for (T value : values) {
        if (!(comparator.compare(value, minimum) >= 0 && 
                comparator.compare(value, maximum) <= 0)){
            return false;
        }
    }
    return true;
}

这允许您根据需要比较对象,并且它们不需要是Comparable

您还可以提供与其他答案类似的方法,以便在ComparatorT时跳过写Comparable

public static <T extends Comparable<? super T>> boolean isBetween(T minimum, 
        T maximum, T... values) {
    return isBetween(T::compareTo, minimum, maximum, values);
}

答案 3 :(得分:0)

使用Comparable&lt; T>而不是原始的可比较。这样,您将确保T类型的所有实例都具有相同的类型,并且在编译时将失败。