Java 将父对象强制转换为子对象-BuffereImage对象

Java 将父对象强制转换为子对象-BuffereImage对象,java,casting,bufferedimage,Java,Casting,Bufferedimage,每当我尝试将一个BuffereImage(父级)强制转换为我扩展的AdvancedBuffereImage(子级)时,我会得到一个ClassCastException,我没有覆盖任何方法,并且在不修改它们的情况下实现了所有承包商 每当我尝试使用ImageIO.read()方法从文件中创建AdvancedBuffereImage时,我都会签署此异常 看来应该没有什么问题,,有什么问题吗?只有当您试图强制转换的对象实际上是要强制转换到的类的实例时,您的向下转换才会成功。除非父类的引用包含子类或其派生

每当我尝试将一个BuffereImage(父级)强制转换为我扩展的AdvancedBuffereImage(子级)时,我会得到一个
ClassCastException
,我没有覆盖任何方法,并且在不修改它们的情况下实现了所有承包商

每当我尝试使用ImageIO.read()方法从文件中创建AdvancedBuffereImage时,我都会签署此异常


看来应该没有什么问题,,有什么问题吗?

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

除非父类的引用包含子类或其派生类的实例,否则无法将父类强制转换为子类

在您的例子中,
ImageIO.read(file)
返回
buffereImage
的一个实例,它是基类。只有当
ImageIO.read(file)
返回
AdvancedBuffereImage
或其子类的实例时,这才有效

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

向下投射不会像这样起作用。请参见上面帖子中的答案。另一种方法是,创建一个静态工厂方法,该方法接受
buffereImage
,并返回使用
ImageIO.read()
返回的对象构建的类的实例

例如:

private AdvancedBufferedImage(BufferedImage bi) {
    //  build your AdvancedBufferedImage from bi
    ...
}

public static AdvancedBufferedImage buildABI(BufferedImage bi) {
    return new AdvancedBufferedImage(bi)

buffereImage
不是
AdvancedBuffereImage
,因此强制转换失败

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


你可能想在你的
AdvancedBuffereImage
类中包装一个
BuffereImage
,然后你可以传递并操作你的高级类。

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

首选的解决方案是创建AdvancedBuffereImage的构造函数,将BuffereImage作为参数。有了它,你可以做以下事情

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

在这里,AdvancedBuffereImage的构造函数可以决定如何在advanced中正确转换BuffereImage。

通常,不能将父类强制转换为子类就像强迫把动物扔给狗一样。狗是动物,但另一种方式并不总是正确的,所以Java编译器不允许您这样做


请参阅。

允许向下广播,但它必须是子级的实际实例:

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);

  }
}

因此,您建议将AdvancedBuffereImage的关系更改为BuffereImage,即具有A而不是?确切地说。这种方法允许您委派不希望自己实现的方法,并且仍然添加额外的功能。只需包装现有类。请注意,eclipse中有一个方便的工具可用于包装现有类,创建一个包含要委托的类实例的类,右键单击成员,
delegate methods
。对于大型类来说非常方便哇,在发布添加eclipse评论的帖子2年后,您又回到了这里。记住这一点很好。我不记得曾经写过这样的回答:我知道你想说什么,但在这种情况下,承包商中有一些参数没有获得者,因此它也必须实现。然后我认为在你的情况下,组合比继承更好。让您的类拥有BuffereImage对象而不是扩展它?
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);

  }
}