【问题标题】:casting parent to child - BufferedImage object将父级转换为子级 - BufferedImage 对象
【发布时间】:2012-08-03 15:37:27
【问题描述】:

每当我尝试将 BufferedImage(父)转换为我扩展自己的 AdvancedBufferedImage(子)时,我都会得到一个 ClassCastException,我没有没有覆盖任何方法,而且我已经实现了所有的承包商而不修改它们

每当我尝试使用 ImageIO.read() 方法从文件中创建 AdvancedBufferedImage 时,都会遇到此异常。

File file = new file(path);
AdvancedBufferedImage image = (AdvancedBufferedImage) ImageIO.read(file);

看起来应该没有问题,请问是什么问题?

【问题讨论】:

    标签: java casting bufferedimage


    【解决方案1】:

    这样的向下转换是不允许的。

    首选的解决方案是创建 AdvancedBufferedImage 的构造函数,将 BufferedImage 作为参数。有了它,您可以执行以下操作。

    File file = new file(path);
    AdvancedBufferedImage image = new AdvancedBufferedImage(ImageIO.read(file));
    

    这里 AdvancedBufferedImage 的构造函数可以决定如何将 BufferedImage 正确转换为高级..

    【讨论】:

    • 所以你建议将AdvancedBufferedImage与BufferedImage的关系改为HAS A not IS A?
    • 没错。这种方法允许您委派您不想自己实现的方法,并且仍然添加额外的功能。您只需包装现有的类。
    • 只是一个通知,在 Eclipse 中有一个方便的工具可以做到这一点,创建一个具有您要委托的类的实例的类,右键单击成员 delegate methods。对于大型课程非常方便
    • 哇,您在发布日食评论后 2 年又回到了这里。记住这一点做得很好。我不记得曾经写过这个答案:P
    【解决方案2】:

    您不能将 PARENT 类强制转换为 CHILD 类,除非 PARENT 类的引用包含 CHILD 类或其派生类的实例。

    在您的情况下,ImageIO.read(file) 返回一个 BufferedImage 的实例,它是基类。这只有在ImageIO.read(file) 返回AdvancedBufferedImage 或其子类的实例时才有效。

    当你扩展某个类时,派生类会从基类继承一些属性,但是,基类什么也得不到。因此,由于派生类的实例具有基类的所有属性,因此基类的引用可以保存派生类的实例,即您可以将派生类强制转换为基类。现在,派生类可能会添加一些新属性,而基类永远不会知道这些属性。所以从 BASE 类转换为 DERIVED 显然是不正确的。

    【讨论】:

      【解决方案3】:

      Downcasting in Java

      向下转换不会像这样工作。请参阅上面帖子中的答案。作为替代方案,如何创建一个静态工厂方法,该方法采用BufferedImage 并返回使用ImageIO.read() 返回的对象构建的类的实例?

      例如:

      private AdvancedBufferedImage(BufferedImage bi) {
          //  build your AdvancedBufferedImage from bi
          ...
      }
      
      public static AdvancedBufferedImage buildABI(BufferedImage bi) {
          return new AdvancedBufferedImage(bi)
      

      【讨论】:

      • 我明白你想说什么,但在这种情况下,承包商中有一些参数没有获取器,所以它也必须实施
      • 那么在您的情况下,我认为组合比继承更好。您的班级是否拥有一个 BufferedImage 对象而不是扩展它?
      【解决方案4】:

      通常,您不能将父类转换为子类。 就像强制将动物施用于狗。狗是一种动物,但另一种说法并不总是正确的,因此 Java 编译器不允许您这样做。

      object inheritance

      【讨论】:

        【解决方案5】:

        允许向下转换,但它必须是孩子的实际实例:

        class A {
          String name = "a";
          A(){};
        }
        
        class B extends A {
        }
        
        public class Main {
          public static void main(String[] args) {
            A a = new B(); // must a b instance
            B b = new B();
            b = (B)a;
            System.out.println(b.name);
        
          }
        }
        

        【讨论】:

          【解决方案6】:

          BufferedImage 不是 AdvancedBufferedImage,所以转换失败。

          您可以扩展BufferedImage 的功能,但read 方法仍然只返回BufferedImage。强制转换不会强制引用成为或表现为所需的类型。

          您可能希望在您的 AdvancedBufferedImage 类中包装一个 BufferedImage,然后您可以传递和操作您的高级类。

          【讨论】:

            【解决方案7】:

            只有当您尝试转换的对象实际上是您要转换的类的实例时,您的向下转换才会成功。

            【讨论】:

              猜你喜欢
              • 2015-10-20
              • 1970-01-01
              • 2021-08-29
              • 2018-05-16
              • 2018-09-17
              • 1970-01-01
              • 2015-01-21
              相关资源
              最近更新 更多