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