上下铸和下铸在类变量方面有什么区别

在类变量方面,上下加和下放有什么区别?

例如,在下面的程序类中,Animal 只包含一个方法,但 Dog 类包含两个方法,然后我们如何将 Dog 变量转换为 Animal 变量。

如果铸造已经完成,那么我们怎么能用动物的变量来调用狗的另一种方法。

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}

答案 1

上倾是投射到超类型,而下倾是投射到子类型。上抛始终是允许的,但下放涉及类型检查,并且可以抛出 .ClassCastException

在你的例子中,从 a 到 a 的强制转换是向上转换的,因为 is-a .通常,只要两个类之间存在 is-a 关系,就可以进行 upcast。DogAnimalDogAnimal

下沉式投影是这样的:

Animal animal = new Dog();
Dog castedDog = (Dog) animal;

基本上,您正在做的是告诉编译器您知道对象的运行时类型到底是什么。编译器将允许转换,但仍将插入运行时健全性检查,以确保转换有意义。在这种情况下,强制转换是可能的,因为在运行时实际上是一个,即使的静态类型是 。animalDoganimalAnimal

但是,如果您要执行此操作:

Animal animal = new Animal();
Dog notADog = (Dog) animal;

你会得到一个.原因是 因为 的运行时类型是 ,所以当你告诉运行时执行强制转换时,它会看到它实际上不是 a,因此会抛出一个 。ClassCastExceptionanimalAnimalanimalDogClassCastException

要调用超类的方法,您可以执行或通过执行向上转换。super.method()

要调用子类的方法,您必须执行 downcast。如上所述,您通常这样做会带来风险;但是,您可以在执行强制转换之前使用运算符检查对象的运行时类型,这样可以防止:ClassCastExceptioninstanceofClassCastException

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
    // Guaranteed to succeed, barring classloader shenanigans
    Dog castedDog = (Dog) animal;
}

从Java 16开始,可以更简洁地表达下垂,Java 16引入了模式匹配,例如

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog castedDog) {
    // now castedDog is available here as in the example above
}

答案 2

下铸和上铸如下:
enter image description here

上放:当我们想将子类投射到超级类时,我们使用上放(或加宽)。它会自动发生,无需显式执行任何操作。

下放:当我们想将一个超级类投射到子类时,我们使用下倾(或缩小),而下倾在Java中是不可能直接实现的,明确地说我们必须这样做。

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException

自动装箱与投射


推荐