2

I have a container which can persist values of different types implementing the Comparable interface. I need to compare those values as follows:

UpperLowerContainer values;
//initializing the container
Comparable<?> upper = (Comparable<?>) values.getUpper();
Comparable<?> lower = (Comparable<?>) values.getLower();
if (upper.compareTo(lower) < 0){ //This is not compiled
    //do some
}

The code is not compiled because of the obvious reason. The capture of the lower's wildcard cannot be cast to the capture of upper's wildacrd and vice versa.

But how can I solve that issue? Any idea?

UPD: The type of the values stored in the container are the same. There is a validation before storing them into it.

user3663882
  • 6,957
  • 10
  • 51
  • 92
  • Comparable upper = (Comparable) values.getUpper(); Comparable lower = (Comparable) values.getLower(); try casting the as if (upper.compareTo((CLASSNAME)lower) – Spark-Beginner Jun 08 '15 at 07:24
  • classname can be date as well as integer – user3663882 Jun 08 '15 at 07:28
  • I'm not sure that what you're asking is possible. You're asking to compare potentially incomparable objects together. Having some more code would round out the actual issue, as while I think the other answers touch on the compilation, they're not sussing out the root problem. – Makoto Jun 08 '15 at 07:29
  • Although you have to teel JVM what class you are going to compare, If your class is Integer use : Comparable upper = (Comparable) values.getUpper(); Comparable lower = (Comparable) values.getLower(); if (upper.compareTo((Integer)lower) – Spark-Beginner Jun 08 '15 at 09:30

2 Answers2

0

What does your class UpperLowerContainer look like? You could use type arguments, so that you do not need to use wildcards and casts. For example:

public class UpperLowerContainer<T extends Comparable<T>> {

    private final T lower;
    private final T upper;

    public UpperLowerContainer(T lower, T upper) {
        this.lower = lower;
        this.upper = upper;
    }

    public T getLower() {
        return lower;
    }

    public T getUpper() {
        return upper;
    }
}

And then:

Comparable<T> upper = values.getUpper();
Comparable<T> lower = values.getLower();
if (upper.compareTo(lower) < 0) {
    // do something
}

The reason why it doesn't work is because the compiler can't be sure that the two wildcards in these lines refer to the same type:

Comparable<?> upper = (Comparable<?>) values.getUpper();
Comparable<?> lower = (Comparable<?>) values.getLower();

If you call compareTo on one of those comparables, you have to pass it a value of the same type. However, because type type is unknown, there's no way for the compiler to check if you pass a value of the right type, so you get an error.

Jesper
  • 202,709
  • 46
  • 318
  • 350
0

Given code will not compile until you will not specify type of object. You can not use wild cards as you are trying to use. class declaration should be:

public class UpperLowerContainer<T extends Comparable<T>>

and you should use like

Comparable<T> upper = values.getUpper();
Comparable<T> lower = values.getLower();

now you code

if (upper.compareTo(lower) < 0) {
    // do something
}

will compile

Spark-Beginner
  • 1,334
  • 5
  • 17
  • 24