简体   繁体   中英

casting Integer Object to double throwing error

I am trying to write a 'Cup' class which implements the Comparable interface.

My code:

class Cup<T> implements Comparable<T>{

    public T radius;
    public T height;

    public Cup(T radius, T height){
        this.radius = radius;
        this.height = height;
    }

    public double getVolume(){

        return (double) radius * (double) radius* (double) height* 3.14 ; // throwing error 
    }

    public int compareTo(Object cup){

        if(getVolume()== ((Cup) cup).getVolume()){ // cannot access java.lang.Comparable
            return 0;
        }
        else if(getVolume() > ((Cup) cup).getVolume()){
            return 1;
        }
        else if(getVolume() < ((Cup) cup).getVolume()){
            return -1;
        }
        return -2;
    }
}

class test{
    public static void main(String[] args) {

        Cup<Integer> mycup = new Cup<Integer>(5,5);

        Cup<Integer> momscup = new Cup<Integer>(7,7);

        mycup.compareTo(momscup);

    }
}

But the program throws error stating: java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Double .

I am NOT trying to cast to Double, but to double. Why is it throwing the error?

Thanks

I am NOT trying to cast to Double, but to double. Why is it throwing the error?

The root of your problem is that the static type of T is Object not Integer . So the compiler has determined that the following path may work:

  1. Cast the object's actual type to Double (which requires a runtime check)
  2. Unbox the Double to a double .

The problem is that Integer cannot be cast to Double .

The best solution is this:

class Cup<T extends Number> implements Comparable<T> {
    ...
    public double getVolume(){
        return radius.doubleValue() * radius.doubleValue() 
               height.doubleValue() * Math.PI;
    }

which is statically type-safe (modulo any unsafe conversions that you might do elsewhere).


Note that if T was replaced by Integer , the compiler would use a different path for the conversion:

  1. Unbox the Integer to an int .
  2. Widen the int to a double .

Depending on exactly how you wrote the πr 2 h expression, the type casts may be unnecessary.

By what you are doing is actually implicitly adding a cast to Double and because of this you are getting the exception.

I'd suggest you few changes after which your class looks like this:

class Cup<T extends Number> implements Comparable<Cup<T>> {

    public T radius;
    public T height;

    public Cup(T radius, T height) {
        this.radius = radius;
        this.height = height;
    }

    public double getVolume() {
        return radius.doubleValue() * radius.doubleValue() * height.doubleValue() * 3.14;
    }

    @Override
    public int compareTo(Cup<T> cup) {
        return Double.compare(getVolume(), cup.getVolume());
    }
}

Closely look how I've changed the compareTo method and the getVolume method to make it more readable.

And after these changes you don't get when running the test:

class test {
    public static void main(String[] args) {
        Cup<Integer> mycup = new Cup<>(5, 5);
        Cup<Integer> momscup = new Cup<>(7, 7);
        mycup.compareTo(momscup);
    }
}

The following are the changes that I'd suggest you so that you can learn.

  • From Effective Java Item 31, you should use bounded wildcards to increase the API flexibility. (Read the generics chapter from Effective Java, it will be highly helpful)
  • Use Double.compare , it's a convenient method already given to do what exactly you want.
  • Use @Override if you are overriding a method.
  • Cup<Integer> mycup = new Cup<>(5, 5); While initialization you again don't need to mention Integer on the right-hand side. (This can be done if you are using JDK 7 or higher)

radius and height properties are defined as T, but you cast them to double, you should declare them as double or make the Generic type of the class extends Number which is the abstract parent class of Double and Integer

class Cup<T extends Number> {

    public T radius;
    public T height;

    public Cup(T radius, T height) {
        this.radius = radius;
        this.height = height;
    }

    public double getVolume() {

        return radius.doubleValue() * radius.doubleValue() * height.doubleValue() * 3.14; // throwing error 
    }

}

class test {

    public static void main(String[] args) {

        Cup<Integer> mycup = new Cup<Integer>(5, 5);

        Cup<Integer> momscup = new Cup<Integer>(7, 7);

        System.out.println(mycup.getVolume());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM