Reputation: 596
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
Upvotes: 0
Views: 506
Reputation: 718798
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:
Double
(which requires a runtime check)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:
Integer
to an int
.int
to a double
. Depending on exactly how you wrote the πr2h expression, the type casts may be unnecessary.
Upvotes: 5
Reputation: 2331
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.
Double.compare
, it's a convenient method already given to do what exactly you want.@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)Upvotes: 2
Reputation: 150
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());
}
}
Upvotes: 0