How to use generics in Java to reference nested types?

How do I create generic classes that reference nested generic types?

I'm trying to create a comparator class that can compare the internal types of B without exposing them In the following example, I get a compiler warning to pass my t embedded value to 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());
    }
}

Can I use internal values to safely allow projection?

What I've tried

>Create comparable wildcards (not compileable):

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);
    }
}

>Declaring an auxiliary generic parameter type (U) simply delays the problem:

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();

The comparator is not comparing two instances of class A, but part of their content

Solution

Wildcard solution does not work

class AComparator2<T extends B<?>> {
        public int compare(T o1,T o2)

Because t is too loose here, we can't be sure that the two t can be compared with each other - maybe O1 is B < X1 > and O2 is B, X2, x1, X2 are two different types

Your third solution limits t to a specific B < U >

class AComparator3<T extends B<U>,U extends Comparable<U>>

This works perfectly except that using the website must specify u, even if u can be derived from t

AComparator3<A,Integer>  
                    ^^^^^^^ duh!

It's annoying to have the same problem before other use cases There is no good answer

Fortunately, in your case, u does not need to be used anywhere on the website, so we can simply use wildcards

AComparator3<A,?> comparator = sscce.new AComparator3<>();
    comparator.compare(sscce.new A(),sscce.new A());

In fact, the comparator is comparator < a >, which may be what you need In addition, we can create a convenient way to hide the new ugliness So you can do something similar

Comparator<A> comparator = sscce.comparator();
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>