我正在尝试编写一个实现Comparable接口的'Cup'类。
我的代码:
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);
}
}
但该程序抛出错误说明:java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Double
。
我不是要试图加入Double,而是加倍。为什么会抛出错误?
谢谢
我不是要试图加入Double,而是加倍。为什么会抛出错误?
问题的根源是T
的静态类型是Object
而不是Integer
。因此编译器已确定以下路径可能有效:
Double
(需要运行时检查)Double
拆开为double
。问题是Integer
无法投射到Double
。
最好的解决方案是:
class Cup<T extends Number> implements Comparable<T> {
...
public double getVolume(){
return radius.doubleValue() * radius.doubleValue()
height.doubleValue() * Math.PI;
}
这是静态类型安全的(模块化你可能在其他地方做的任何不安全的转换)。
请注意,如果T
被Integer
替换,编译器将使用不同的路径进行转换:
Integer
拆箱到int
。int
扩大到double
。根据您编写πr2h表达式的具体方式,类型强制转换可能是不必要的。
通过你正在做的事实上是隐含地向Double
添加一个强制转换,因此你得到了异常。
我建议您进行一些更改,之后您的课程将如下所示:
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());
}
}
仔细看看我是如何改变compareTo
方法和getVolume
方法以使其更具可读性。
在完成这些更改后,您在运行测试时无法获得:
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);
}
}
以下是我建议您进行的更改,以便您可以学习。
Double.compare
,它是一种方便的方法,可以用来做你想要的。@Override
。Cup<Integer> mycup = new Cup<>(5, 5);
初始化时你再次不需要在右侧提及Integer
。 (如果您使用的是JDK 7或更高版本,则可以这样做)radius和height属性定义为T,但是你将它们转换为double,你应该将它们声明为double或者使类的泛型类型扩展Number这是Double和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());
}
}