Reputation: 539
Before asking this question I want to say I am new in Java Generics. I have tried to implement Comparator chaining for a class so I have created this following class.
static class ChainComparator implements Comparator<StudentDTO> {
List<Comparator<StudentDTO>> chainComparators;
@SafeVarargs
public ChainComparator(Comparator<StudentDTO>... comparators) {
chainComparators = Arrays.asList(comparators);
}
@Override
public int compare(StudentDTO o1, StudentDTO o2) {
for (Comparator<StudentDTO> comparator : chainComparators) {
int result = comparator.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
}
Here this class I have created for multiple comparator implementation for Student class. Now I am thinking this can be generic for all classes so I have tried with the following class.
public class ChainComparator implements Comparator<Class<?>>{
List<Comparator<?>> chainComparators;
@SafeVarargs
public ChainComparator(Comparator<?>... comparators) {
chainComparators = Arrays.asList(comparators);
}
@Override
public int compare(Class<?> o1, Class<?> o2) {
for (Comparator<?> comparator : chainComparators) {
int result = comparator.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
}
But here I am getting the following compilation error
The method compare(capture#1-of ?, capture#1-of ?) in the type Comparator<capture#1-of ?> is not applicable for the arguments (Class<capture#2-of ?>, Class<capture#3-of ?>)
I am getting this above error on the below line
comparator.compare(o1, o2);
Can anyone please help me to understand why I am getting this error and how I can solve this error or my approach itself is wrong.
I can understand if I use any other library or Java8 I can achieve this very quickly with a decent code but actually I just curious and wanted to learn and understand Generic more.
Upvotes: 0
Views: 73
Reputation: 159086
You can't use wildcards here, because every wildcard is independent of the others.
Comparator<?>
and compare(Class<?> o1, Class<?> o2)
can be considered as meaning Comparator<A>
and compare(Class<B> o1, Class<C> o2)
, where A
, B
, and C
can each be anything (wildcard), but you cannot of cause compare a Class<B>
with a Class<C>
.
What you need to do is declare a generic parameter.
static class ChainComparator<T> implements Comparator<T> {
List<Comparator<T>> chainComparators;
@SafeVarargs
public ChainComparator(Comparator<T>... comparators) {
chainComparators = Arrays.asList(comparators);
}
@Override
public int compare(T o1, T o2) {
for (Comparator<T> comparator : chainComparators) {
int result = comparator.compare(o1, o2);
if (result != 0) {
return result;
}
}
return 0;
}
}
You would then use it using the diamond operator:
Comparator<Foo> chain = new ChainComparator<>(fooComparator1, fooComparator2);
Upvotes: 1