3

I have defined 4 comparators for my object like this:

public static Comparator<mObject> comp0 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

public static Comparator<mObject> comp1 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

public static Comparator<mObject> comp2 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

public static Comparator<mObject> comp4 = new Comparator<mObject>() {

        @Override
        public int compare(mObject l, mObject r) {
            ...compare
        }
    };

Now i want to create an array with the 4 comparators ,like this :

public final static Comparator<mObject>[] Object_comparators = { comp0,
        comp1,
        comp2,
        comp3};

but Eclipse underlines everything between {..} like it is an error .Why is it ,and how could i fix it ?

一二三
  • 20,127
  • 11
  • 58
  • 72
Nikoi
  • 389
  • 2
  • 14

2 Answers2

9

You cannot create an array of classes with a parameterized generic type.

If you don't mind losing type safety, you can do this:

Comparator[] list = new Comparator[4];

But my preferred strategy would be to use a List:

List<Comparator<mObject>> list = Arrays.asList(comp0, comp1, comp2, comp3);
Mark Elliot
  • 68,728
  • 18
  • 135
  • 157
2

As Mark Elliot said you can't use generics type in arrays. This is because of type erasure, while arrays have their type known at runtime. Because of type erasure, the generic type is never known at runtime. This means the generics are just useful at compilation time, and that by some tricks, you can insert Animal objects into a List<Comparator>

Btw you can't declare the creation of an anonymous array without specifying the type of the array, since there is no type erasure for the array type.

Thus it is not allowed to create an array using generic types and could lead to some unexpected behaviors.

Think about it: if you create an array of car (Car[]) then you can cast it to Object[]. That does not mean you can put objects in that array, since the type of the array is still known at runtime. You will get an ArrayStoreException if you try to put a dog on that array.


Now what if we created an array Car<Ferrari>[]? You can still cast it to Object[]. It works like the Car[] array except in this case, when you have casted it into an Object[], you WILL be able to put objects of type Car<Renault> at runtime, since the generic type is not known!


I think Java prevents us from such behaviors.

But you can still use a array of generics reference!!!

public static void main(String[] args) {

    Comparator<String> NORMAL = new Comparator<String>() {
        @Override
        public int compare(String s, String s1) {
            return s.compareTo(s1);
        }
    };

    Comparator<String> REVERSE = new Comparator<String>() {
        @Override
        public int compare(String s, String s1) {
            return - s.compareTo(s1);
        }
    };

    Comparator<String>[] comparators = new Comparator[] {NORMAL,REVERSE};

    List<String> strings = Arrays.asList("f","d","c","a","e","b");

    TreeSet<String> normalSet = new TreeSet<String>(comparators[0]);
    normalSet.addAll(strings);
    for ( String s : normalSet ) {
        System.out.println("normal : " + s);
    }

    TreeSet<String> reverseSet = new TreeSet<String>(comparators[1]);
    reverseSet.addAll(strings);
    for ( String s : reverseSet ) {
        System.out.println("reverse : " + s);
    }

}

Produces the output:

normal : a
normal : b
normal : c
normal : d
normal : e
normal : f

reverse : f
reverse : e
reverse : d
reverse : c
reverse : b
reverse : a

So you CAN use arrays with generics, but Java seems to prevent you from doing such a thing.

I guess it's because initially the array contract may be something like this:

If you create an array of type X, you will NEVER EVER be able to put anything in it that IS-NOT-AN X. If you try, you'll get an ArrayStoreException

Thus allowing arrays with generics creation would lead to a different rule like:

If you create an array of type X<Y>, you will NEVER EVER be able to put anything that IS-NOT-AN X. If you try, you'll get an ArrayStoreException. But you CAN add both X<Y> and X<Z> objects!


As my previous code shows it, we CAN'T create arrays with generics, but we can create arrays without generics, and use it as an array with generics.

Comparator<String>[] comparators = new Comparator[] {NORMAL,REVERSE};

I guess it's somehow a way for Java to tell us "if you know what you'r doing, then ok you can do it"

Sebastien Lorber
  • 79,294
  • 59
  • 260
  • 386