Sha*_*eep 5 java objectinstantiation
最近我的老师正在讨论使用不同的构造函数来实例化对象.但我真的很困惑.为此,我想了解为什么我得到以下编译错误.
class SuperClass {
void superClass(){
System.out.println("superClass");
}
}
class SubClass extends SuperClass {
void subClass(){
System.out.println("subClass");
}
}
class Call {
public static void main(String args[]){
SuperClass s = new SubClass();
s.superClass();
}
}
Run Code Online (Sandbox Code Playgroud)
当我编译并运行以下代码时,我得到了输出
superClass
Run Code Online (Sandbox Code Playgroud)
但是当我尝试subClass()通过sObject 调用时,我收到以下错误.
damn.java:17: cannot find symbol
symbol : method subClass()
location: class SuperClass
s.subClass();
^
1 error
Run Code Online (Sandbox Code Playgroud)
好吧,根据这个,我可以假设即使我用不同的构造函数实例化对象,只有指定的Object类型被加载到RAM.
但是,当我在这里使用覆盖时,
class SuperClass {
void superClass(){
System.out.println("superClass");
}
}
class SubClass extends SuperClass {
void superClass(){
System.out.println("subClass");
}
}
class Call {
public static void main(String args[]){
SuperClass s = new SubClass();
s.superClass();
}
}
Run Code Online (Sandbox Code Playgroud)
我在子类中调用了方法.这让我对此感到困惑.当我使用不同的构造函数来实例化Object时,任何人都可以解释我在这里发生了什么.
在运行时,JVM 知道您的s变量是“子类”,因此可以调用正确的(覆盖的)方法。
不过,您遇到的问题是在编译时。编译器会尝试验证您的程序以确保您没有犯任何错误。除了你告诉它的类型之外,它不知道变量的类型。
// the Java compiler remembers that there is a variable called 's' and that
// it has the type 'SuperClass'. Note that the compiler does not check the
// actual type of the instance. It just checks to see if the assignment is
// is valid. Since the right side is of type 'SubClass' and the left side
// has the type 'SuperClass' which is a parent of 'SubClass' this assignment
// is valid for the compiler. But it ONLY remembers that 's' is of type
// 'SuperClass' since that is what you told it about 's'.
SuperClass s = new SubClass();
// Here the compiler sees 's' and looks up its type. The type of 's' is
// 'SuperClass' as remembered earlier. javac will no go and look up the
// definition of 'SuperClass' and finds out that 'SuperClass' does not
// have a method with the name 'subClass' so you get a compiler error.
s.subClass();
Run Code Online (Sandbox Code Playgroud)
编译器这样做的原因是,您告诉编译器 ' 是 SuperClass 类型。因此,任何扩展 SuperClass 的分配都是对 's' 的有效分配。理论上,您可以为 's' 分配一个超类。如果编译器不执行此检查,您将能够编写代码来调用可能没有这些方法的对象上的方法,这将导致运行时错误。在运行时随机出现这样的错误比编译器仅检查所有赋值和调用要糟糕得多,因为您可以立即修复这些错误,并且运行时错误有时很难找到和修复。
正如其他人指出的那样,您可以稍后通过强制转换告诉编译器您的 's' 实际上是一个 'SubClass':
((SubClass) s).subClass();
Run Code Online (Sandbox Code Playgroud)
这样你基本上就告诉编译器:“我知道 s 实际上是一个‘子类’,所以请把它当作这一部分的子类”。如果你在某种程度上错了,并且你的 's' 在运行时实际上是一个 'SuperClass',你将得到一个 'ClassCastException',这是一个运行时错误,因为 JVM 不知道此时要做什么。
| 归档时间: |
|
| 查看次数: |
1060 次 |
| 最近记录: |