转换Integer对象以加倍抛出错误

问题描述 投票:0回答:3

我正在尝试编写一个实现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,而是加倍。为什么会抛出错误?

谢谢

java
3个回答
5
投票

我不是要试图加入Double,而是加倍。为什么会抛出错误?

问题的根源是T的静态类型是Object而不是Integer。因此编译器已确定以下路径可能有效:

  1. 将对象的实际类型转换为Double(需要运行时检查)
  2. Double拆开为double

问题是Integer无法投射到Double

最好的解决方案是:

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

这是静态类型安全的(模块化你可能在其他地方做的任何不安全的转换)。


请注意,如果TInteger替换,编译器将使用不同的路径进行转换:

  1. Integer拆箱到int
  2. int扩大到double

根据您编写πr2h表达式的具体方式,类型强制转换可能是不必要的。


2
投票

通过你正在做的事实上是隐含地向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);
    }
}

以下是我建议您进行的更改,以便您可以学习。

  • 从Effective Java Item 31开始,您应该使用有界通配符来增加API灵活性。 (阅读Effective Java中的泛型章节,它将非常有帮助)
  • 使用Double.compare,它是一种方便的方法,可以用来做你想要的。
  • 如果要覆盖方法,请使用@Override
  • Cup<Integer> mycup = new Cup<>(5, 5);初始化时你再次不需要在右侧提及Integer。 (如果您使用的是JDK 7或更高版本,则可以这样做)

0
投票

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());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.