приведение родителя к дочернему объекту BufferedImage


Я получаю ClassCastException всякий раз, когда я пытаюсь привести BufferedImage (parent) к AdvancedBufferedImage (child) , который я расширил сам, я не переопределил любые методы и я реализовал все подрядчики , Не изменяя их

Я получаю это исключение всякий раз, когда пытаюсь создать AdvancedBufferedImage из файла с помощью ImageIO.метод read.

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

Кажется, не должно быть никакой проблемы, в чем может быть проблема?

7 9

7 ответов:

Приведения типов, как это не допускается.

Предпочтительным решением было бы создать конструктор AdvancedBufferedImage, взяв в качестве параметра BufferedImage. С этим вы могли бы сделать следующее.

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

Здесь Конструктор AdvancedBufferedImage может решить, как правильно преобразовать BufferedImage в advanced..

Нельзя привести родительский класс к дочернему классу, если ссылка родительского класса не содержит экземпляр дочернего класса или его производных классов.

В вашем случае ImageIO.read(file) возвращает экземпляр BufferedImage, который является базовым классом. Это будет работать только в том случае, если ImageIO.read(file) возвращает экземпляр AdvancedBufferedImage или его подклассы.

При расширении некоторого класса производный класс наследует некоторые свойства от базового класса, однако базовый класс ничего не получает. В результате этого, так как пример производный класс обладает всеми свойствами базового класса, ссылка на базовый класс может содержать экземпляр производного класса, т. е. вы можете привести производный класс к базовому классу. Теперь производный класс может добавить некоторые новые свойства, а базовый класс никогда не знает об этих свойствах. Таким образом, приведение от базового класса к производному явно неверно.

Даункастинг на Java

Приведения типов не собирается работать. Смотрите ответ в приведенном выше сообщении. В качестве альтернативы, как насчет создания статического фабричного метода, который принимает BufferedImage и возвращает экземпляр вашего класса, построенный с объектом, возвращаемым ImageIO.read()?

Например:

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

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

В общем случае классы родителей нельзя преобразовать в классы детей. Это все равно, что заставить бросить животное собаке. Собака-это животное, но другой путь не всегда верен, поэтому компилятор 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);

  }
}

BufferedImage разве это не AdvancedBufferedImage и вот актерский состав терпит неудачу.

Вы можете расширить функциональность BufferedImage, но метод read по-прежнему возвращает только BufferedImage. Приведение не заставляет ссылку становиться или вести себя как нужный тип.

Вы, вероятно, хотите обернуть BufferedImage в свой AdvancedBufferedImage класс, а затем вы можете передавать и управлять своим продвинутым классом.

Ваше понижение будет успешным только в том случае, если объект, который вы пытаетесь привести, на самом деле является экземпляром класса, к которому вы приводите.