当谈到多态性、继承、重载、覆盖、泛型和转换的混合时如何记住事情
How to remember things when it comes to mixture of polymorphism, Inheritance, overloading, overriding, Generics as well as Casting
我正在准备 Java 认证考试,当涉及到多态性、继承、重载、覆盖、泛型以及转换时,很少有情况会变得非常复杂。
我无法理解下面提到的这些示例:
// Tree is the base class
class Tree {
String type = "unknown";
String getTreeString() {
return "Tree";
}
}
// DeciduousTree is a subclass of Tree
class DeciduousTree extends Tree {
String type = "deciduous";
@Override
String getTreeString() {
return "Leafy Tree";
}
}
// FruitTree is a subclass of Tree
class FruitTree extends Tree {
String type = "fruit";
@Override
String getTreeString() {
return "Fruit Tree";
}
}
public class UpcastExamples {
public static void main(String[] args) {
UpcastExamples upex = new UpcastExamples();
// Create two specific trees
Tree tree = new Tree();
Tree mapleTree = new DeciduousTree();
Tree appleTree = new FruitTree();
// we upcast deciduousTree to its parent class
Tree genericTreeMaple = (Tree) mapleTree;
Tree genericTreeApple = (Tree) appleTree;
Tree genericTreeTree = (Tree) tree;
// Print mapleTree's type
System.out.println("Tree type = " + mapleTree.type);
// Let's upcast to use the generic Tree's type..
System.out.println("Tree type = " + (genericTreeMaple.type));
// Print Fruit Tree's type
System.out.println("Tree type = " + appleTree.type);
// Upcasting to pass object as a parameter
upex.printTreeType(genericTreeTree);
upex.printTreeType(genericTreeMaple);
upex.printTreeType(genericTreeApple);
upex.printTreeType(tree);
upex.printTreeType(mapleTree);
upex.printTreeType(appleTree);
}
public void printTreeType(Tree tree) {
System.out.println("Tree type = " + tree.getTreeString());
}
}
我希望这些 upex.printTreeType(genericTreeMaple);upex.printTreeType(genericTreeApple);
打印 Tree
因为它们被升级到 Tree(Base Class) 但不知何故它抓住了它的方法 child classes(我知道它们被覆盖了)但是通过方法重载实现时是一样的
Animal genericDog = new Dog();Animal genericCat = new Cat();
将坚持 parent 的 class 的方法。
我试着这样记住 parentClass p = new childClass() 将始终引用 parent[=27= 的方法] 但它似乎在重写和向上转换期间失败了。
另外,下面还有一些我看不懂的地方,我不想死记硬背
Here BaseClass class is the parent class
And NextClass inherits the BaseClass
BaseClass[] myNextArray = new NextClass[6];
BaseClass[] myNextArray2 = new BaseClass[6];
//Allows this:
NextClass[] nextArray = (NextClass[]) myNextArray; //Line 1
//But doesn't allows this:
NextClass[] nextArray2 = (NextClass[]) myNextArray2;
Do I have to memorize that Array of SubClass is not equal to Array of SuperClass in Java but how come it allows Line 1 is also a big doubt
在Java中,每个对象(包括数组)都有一个在构造时确定的类型,例如使用 new
运算符。这种类型永远不会改变。
变量仅包含对对象的引用。想想遥控器。您可以使用具有更广泛类型的变量来引用对象,即对象的超类或接口的类型。但这不会改变对象本身的类型。
因此,当您调用可重写方法时,您将始终调用对象实际类型的最具体方法。此外,如果对象的实际类型兼容,则类型转换将成功。变量的引用类型并不能说明类型转换是否会成功,否则我们根本不需要运行时检查¹。
当你初始化一个变量时
BaseClass[] myNextArray = new NextClass[6];
对象的实际类型是NextClass[]
,因此,后续类型转换为NextClass[]
可以成功。相反,使用
BaseClass[] myNextArray2 = new BaseClass[6];
对象的实际类型是 BaseClass[]
,因此,类型转换为 NextClass[]
将失败。
请注意,可以更改引用变量以使其指向不同的对象,因此将引用转换为特定类型是否会成功也可能会发生变化。
BaseClass[] myNextArray = new NextClass[6];
NextClass[] nextArray = (NextClass[]) myNextArray; // succeeds
myNextArray = new BaseClass[6]; // let myNextArray refer to a different object
nextArray = (NextClass[]) myNextArray; // will fail
¹ 该规则的唯一例外是编译器将拒绝某些类型转换,这些类型转换可以在编译时证明是不可能成功的,例如尝试将 Integer
转换为 String
.
我正在准备 Java 认证考试,当涉及到多态性、继承、重载、覆盖、泛型以及转换时,很少有情况会变得非常复杂。
我无法理解下面提到的这些示例:
// Tree is the base class
class Tree {
String type = "unknown";
String getTreeString() {
return "Tree";
}
}
// DeciduousTree is a subclass of Tree
class DeciduousTree extends Tree {
String type = "deciduous";
@Override
String getTreeString() {
return "Leafy Tree";
}
}
// FruitTree is a subclass of Tree
class FruitTree extends Tree {
String type = "fruit";
@Override
String getTreeString() {
return "Fruit Tree";
}
}
public class UpcastExamples {
public static void main(String[] args) {
UpcastExamples upex = new UpcastExamples();
// Create two specific trees
Tree tree = new Tree();
Tree mapleTree = new DeciduousTree();
Tree appleTree = new FruitTree();
// we upcast deciduousTree to its parent class
Tree genericTreeMaple = (Tree) mapleTree;
Tree genericTreeApple = (Tree) appleTree;
Tree genericTreeTree = (Tree) tree;
// Print mapleTree's type
System.out.println("Tree type = " + mapleTree.type);
// Let's upcast to use the generic Tree's type..
System.out.println("Tree type = " + (genericTreeMaple.type));
// Print Fruit Tree's type
System.out.println("Tree type = " + appleTree.type);
// Upcasting to pass object as a parameter
upex.printTreeType(genericTreeTree);
upex.printTreeType(genericTreeMaple);
upex.printTreeType(genericTreeApple);
upex.printTreeType(tree);
upex.printTreeType(mapleTree);
upex.printTreeType(appleTree);
}
public void printTreeType(Tree tree) {
System.out.println("Tree type = " + tree.getTreeString());
}
}
我希望这些 upex.printTreeType(genericTreeMaple);upex.printTreeType(genericTreeApple);
打印 Tree
因为它们被升级到 Tree(Base Class) 但不知何故它抓住了它的方法 child classes(我知道它们被覆盖了)但是通过方法重载实现时是一样的
Animal genericDog = new Dog();Animal genericCat = new Cat();
将坚持 parent 的 class 的方法。
我试着这样记住 parentClass p = new childClass() 将始终引用 parent[=27= 的方法] 但它似乎在重写和向上转换期间失败了。
另外,下面还有一些我看不懂的地方,我不想死记硬背
Here BaseClass class is the parent class
And NextClass inherits the BaseClass
BaseClass[] myNextArray = new NextClass[6];
BaseClass[] myNextArray2 = new BaseClass[6];
//Allows this:
NextClass[] nextArray = (NextClass[]) myNextArray; //Line 1
//But doesn't allows this:
NextClass[] nextArray2 = (NextClass[]) myNextArray2;
Do I have to memorize that Array of SubClass is not equal to Array of SuperClass in Java but how come it allows Line 1 is also a big doubt
在Java中,每个对象(包括数组)都有一个在构造时确定的类型,例如使用 new
运算符。这种类型永远不会改变。
变量仅包含对对象的引用。想想遥控器。您可以使用具有更广泛类型的变量来引用对象,即对象的超类或接口的类型。但这不会改变对象本身的类型。
因此,当您调用可重写方法时,您将始终调用对象实际类型的最具体方法。此外,如果对象的实际类型兼容,则类型转换将成功。变量的引用类型并不能说明类型转换是否会成功,否则我们根本不需要运行时检查¹。
当你初始化一个变量时
BaseClass[] myNextArray = new NextClass[6];
对象的实际类型是NextClass[]
,因此,后续类型转换为NextClass[]
可以成功。相反,使用
BaseClass[] myNextArray2 = new BaseClass[6];
对象的实际类型是 BaseClass[]
,因此,类型转换为 NextClass[]
将失败。
请注意,可以更改引用变量以使其指向不同的对象,因此将引用转换为特定类型是否会成功也可能会发生变化。
BaseClass[] myNextArray = new NextClass[6];
NextClass[] nextArray = (NextClass[]) myNextArray; // succeeds
myNextArray = new BaseClass[6]; // let myNextArray refer to a different object
nextArray = (NextClass[]) myNextArray; // will fail
¹ 该规则的唯一例外是编译器将拒绝某些类型转换,这些类型转换可以在编译时证明是不可能成功的,例如尝试将 Integer
转换为 String
.