Java 为什么我可以投射一个对象?可以用其他对象来完成吗?
因此,我正在编写一个Java 为什么我可以投射一个对象?可以用其他对象来完成吗?,java,casting,Java,Casting,因此,我正在编写一个paintComponent(Graphics g)方法,我一开始就意识到我正在将它转换为Graphics2D g2=(Graphics2D)g。我不久前写了这段代码,才意识到我不知道这是什么。我在谷歌上搜索了一下,但对象投射对我来说有点陌生 一个对象引用可以类型转换为另一个对象引用。这称为铸造对象 ^^从我的课本中逐字逐句地读出来,作者是Y.Daniel Liang 我不明白为什么会这样Graphics和Graphics2D是两个不同的对象,它们如何从彼此继承实例变量和方法
paintComponent(Graphics g)
方法,我一开始就意识到我正在将它转换为Graphics2D g2=(Graphics2D)g代码>。我不久前写了这段代码,才意识到我不知道这是什么。我在谷歌上搜索了一下,但对象投射对我来说有点陌生
一个对象引用可以类型转换为另一个对象引用。这称为铸造对象
^^从我的课本中逐字逐句地读出来,作者是Y.Daniel Liang
我不明白为什么会这样Graphics
和Graphics2D
是两个不同的对象,它们如何从彼此继承实例变量和方法?很明显,我意识到了原始铸造即加宽和变窄。这是有道理的,因为它们只是整数、双精度、字节等的包装类。如果你看这里“
在顶部,您将看到java.lang.Object->java.awt.Graphics->java.awt.Graphics2D
这是什么意思!?:Object是booth Graphics和Graphics2D的超类。Graphics是Graphics2D的超级类。因此Graphics2D扩展了图形,因此它们不是那么“不同”的对象。Graphics2D
和Graphics
都是抽象类,这意味着不能有它们的实例,但可以有一个扩展其中一个的对象
Graphics2D
扩展了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");
}
}
在上述示例中,g1
和g2
都是图形
,但只有g2
是图形2d
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");
}
}
paintComponent(g1)
将抛出java.lang.ClassCastException:ClassDebugGraphics无法转换为Graphics2D
,而paintComponent(g2)代码>将打印成功铸造
您在代码中没有提到发送到paintComponent()
的内容,但它扩展了Graphics2D
,因此您可以将其强制转换为它。通过强制转换,不会发生任何类型的对象转换或转换。
假设您有以下类结构:
class Mammal { }
class Human extends Mammal { }
class Dog extends Mammal { }
现在,当您使用Human-Human=new-Human()创建一个新的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();
}
}
doSomething(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();
}
}
doSomething(new Human());
因此,您的方法可以将任何类型的哺乳动物作为输入参数,在您的方法中,您可以检查它到底是什么类型的哺乳动物。因此,当您传递一个new Human()
作为输入时,对象的实际类型将是Human。之所以可以将人类传递给预期为哺乳动物的方法,是因为继承。因此,您的方法将知道,输入参数肯定是哺乳动物。但它可以是任何种类的哺乳动物。如果您想知道对象的实际类型,可以使用instanceof
作为示例。在这方面:
Human human = (Human) mammal;
并不意味着要转换哺乳动物输入参数。这只是意味着从现在起,您希望将输入参数用作人。你可以这么做,因为用IsNanceof检查它是否真的是人类。你也可以这样做:
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提供的方法。如果您查看Javadoc,您会发现,java.awt.Graphics2D
是java.awt.Graphics
的子类
在Java 11中,Graphics
的直接已知子类是debugraphics
和Graphics2D
,因此当您有Graphics g
时,它很可能也是Graphics2D
,因为Graphics
本身是一个抽象类,因此不能直接实例化。因此可以将对象强制转换为特定类型。当然,你可以先检查一下,就像这样
if(图形的g实例2d){
图形2d g2=(图形2d)g;
...
}
为了让您能够访问在Graphics2D
中定义的方法,而不是在Graphics
中定义的方法,可能需要执行强制转换
再看看Javadoc就会发现,Graphics2D
也是一个抽象类。所以,你能做的是,看看你真正处理的是什么类,打印出类名,如下所示:
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");
}
}
System.out.println(g.getClass().getName());
同一对象既可以是图形
也可以是图形2D
。关键是类Graphics2D
扩展了类Graphics
。该强制转换之所以有效,是因为该对象始终是Graphics2D
的子类型。不,它们没有完全不同,Graphics2D扩展了图形!因此Graphics2D将拥有所有公开的图形方法,如果该方法没有接收到Graphics2D对象,它应该抛出一个错误。这并不能解释编译器实际上是如何解释强制转换的。就像我说的,我显然理解原始铸造。所以从Graphics到Graphics2D的转换是有意义的。因为转换没有抛出异常,这意味着此时“g”是Graphics2D的实例,否则转换会失败。我的代码是paintComponent(Graphics g)
,我不发送任何内容,当使用super.paintComponent(g)创建JFrame时会调用它代码>在我覆盖的组件内。所以它不是发送一个Graphics2D,而是一个图形对象……对于可能出现的任何混乱,我深表歉意caused@ErlichBachmanGraphics
是超类,paintComponent
接收此类型作为参数,