Почему я могу разыграть предмет? Можно ли это сделать с другими объектами? - PullRequest
2 голосов
/ 13 февраля 2020

Итак, я писал paintComponent(Graphics g) метод, и в начале понял, что приводю его к Graphics2D g2 = (Graphics2D) g;. Я написал этот код некоторое время go и просто понял, что понятия не имею, что это такое. Я немного погуглил, но приведение объектов немного чуждо мне.

Одна ссылка на объект может быть приведена к другой ссылке на объект. Это называется объектом приведения.

^^ Слово в слово из моего учебника Я. Даниэля Ляна

Я не понимаю, почему это работает. Graphics и Graphics2D - это два разных объекта, как они могут наследовать переменные экземпляра и методы друг от друга? Очевидно, я знаю, что примитивное литье ie расширяется и сужается. Это имеет смысл, поскольку они являются просто классами-обертками Integer, Double, Byte et c ...

Ответы [ 4 ]

2 голосов
/ 13 февраля 2020

При приведении не происходит никакого преобразования или преобразования объекта. Просто представьте, что у вас следующая структура класса:

class Mammal { }
class Human extends Mammal { }
class Dog extends Mammal { }

Теперь, когда вы создаете новый экземпляр Human с Human human = new Human();, это тоже будет Млекопитающее, верно? Таким образом, вы можете написать метод вроде:

public void doSoemthing(Mammal mammal) {
    if (mammal instanceof Human) {
        Human human = (Human) mammal;
        human.doWork();
    } else if (mammal instanceof Dog) {
        Dog dog = (Dog) mammal;
        dog.bark();
    }
}

и вызвать метод: можно проверить, что это за млекопитающее. Поэтому, когда вы передаете new Human() в качестве входных данных, фактическим типом объекта будет Human. Причина, по которой вы можете передать Человека методу, ожидающему Млекопитающее, заключается в наследовании. Итак, ваш метод будет знать, что входной параметр определенно является млекопитающим. Но это может быть любой вид млекопитающего. Если вы хотите узнать, что является типом Объекта, вы можете использовать instanceof, например. И в этой строке:

Human human = (Human) mammal;

не означает, что вы конвертируете входной параметр млекопитающего. Это просто означает, что теперь вы хотите использовать входной параметр в качестве человека. И вы можете сделать это, потому что с течением времени вы проверяете, что это действительно человек. Вы также можете сделать что-то вроде этого:

public void doExample2(Object input) {
    if (input instanceof Integer) {
        System.out.println("I am a number");
    } else if (input instanceof Graphics) {
        System.out.println("I am a Graphics");
    }
}

Обратите внимание на тип входного параметра. Объект - это базовый класс всего.

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

1 голос
/ 13 февраля 2020

Оба Graphics2D и Graphics являются абстрактными классами, что означает, что вы не можете иметь их экземпляр, но вы можете иметь объект, расширяющий один из них.

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

abstract class Graphics {}

abstract class Graphics2D extends Graphics {}

class ClassGraphics extends Graphics {}

class ClassGraphics2D extends Graphics2D {}

class Main {

    public static void main(String[] args) {
        Graphics g1 = new ClassDebugGraphics();
        Graphics g2 = new ClassDebugGraphics2D();
        paintComponent(g1);
        paintComponent(g2);
    }

    public static void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        System.out.print("Successful casting");
    }
}

In В приведенном выше примере g1 и g2 равны Graphics, но только g2 равно Graphics2D.

paintComponent(g1); выдаст java.lang.ClassCastException: ClassDebugGraphics cannot be cast to Graphics2D, а paintComponent(g2); выведет Successful casting .

Вы не упомянули, что отправлено на paintComponent() в вашем коде, но оно расширяет Graphics2D, так что вы можете привести его к нему.

0 голосов
/ 13 февраля 2020

Если вы посмотрите на Javado c, вы увидите, что java.awt.Graphics2D является подклассом java.awt.Graphics. https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/java/awt/Graphics2D.html

В Java 11 прямыми известными подклассами Graphics являются DebugGraphics и Graphics2D, поэтому, когда у вас есть Graphics g, наиболее вероятно также Graphics2D, поскольку Graphics сам по себе является абстрактным классом и, следовательно, не может быть создан непосредственно. Таким образом, вы можете привести объект к указанному типу c. Чтобы быть уверенным, вы могли бы сначала выполнить проверку, например, так.

if (g instanceof Graphics2D) {
    Graphics2D g2 = (Graphics2D) g;
    ...
}

Приведение, вероятно, выполнено, чтобы вы могли получить доступ к методам, определенным в Graphics2D, но не в Graphics.

Другой взгляд на Javado c показывает, что Graphics2D также является абстрактным классом. Итак, что вы можете сделать, чтобы увидеть, с каким классом вы действительно имеете дело, распечатать имя класса следующим образом:

System.out.println(g.getClass().getName());
0 голосов
/ 13 февраля 2020

Если вы посмотрите здесь "https://docs.oracle.com/javase/7/docs/api/java/awt/Graphics2D.html"

В верхней части вы увидите java .lang.Object -> java .awt.Graphics - > java .awt.Graphics2D

Так что же это значит!?: java .lang.Object - суперкласс для стенда Graphics и Graphics2D. Графика это супер класс для Graphics2D. Таким образом, Graphics2D расширяет Graphics, поэтому они не настолько «разные» объекты.

...