Java 使用两个不同的子类进行向下转型
Java downcasting with two different subclasses
我正在学习 Java 并且一直在使用我在 Eclipse 中定义的 classes 在我的命令提示符中使用向上和向下转换。我正在使用此处包含的三个 classes,我的问题在底部:
public class Animal {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void eat() {
System.out.println("Yummy");
}
public void sleep() {
System.out.println("I like sleep.");
}
}
public class Mammal extends Animal {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void controlTemp() {
System.out.println("Temperature regulation ");
}
}
public class Lion extends Mammal {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
@Override
public void sleep() {
super.sleep();
System.out.println("Especially on the grass.");
}
@Override
public void controlTemp() {
super.controlTemp();
System.out.println("I'm an endotherm.");
}
public void roar() {
System.out.println("ROARRRRR!");
}
}
这是我在 cmd 中使用 jshell 所做的:
jshell> Animal a1 = new Lion();
a1 ==> Lion@4afc40bb
| created variable a1 : Animal
jshell> ((Mammal)a1).controlTemp();
Temperature regulation
I'm an endotherm.
jshell> ((Lion)a1).controlTemp();
Temperature regulation
I'm an endotherm.
我的问题是为什么将 a1 转换为 Mammal 会给我 Lion class 中覆盖的 controlTemp() 方法的结果,而不是 Mammal class 中的结果?
因为java中的所有非静态方法总是通过一个叫做动态调度.[=26的东西解决=]
更具体地说,什么方法签名你实际上select取决于你调用的东西的类型它在。表达式 ((Mammal) a1)
是 Mammal
类型(不是因为 a1
是狮子;这是因为任何转换为 Mammal 的都是 Mammal 类型的表达式)。
但是,对于给定的签名,您得到的实际方法是什么?这完全 取决于表达式引用的实际对象的运行时类型。
在运行时级别,方法不仅有名称:它们的完整签名包括它们的参数类型、名称和 return 类型。
如您的 @Override
注释所示,Lion class 中的 public void controlTemp()
具有相同的名称、相同的参数类型(即:noa 参数)和相同的 return 类型(即:void
),因此它 覆盖 Mammal
.
中的 void controlTemp()
方法
这使我们进入以下流程:
- 你 'selected' 在 Mammal 中定义的
controlTemp()
方法,它被编译到你的 class 文件中。换句话说,在编译过程中,都是关于哺乳动物的。这就是表达式的类型。
- 但是在运行时,这个方法是动态调度的:检查你的
a1
ref 指向的实际对象,发现是 Lion
的实例,并且最具体的版本Lion
的任何实例所具有的 controlTemp
方法的一部分,是在 Lion
中定义的方法。这样一个就被调用了。
那么你如何调用来自动物的那个? 不可能,除非在 public class Lion extends Mammal {}
中,您可以在其中使用 super.controlTemp()
调用它。在其他任何地方,你根本无法这样做(至少,如果没有原始的 class hackery,这远远超出了你所处水平的范围,而且不是任何人用 java-the-language 编写的东西这样做是有充分理由的)。
我正在学习 Java 并且一直在使用我在 Eclipse 中定义的 classes 在我的命令提示符中使用向上和向下转换。我正在使用此处包含的三个 classes,我的问题在底部:
public class Animal {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void eat() {
System.out.println("Yummy");
}
public void sleep() {
System.out.println("I like sleep.");
}
}
public class Mammal extends Animal {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
public void controlTemp() {
System.out.println("Temperature regulation ");
}
}
public class Lion extends Mammal {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
@Override
public void sleep() {
super.sleep();
System.out.println("Especially on the grass.");
}
@Override
public void controlTemp() {
super.controlTemp();
System.out.println("I'm an endotherm.");
}
public void roar() {
System.out.println("ROARRRRR!");
}
}
这是我在 cmd 中使用 jshell 所做的:
jshell> Animal a1 = new Lion();
a1 ==> Lion@4afc40bb
| created variable a1 : Animal
jshell> ((Mammal)a1).controlTemp();
Temperature regulation
I'm an endotherm.
jshell> ((Lion)a1).controlTemp();
Temperature regulation
I'm an endotherm.
我的问题是为什么将 a1 转换为 Mammal 会给我 Lion class 中覆盖的 controlTemp() 方法的结果,而不是 Mammal class 中的结果?
因为java中的所有非静态方法总是通过一个叫做动态调度.[=26的东西解决=]
更具体地说,什么方法签名你实际上select取决于你调用的东西的类型它在。表达式 ((Mammal) a1)
是 Mammal
类型(不是因为 a1
是狮子;这是因为任何转换为 Mammal 的都是 Mammal 类型的表达式)。
但是,对于给定的签名,您得到的实际方法是什么?这完全 取决于表达式引用的实际对象的运行时类型。
在运行时级别,方法不仅有名称:它们的完整签名包括它们的参数类型、名称和 return 类型。
如您的 @Override
注释所示,Lion class 中的 public void controlTemp()
具有相同的名称、相同的参数类型(即:noa 参数)和相同的 return 类型(即:void
),因此它 覆盖 Mammal
.
void controlTemp()
方法
这使我们进入以下流程:
- 你 'selected' 在 Mammal 中定义的
controlTemp()
方法,它被编译到你的 class 文件中。换句话说,在编译过程中,都是关于哺乳动物的。这就是表达式的类型。 - 但是在运行时,这个方法是动态调度的:检查你的
a1
ref 指向的实际对象,发现是Lion
的实例,并且最具体的版本Lion
的任何实例所具有的controlTemp
方法的一部分,是在Lion
中定义的方法。这样一个就被调用了。
那么你如何调用来自动物的那个? 不可能,除非在 public class Lion extends Mammal {}
中,您可以在其中使用 super.controlTemp()
调用它。在其他任何地方,你根本无法这样做(至少,如果没有原始的 class hackery,这远远超出了你所处水平的范围,而且不是任何人用 java-the-language 编写的东西这样做是有充分理由的)。