Java 子类的对象无法调用其自己的方法

Java 子类的对象无法调用其自己的方法,java,inheritance,casting,extends,upcasting,Java,Inheritance,Casting,Extends,Upcasting,如果c是ChildClass对象,那么为什么它不能调用ChildClass的方法呢? 比如: 特别是: Object s=new StringBuffer(); 这里s是StringBuffer的对象,但是s.append(null)是编译时错误。为什么会这样?因为编译器不知道引用s将在运行时引用StringBuffer的实例,而Java是因为编译器不知道引用s将在运行时引用StringBuffer的实例,而Javaisc被声明为父类。因此,编译器只知道它是它的父类或某个子类。假设在某个地方重

如果
c
ChildClass
对象,那么为什么它不能调用
ChildClass
的方法呢? 比如:

特别是:

Object s=new StringBuffer();

这里
s
StringBuffer
的对象,但是
s.append(null)
是编译时错误。为什么会这样?

因为编译器不知道引用
s
将在运行时引用
StringBuffer
的实例,而
Java
是因为编译器不知道引用
s
将在运行时引用
StringBuffer
的实例,而
Java
is

c
被声明为
父类。因此,编译器只知道它是它的
父类
某个子类。假设在某个地方重新分配了另一条语句
c

c = new SomeOtherChildClass();
这是合法的,因为
SomeOtherChildClass
也是
ParentClass
的子类,并且您已经告诉编译器
c
可以是任何
ParentClass
。现在,如果编译器看到

c.methodOfChildClass();
它如何知道
c
ChildClass
而不是
SomeOtherChildClass
没有该方法

另外,如果您确定
c
确实是一个
ChildClass
,在某个时候,您可以通过向下转换让它调用
ChildClass
方法:

((ChildClass)c).methodOfChildClass();

强制转换将使编译器将
c
视为
ChildClass
;在运行时,程序将检查以确保
c
确实是
ChildClass
,否则程序将抛出
ClassCastException

c
声明为
ParentClass
。因此,编译器只知道它是它的
父类
某个子类。假设在某个地方重新分配了另一条语句
c

c = new SomeOtherChildClass();
这是合法的,因为
SomeOtherChildClass
也是
ParentClass
的子类,并且您已经告诉编译器
c
可以是任何
ParentClass
。现在,如果编译器看到

c.methodOfChildClass();
它如何知道
c
ChildClass
而不是
SomeOtherChildClass
没有该方法

另外,如果您确定
c
确实是一个
ChildClass
,在某个时候,您可以通过向下转换让它调用
ChildClass
方法:

((ChildClass)c).methodOfChildClass();

强制转换将使编译器将
c
视为
ChildClass
;在运行时,程序将检查以确保
c
确实是
ChildClass
,否则程序将抛出
ClassCastException

,您需要强制转换对象以使用实例的方法

Object s = new StringBuffer();
StringBuffer s2 = (StringBuffer) s;
s2.append(null);

尽管是StringBuffer的一个实例,但它仍然是Object类型,并且Object没有method append

您需要强制转换该对象以使用实例的方法

Object s = new StringBuffer();
StringBuffer s2 = (StringBuffer) s;
s2.append(null);

尽管是StringBuffer的一个实例,但它仍然是Object类型,并且Object没有method append

编译器的工作是确保不调用任何与调用它的变量不匹配的方法。为了帮助编译器实现这一点,我们给所有变量一个“类型”。类型可以是“int”之类的基元类型,也可以是类、枚举或接口。如果是类、接口或枚举;然后,该类、接口或枚举中列出的方法就是编译器允许您在该变量上使用的方法

变量的“类型”不一定与变量引用的对象的“类”相同。在您的示例中,类型是
Object
,但类是
StringBuffer
。但是编译器用来检查方法调用是否正常的是类型,而不是类;因为编译器不可能知道您可能使用变量引用的每个对象的类


如果语言不是这样工作的,那么变量没有类型就没有意义了。Javascript就是这样工作的——所有东西都声明为
var
,没有真正的类型系统。当我们说Java是“静态类型”时,我们的意思是我们必须给变量类型,这样做有助于编译器保护我们不滥用变量。

编译器的工作是确保您不调用任何与调用它的变量不匹配的方法。为了帮助编译器实现这一点,我们给所有变量一个“类型”。类型可以是“int”之类的基元类型,也可以是类、枚举或接口。如果是类、接口或枚举;然后,该类、接口或枚举中列出的方法就是编译器允许您在该变量上使用的方法

变量的“类型”不一定与变量引用的对象的“类”相同。在您的示例中,类型是
Object
,但类是
StringBuffer
。但是编译器用来检查方法调用是否正常的是类型,而不是类;因为编译器不可能知道您可能使用变量引用的每个对象的类


如果语言不是这样工作的,那么变量没有类型就没有意义了。Javascript就是这样工作的——所有东西都声明为
var
,没有真正的类型系统。当我们说Java是“静态类型”时,我们的意思是我们必须给变量类型,这样做有助于编译器保护我们不滥用变量。

您必须将对象强制转换为stringbuffer类型,或者您必须像下面这样声明s对象stringbuffer s=new stringbuffer()然后,您可以调用此类的所有方法,您必须将对象强制转换为stringbuffer类型,或者必须声明s对象,如stringbuffer s=new stringbuffer(),然后