如何在Java中使用泛型引用嵌套类型?

Slo*_*Oak 10 java generics

如何创建引用嵌套泛型类型的泛型类?

我正在尝试创建一个Comparator类,它可以比较B的内部类型,而不想暴露这些类型.在下面的例子中,我得到一个编译器警告,用于将我的T内部嵌套值转换为Comparable:

public class SSCCE {

    // Compare my A instances.
    class AComparator<T extends B> implements Comparator<T> {

        @Override
        public int compare(final T o1, final T o2) {
            return o1.getValue().compareTo(o2.getValue());
        }
    }


    class A extends B<Integer> {
        @Override Integer getValue() { return 1; }
    }

    class A2 extends B<String> {
        @Override String getValue() { return "Test String!"; }
    }

    abstract class B<T extends Comparable<T>> {
        abstract T getValue();
    }

    public static void main(String[] args) {
        SSCCE sscce = new SSCCE();
        AComparator<A> comparator = sscce.new AComparator<>();
        comparator.compare(sscce.new A(), sscce.new A());
    }
}
Run Code Online (Sandbox Code Playgroud)

是否可以使用安全允许铸造来表示内部值?

我试过的事情:

  • 创建可比较的通配符(不可编译):

    class AComparator2<T extends B<? extends Comparable<?>>> implements Comparator<T> {
    
        @Override
        public int compare(final T o1, final T o2) {
            Comparable<?> o1value = (Comparable) o1.getValue();
            Comparable<?> o2value = (Comparable) o2.getValue();
            return o1value.compareTo(o2value);
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 声明一个辅助通用参数类型(U),它只是推迟了问题:

    class AComparator3<T extends B<U>, U extends Comparable<U>> implements Comparator<T> {
    
        @Override
        public int compare(final T o1, final T o2) {
            U o1value = o1.getValue();
            U o2value = o2.getValue();
            return o1value.compareTo(o2value);
        }
    }
    ...
    AComparator3<A, Comparable<U>> comparator = sscce.new AComparator3();
    
    Run Code Online (Sandbox Code Playgroud)

这个比较器不是要比较A类的两个实例,而是它们内容的一部分.

Zho*_*gYu 7

通配符解决方案不起作用

    class AComparator2<T extends B<?>> {
        public int compare(T o1, T o2)
Run Code Online (Sandbox Code Playgroud)

因为T这里太松了; 我们不能确定两者T可以相互比较 - 它可能o1是a B<X1>o2a B<X2>,并且X1, X2是两种不同的类型.

您的第三个解决方案限制T为特定的B<U>

    class AComparator3<T extends B<U>, U extends Comparable<U>>
Run Code Online (Sandbox Code Playgroud)

这很完美; 除了使用网站必须指定U,即使U可以从中推断T.

    AComparator3<A, Integer>  
                    ^^^^^^^ duh!
Run Code Online (Sandbox Code Playgroud)

这很烦人.之前已经从其他用例中提出了同样的问题.没有好的答案.

幸运的是,在您的情况下,U在使用网站上的任何地方都不需要,因此我们可以简单地使用通配符

    AComparator3<A, ?> comparator = sscce.new AComparator3<>();
    comparator.compare(sscce.new A(), sscce.new A());
Run Code Online (Sandbox Code Playgroud)

事实上,比较器是一个Comparator<A>,这可能是你所需要的.我们也可以创建一种方便的方法来隐藏丑陋new.所以你可能会做类似的事情

    Comparator<A> comparator = sscce.comparator(); 
Run Code Online (Sandbox Code Playgroud)