为什么在调用子类的特定方法时必须强制转换对象?

时间:2017-04-02 21:11:17

标签: java casting instantiation

所以,例如,

Person p = New Person()

Person z = New Adult()

假设Adult Class有自己的方法叫做drive(),为什么我不能这样做:

z.drive()

我知道这不起作用,但这背后的逻辑是什么?当您说:Person z = New Adult()时,您是不是指定它是Adult实例?

3 个答案:

答案 0 :(得分:2)

"逻辑"它背后不起作用是因为Java的设计工作方式。 Java是一种静态类型的语言,这意味着每个变量在编译时都具有声明的类型。 Java也是强类型,这意味着可以保留的值和支持的操作仅限于声明的类型。此强制执行称为type safety

static type checking的优点是编译器会阻止您分配不兼容的类型或调用不可用的方法。可以在编译时和运行时捕获错误。

尝试搜索"强与弱打字"这将提供更多细节,论点和方法的优点/缺点。

答案 1 :(得分:0)

你问这个,我引用:

  

当你说:Person z = New Adult()时,你不指定它是一个   成人实例?

不,恰恰相反,更确切地说:

//Main.java, first version.
class Person { 
    public void drive() {
        System.out.println("Person.drive");
    }
}

class Adult extends Person {

    @Override 
    public void drive() {
        System.out.println("Adult.drive");
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person();
        p.drive();  // Person.drive

        Person a = new Adult();
        a.drive();  // Adult.drive
    }
}

Second Variation,这次Person没有drive()方法:

//Main.java, second version.
class Person {}

class Adult extends Person {

    // NO overriding here ..
    public void drive() {
        System.out.println("Adult.drive");
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Adult(); // 1

        // Now this cast is needed:
        Adult  a = (Adult) p;   // 2

        a.drive();  // Adult.drive(), as before  // 3
    }
}

将这两个独立的程序分别放在Main.java中,编译并运行。

让我们考虑第二个版本。看到标有// 1和// 2的行。 在// 1中发生的事情是所谓的成人类切片。 Adult是Person的扩展,因此有权声明比Person对象更多的内存。但是,您将Person分配给Adult对象,因此不会对较大的Adult对象的所有内存进行初始化

因此,Jave敦促您将人员转移到// 2中的真实成人对象,以便向您展示您知道您正在做什么。只允许然后在// 3中调用a.drive()。

希望,这有助于澄清一些事情。

问候,Micha

答案 2 :(得分:0)

  

当您说:Person z = New Adult()时,您是不是指定它是Adult个实例?

您正在创建Adult对象,但声明Person z表示允许变量z引用任何类型的人,而不是只是一个成年人。你可以在下一行写下z = new Child()

当您在z上调用方法时,Java会检查它对于可以引用的变量的所有对象是否有效。它不会分析前面的代码来试图找出它实际上 所引用的特定类型,因为在大多数情况下这是不可能的。 (例如,变量可以作为方法参数传入,或者可以根据Adult语句设置为Childif。)可能是保证变量将引用特定类的特定情况,但Java语言不会特别处理这些情况。如果变量是使用Person类型声明的,则只能在其上调用Person方法。

如果你写Adult z = new Adult(),那么你可以拨打z.drive(),因为该变量只能保证成人,而不是孩子。