如果c
是一个ChildClass
对象,那么为什么它不能调用 的方法ChildClass
?喜欢:
ParentClass c=new ChildClass(); //Here ChildClass extends ParentClass
尤其是:
Object s=new StringBuffer();
这s
是 的对象StringBuffer
,但是s.append(null)
是编译时错误。为什么这样?
如果c
是一个ChildClass
对象,那么为什么它不能调用 的方法ChildClass
?喜欢:
ParentClass c=new ChildClass(); //Here ChildClass extends ParentClass
尤其是:
Object s=new StringBuffer();
这s
是 的对象StringBuffer
,但是s.append(null)
是编译时错误。为什么这样?
编译器的工作是确保您不调用任何与您调用它的变量不匹配的方法。为了帮助编译器,我们给所有变量一个“类型”。类型可能是像“int”这样的原始类型,也可能是类、枚举或接口。如果是类、接口或枚举;那么在该类、接口或枚举中列出的方法就是编译器允许您在该变量上使用的方法。
变量的“类型”不一定与变量引用的对象的“类”相同。在您的示例中,类型是Object
,但类是StringBuffer
。但是编译器使用类型而不是类来检查您的方法调用是否正常;因为不能期望编译器知道您可能使用变量来引用的每个对象的类。
如果语言不以这种方式工作,那么具有类型的变量就没有意义了。这就是 Javascript 的工作方式——一切都被声明为var
并且没有真正的类型系统。当我们说 Java 是“静态类型的”时,我们的意思是我们必须给变量类型,这样做有助于编译器防止我们误用变量。
因为编译器不知道引用s
将StringBuffer
在运行时引用的实例并且Java
是静态类型的语言
c
被声明为ParentClass
. 因此,编译器所知道的只是它是它的一个子类ParentClass
或某个子类。假设在c
某处重新分配了一些其他语句:
c = new SomeOtherChildClass();
这是合法的,因为SomeOtherChildClass
它也是 的子类ParentClass
,并且您已经告诉编译器c
可以是 any ParentClass
。现在,如果编译器看到
c.methodOfChildClass();
它怎么知道那c
是一个ChildClass
而不是一个SomeOtherChildClass
没有那个方法的?
PS如果你确定c
真的是 a ChildClass
,在某些时候,你可以让它ChildClass
通过向下转换来调用一个方法:
((ChildClass)c).methodOfChildClass();
强制转换将导致编译器将其c
视为ChildClass
; 在运行时,程序将检查以确保c
确实是 a ChildClass
,否则程序将抛出ClassCastException
.
您需要强制转换对象以使用实例的方法
Object s = new StringBuffer();
StringBuffer s2 = (StringBuffer) s;
s2.append(null);
尽管是 StringBuffer 的一个实例,它仍然是 Object 类型,并且 Object 没有方法 append
你必须将你的对象转换为 stringbuffer 类型,或者你必须像这样声明 s 对象 stringbuffer s =new stringbuffer() 然后你可以调用这个类的所有方法