【问题标题】:Rectangle cannot be cast to Circle?矩形不能转换为圆形?
【发布时间】:2015-10-13 16:58:43
【问题描述】:

所以我正在尝试编写一个方法来返回具有最大区域的对象的索引。这是我目前的方法

private static int findPositionLargestObject(ArrayList < GeometricObject > geoList) {
    int maxIndexC = 0;
    int maxIndexR = 0;
    for (GeometricObject o: geoList) {
        for (int i = 1; i < geoList.size(); i++) {
            if (o instanceof Rectangle) {
                if (((Rectangle) geoList.get(i)).getArea() > ((Rectangle) geoList.get(maxIndexR)).getArea()) {
                    maxIndexR = i;
                }
            }
            if (o instanceof Circle) {
                if (((Circle) geoList.get(i)).getArea() > ((Circle) geoList.get(maxIndexC)).getArea()) {
                    maxIndexC = i;
                }
            }

        }
    }
    if (maxIndexC > maxIndexR) {
        return maxIndexC;
    } else return maxIndexR;
}

但是,当我运行此方法时,我收到错误消息 rectangle can't be cast to circle。我之所以有两个不同的 if 语句,是因为圆形和矩形对象的 getArea 方法分别不同。任何想法为什么我会收到此消息,谢谢!

这是我的公开课

public class hw2redo 
{
     public static void main(String[] args) throws FileNotFoundException {

          GeometricObject g = null;
          File diskFile = new File("file.txt");
          Scanner diskScanner = new Scanner(diskFile);
          ArrayList<GeometricObject> list = new ArrayList<GeometricObject>();
          while(diskScanner.hasNext()){
              String geolist = diskScanner.nextLine();
              g = recreateObject(geolist);

              list.add(g);

          }
          diskScanner.close();
         /* while (diskScanner.hasNext()) {
              String list = diskScanner.nextLine();
              g = recreateObject(list);
          }
          diskScanner.close();*/
          showObjects(list);
          findPositionLargestObject(list);
       }





    private static GeometricObject recreateObject(String data) {

          String[] list = data.split(",");
          String geoObject = list[0];

          if (geoObject.equals("Circle")) {
             String color = list[1];
             boolean filled = Boolean.valueOf(list[2]); 
             double radius = Double.valueOf(list[3]);
             return new Circle(radius, color, filled);
          }

          if (geoObject.equals("Rectangle")) {
             String color = list[1];
             boolean filled = Boolean.valueOf(list[2]);
             double height = Double.valueOf(list[3]);
             double width = Double.valueOf(list[4]);
             return new Rectangle(width, height, color, filled);
          }
        return null;


       }

    private static void showObjects(ArrayList<GeometricObject> list) {

         for(GeometricObject o : list) {

             if ( o instanceof Circle)
             {
             System.out.println(o);
             ((Circle) o).printCircle();
             System.out.println("");
             }
             if ( o instanceof Rectangle)
             {
             System.out.println(o);
             ((Rectangle) o).printRectangle();
             System.out.println("");
             }
         }
    }
      private static int findPositionLargestObject(ArrayList<GeometricObject> geoList) {

            int maxIndexC = 0;
            int maxIndexR = 0;
            for(GeometricObject o : geoList)
            {
            for (int i = 1; i < geoList.size(); i++) {
                if ( o instanceof Rectangle)
                {
                if (((Rectangle) geoList.get(i)).getArea() > ((Rectangle) geoList.get(maxIndexR)).getArea()) {
                    maxIndexR = i;
                }
                }
                if ( o instanceof Circle)
                {
                if (((Circle) geoList.get(i)).getArea() > ((Circle) geoList.get(maxIndexC)).getArea()) {
                        maxIndexC = i;
                }
                }

            }
        }
           if (maxIndexC > maxIndexR)
           {
               return maxIndexC;
           }
           else
               return maxIndexR;
     }
}

