在java中,我们可以将超类Object传递给子类引用吗?

Raj*_*kar 10 java polymorphism inheritance reference

在java中,我们可以将超类Object传递给子类引用吗?

我知道这是一个奇怪的问题/几乎不可行,但我想理解这背后的逻辑为什么在java中不允许这样做.

class Employee {
    public void met1(){
        System.out.println("met1");
    }
}


class SalesPerson extends Employee 
{
    @Override
    public void met1(){
    System.out.println("new met1");
    }


    public void met2(){
        System.out.println("met2");
    }

}

public class ReferenceTest {
    public static void main(String[] args) {

        SalesPerson sales = new Employee(); // line 1

        sales.met1();  // line 2

        sales.met2();  // line 3
    }
}
Run Code Online (Sandbox Code Playgroud)

如果Java允许编译第1行会发生什么?问题出在哪里?

欢迎任何输入/链接.

Kon*_*kov 21

如果SalesPerson sales = new Employee();允许您的语句进行编译,这将破坏多态性的原理,这是该语言具有的功能之一.

此外,您应该熟悉编译时类型运行时类型的意思:

变量的编译时类型是它声明的类型,而运行时类型是变量指向的实际对象的类型.例如:

Employee sales = new SalesPerson();  
Run Code Online (Sandbox Code Playgroud)

编译时类型salesEmployee,运行时类型将是SalesPerson.编译时类型定义了可以调用的方法,而运行时类型定义了实际调用期间发生的情况.

让我们假设这句话有效:

SalesPerson sales = new Employee();
Run Code Online (Sandbox Code Playgroud)

正如我所说,编译时类型定义了可以调用哪些方法,因此met2()可以有资格进行调用.同时,Employee班级没有met2(),所以实际的呼叫是不可能的.


awk*_*ksp 6

不。允许这样做是零意义的。

原因是因为子类通常定义额外的行为。如果可以将超类对象分配给子类引用,则在尝试访问实际不存在的类成员时会在运行时遇到问题。

例如,如果允许这样做:

String s = new Object();
Run Code Online (Sandbox Code Playgroud)

你会遇到一些非常糟糕的问题。如果你尝试调用一个String方法会发生什么?运行时会崩溃吗?或者也许会执行空操作?这甚至应该编译吗?

如果运行时崩溃,您可以使用运行时检查来确保您收到的对象实际上包含您想要的方法。但是,您基本上是在实现 Java 类型系统在编译时已经提供的保证。所以说真的,这个“功能”只会让你一开始就不需要编写一堆类型检查代码。

如果执行 no-ops 而不是不存在的方法,那么当您要访问的成员不存在时,确保您的程序按编写的方式运行将是极其困难的,因为任何引用都可能Object在任何时候都是一个。当您独自工作并控制所有代码时,这可能很容易处理,但是当您必须处理其他代码时,这些保证基本上就消失了。

如果您希望编译器进行检查,假设编译器编写者没有追捕您并与您进行严厉的谈话——好吧,您又回到了“正常”行为。再说一次,这只是零收益的大量工作。


长话短说:不,这是不允许的,因为这样做是零意义的,如果语言设计者试图允许他们在造成更多伤害之前被锁定。