有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java声明泛型

我在静态方法和字段中定义泛型时遇到问题

假设我有一个简单的接口,所有类都使用它,它包含一个名为valueT类型的字段:

public interface HasValue<T> {
    // Getter:
    public T value();
    // Setter:
    public void setValue(T value);
}

如果我有一个类型为N的对象数组,它实现了HasValue<T>,我可能需要对这个数组进行排序。一种经典的方法是使用value字段比较那些N对象:如果T实现了Comparable<T>接口,并且arg0arg1都是N类型,那么arg0.compareTo(arg1)将等于arg0.value().compareTo(arg1.value())

我们的目标是创建一个可用的、不耗时的、可能的简单方法来获得上述情况


每次我需要类似的东西时,都可以创建一个自定义Comparator<N>。这将迫使我每次都要写代码:肯定很耗时


我可以直接在接口中创建Comparator<N>。第一次尝试是创建一个方法:

  1. 它需要是一个默认方法。部分代码将测试类T是否实现了Comparable接口,为此,我需要一个T类的示例:使用this.value().getClass()是最快的方法。对于静态方法,我不能使用this
  2. 我需要说明N类实现了接口HasValue<T>,否则计算机不会知道

    public default <N extends HasValue<T>> Comparator<N> COMPARE_BY_VALUE() throws Exception{
        if(Comparable.class.isAssignableFrom(this.value().getClass()))
            return new Comparator<N>() {
                            public int compare(N arg0, N arg1) {
                                Comparable value0 = (Comparable) arg0.value(), 
                                    value1 = (Comparable) arg1.value();
                                return value0.compareTo(value1);
                            }
            };
        else throw new Exception("The class of the value does not implement the interface Comparable.\n");
    }
    
    • 这个策略有效。。。仅仅它很笨拙,涉及到rawtypes,每次都创建Comparator<N>

第二次尝试:创建静态字段

  • 策略是将测试问题与其他问题分开。默认方法将执行测试:如果成功,该方法将返回静态Comparator,否则返回异常

    public default <N extends HasValue<T>> Comparator<?> COMPARE_BY_VALUE() throws Exception{
        if(Comparable.class.isAssignableFrom(this.value().getClass()))
            return COMPARE_BY_VALUE;
        else throw new Exception("The class of the value does not implement the interface Comparable.\n");
    }
    public static Comparator<HasValue> COMPARE_BY_VALUE = new Comparator() {
                public int compare(Object arg0, Object arg1) {
                    Comparable value0 = (Comparable) ((HasValue)arg0).value(), 
                        value1 = (Comparable) ((HasValue)arg1).value();
                    return value0.compareTo(value1);
                }
            };
    
  • 在声明静态字段时,我(不幸地)不能声明类似public static <T, N extends HasValue<T>> Comparator<N> COMPARE_BY_VALUE的内容。这迫使我返回一个Comparator<HasValue>:不是我想要的

  • 使用通配符,我可以获得关闭的内容:

        public default <N extends HasValue<T>> Comparator<?> COMPARE_BY_VALUE() throws Exception{
            if(Confrontable.class.isAssignableFrom(this.value().getClass()))
                return COMPARE_BY_VALUE;
            else throw new Exception("The class of the value does not implement the interface Comparable.\n");
        }
        public static Comparator<? extends HasValue<? extends Comparable<?>>> COMPARE_BY_VALUE 
                = new Comparator() {
            public int compare(Object arg0, Object arg1) {
                Comparable value0 = (Confrontable) ((HasValue<?>)arg0).value(), value1 = (Confrontable) ((HasValue<?>)arg1).value();
                return value0.compareTo(value1);
            }
        };
    
  • 这种修改(理论上)将返回一个Comparator<N>,其中N扩展HasValue<T>T扩展Comparable<U>,而U实际上是T

    • 因为JVM将{}中的每一个{}解释为一个潜在的新类:三个{}意味着三个新类({}、{}和{}),而{}恰好实现了{},因此{}和{}是一个相同的类
  • 我仍然有大量的原始类型
  • 。。。但至少我每个NT只有一个{}

现在,虽然最后一个策略似乎有效,但我想知道是否有更好的方法来实现我的目标
我最初的想法是说

     public static <T extends Comparable<T>, N extends HasValue<T>> Comparator<N> COMPARE_BY_VALUE = new Comparator() {
                public int compare(N arg0, N arg1) {
                    return arg0.value().compareTo(arg1.value());
                }
        };

并获得一个不带通配符的Comparator<N>。但是,这会发送所有类型的错误。有人有主意吗


共 (1) 个答案

  1. # 1 楼答案

    只要做:

    static <T extends Comparable<T>> Comparator<HasValue<T>> createValueComparator() {
        return new Comparator<HasValue<T>>() {
            @Override
            public int compare(HasValue<T> o1, HasValue<T> o2) {
                return o1.value().compareTo(o2.value());
            }
        };
    }
    

    这意味着:对于实现Comparable的每个类型T,此方法返回可以比较HasValue<T>的comparator

    Java可能无法正确推断这种复杂结构中的类型。您可能必须显式添加类型:

    Collections.sort(list, Main.<Integer> createValueComparator());
    

    或:

    Comparator<HasValue<Integer>> comparator = createValueComparator();
    Collections.sort(list, comparator);
    

    请记住,许多程序员过度使用泛型。通常有一种更简单的方法来实现相同的功能,同时仍然保持类型安全性