【问题讨论】:

    标签: java object casting dynamic-arrays


    【解决方案1】:

    您为每个对象循环遍历数组两次。

    for (GeometricObject o: geoList) { // for each GeometricObject in geoList, 
        for (int i = 1; i < geoList.size(); i++) { // loop through each object in geoList.
    

    删除 for-each 循环或常规 for 循环。

    【讨论】:

      【解决方案2】:

      由于没有为GeometricObject 提供代码,但我假设getArea()GeometricObject 中以某种方式定义,所以如果您可以直接评估它,为什么还要使用演员表:

      int max_circle , area_circle;
      int max_rect , area_rec;
      
      for(int i = 0 ; i < geoList.size() ; i++){
          GeometricObject go = geoList.get(i);
      
          if(go instanceof Rectangle)
              if(go.getArea() > area_rec){
                  area_rec = go.getArea();
                  max_rect = i;
              }else{
                  area_circle = go.getArea();
                  max_circle = i;
              }
      }
      

      你的代码抛出异常的原因是:

      ((Rectangle) geoList.get(maxIndexR))
      

      maxIndexR 初始化为 0,对于圆圈也是如此。因此,如果geoList 中的第一个元素是Rectangle,则第一个圆圈将导致调用((Circle) geoList.get(0)),但第一个元素是Rectangle。同样适用于其他方式。如果您想保留您的代码,只需添加另一个变量来存储圆形和矩形的最大面积,并简单地使用这些值(初始化为 0),而不是从列表中检索形状并进行转换。

      【讨论】:

      • 我的 GeometricObject 实际上没有 getArea() 方法。我的理由是它如何知道是否要检索圆形或矩形区域,因为它们需要不同的公式?
      • @RiFFRAFF 可以使用抽象方法非常简单地解决 (docs.oracle.com/javase/tutorial/java/IandI/abstract.html)。虽然你也可以简单地使用第二种解决方案,如果你不想修改GeometricObject的代码。
      • 好吧,我的 GeometricObject 类是抽象的,我的 Circle 和 Rectangle 类扩展了它,我仍然不明白我如何能够告诉我的 GeometricObject 的 getArea 方法我要使用哪个。
      • @RiFFRAFF 一点也不。这就是多态性背后的想法。您只需向GeometricObject 添加一个抽象定义,任何非抽象子类必须实现getArea()。因此,您可以执行以下操作:GeometricObject go = new Rectangle(...); int area = go.getArea();
      【解决方案3】:

      您正在检查 o 是否是 Rectangle/Circle 的实例,但将 geoList.get(i) 转换为相应的类型。事实上,o 不会在循环中的任何地方使用,除了instanceof 检查。

      【讨论】:

        【解决方案4】:

        据我所知,您将有两个类,Rectangle 和 Circle,它们是从一个名为 Geometry 的通用类扩展而来的。这里要注意的一件重要事情是 Rectangle 和 Circle 将是兄弟姐妹。那是矩形永远不是圆形,反之亦然。此语句的直接后果是您不能将 Rectangle 实例视为 Circle 实例,反之亦然。

        在您的方法 findPositionLargestObject 中,您将 maxIndexCmaxIndexR 初始化为 0。虽然这听起来无害,但实际上您可以这样做:

                    if ( o instanceof Rectangle)
                    {
                    if (((Rectangle) geoList.get(i)).getArea() > ((Rectangle) geoList.get(maxIndexR)).getArea()) {
        

        // 最初为 '0' 的 maxIndexR 的保证是 Rectangle 而不是 Circle? 最大指数R = i; } } if (o instanceof Circle) { if (((Circle) geoList.get(i)).getArea() > ((Circle) geoList.get(maxIndexC)).getArea()) { // 最初为 '0' 的 maxIndexC 的保证是圆形而不是矩形? 最大索引C = i; } }

        这里肯定有一些谬误。另外,如果你只有两种 Geometry,你可以使用if else 而不是两个if clauses。这样会更防错。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多