简体   繁体   English

如何记住混合多态性、Inheritance、重载、覆盖、Generics 以及铸造

[英]How to remember things when it comes to mixture of polymorphism, Inheritance, overloading, overriding, Generics as well as Casting

I was preparing for Java Certification Exam and there are few scenarios which gets very complicated sometimes when to comes to a mixture of polymorphism, Inheritance, overloading, overriding, Generics as well as Casting.我正在准备 Java 认证考试,当涉及到多态性、Inheritance、重载、覆盖、Z0D7BDBF7F4E4F0DC8ED310A01DEE3502 以及铸造的混合时,有时会变得非常复杂。

I am stuck with understanding these examples mentioned below:我坚持理解下面提到的这些例子:

 
// 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());
    }
}

I expected these upex.printTreeType(genericTreeMaple);upex.printTreeType(genericTreeApple);我期望这些upex.printTreeType(genericTreeMaple);upex.printTreeType(genericTreeApple); to print Tree since they are upcasted to Tree(Base Class) but somehow it grabs the methods of its child classes (I know they are overriden) but the same thing when implemented via method overloading then Animal genericDog = new Dog();Animal genericCat = new Cat();打印Tree因为它们被向上转换为 Tree(Base Class) 但不知何故它抓住了它的子类的方法(我知道它们被覆盖了)但是当通过方法重载实现时同样的事情然后Animal genericDog = new Dog();Animal genericCat = new Cat(); will hold on to the method of the parent's class.将坚持父母的class的方法。

I tried to remember like this parentClass p = new childClass() will always refer methods of parentClass but it seems to fail during overriding and upcasting.我试图记住这样的 parentClass p = new childClass() 将始终引用 parentClass 的方法,但在覆盖和向上转换期间似乎失败了。

Also, there are few other things mentioned below that I could not understand, I don't just want to memorize stuffs.另外,下面提到的其他一些我看不懂的东西,我不只是想记住一些东西。

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

In Java, each object (which includes arrays) has a type that is determined upon construction, eg using the new operator.在 Java 中,每个 object(包括数组)都有一个在构造时确定的类型,例如使用new运算符。 This type never changes.这种类型永远不会改变。

Variables only contain references to objects.变量只包含对对象的引用 Think of a remote control.想想遥控器。 You can refer to an object using a variable having a broader type, ie the type of a superclass or interface of the object.您可以使用具有更广泛类型的变量来引用 object,即 object 的超类或接口的类型。 But this doesn't change the type of the object itself.但这不会改变 object 本身的类型。

Therefore, when you invoke an overridable method, you will always invoke the most specific method of the object's actual type.因此,当您调用可重写方法时,您将始终调用对象实际类型的最具体的方法。 Further, a type cast will succeed if the object's actual type is compatible.此外,如果对象的实际类型兼容,则类型转换将成功。 The variable's reference type does not tell whether the type cast will succeed, as otherwise, we wouldn't need the runtime check at all¹.变量的引用类型不会告诉类型转换是否会成功,否则,我们根本不需要运行时检查¹。

When you initialize a variable like当你初始化一个变量时

BaseClass[] myNextArray = new NextClass[6];

the object's actual type is NextClass[] , hence, a subsequent type cast to NextClass[] can succeed.对象的实际类型是NextClass[] ,因此,后续类型转换为NextClass[]可以成功。 In contrast, using相反,使用

BaseClass[] myNextArray2 = new BaseClass[6];

the object's actual type is BaseClass[] , hence, a type cast to NextClass[] will fail.对象的实际类型是BaseClass[] ,因此,转换为NextClass[]的类型将失败。

Note that it is possible to change a reference variable to let it point to a different object, so whether casting the reference to a specific type will succeed may change too.请注意,可以更改引用变量以使其指向不同的 object,因此将引用转换为特定类型是否会成功也可能会发生变化。

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

¹ The only exception to the rule is that the compiler will reject certain type casts that can be proven at compile-time to be impossible to succeed, like trying to cast an Integer to a String . ¹该规则的唯一例外是编译器将拒绝某些可以在编译时证明不可能成功的类型转换,例如尝试将Integer转换为String

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM