我定义了以下类:
class BaseClass {
public String toString()
{
return "I am a: " + getClass().getName();
}
}
class DerivedClass {
public String toString()
{
return super.toString();
}
}
在我的main()函数中,我有以下代码:
BaseClass b = new BaseClass();
DerivedClass d = new DerivedClass();
System.out.println(b);
System.out.println(d); // not sure why/how this works!
正如预期的那样,当代码运行时,我确实得到了正确的运行时类类型:
I am a: BaseClass
I am a: DerivedClass
我的问题是,在DerivedClass中对toString()
的调用究竟是如何工作的?在我的DerivedClass覆盖toString()
中,我正在调用super.toString()
,它似乎应该实际返回“我是a:BaseClass”,因为我们在父级上调用toString()
类。
我怀疑它可能与我的基类toString()
使用getClass().getName()
这一事实有关,所以当我通过子类对象调用它时,Java必须检测我的实际对象类型 - 但我不知道它是怎么知道的......
很抱歉,如果这听起来像一个菜鸟问题,但我仍然围绕着多态的概念。如果有人能够解释为什么它的工作方式如此,我会很感激任何见解。
答案 0 :(得分:2)
getClass()
是一种多态方法。它返回调用它的对象的实际具体类。由于d
类型为DerivedClass
,因此getClass()
方法会返回DerivedClass.class
。
如果方法实现
,您将得到预期的结果return "I am a: " + BaseClass.class.getName();
答案 1 :(得分:0)
想象一下你的课程看起来像这样:
class BaseClass {
@Override
public String toString() {
return "I am a: " + getClass().getName();
}
public Class<?> getClass() {
return BaseClass.class;
}
}
class DerivedClass extends BaseClass {
@Override
public Class<?> getClass() {
return DerivedClass.class;
}
}
由于覆盖工作的方式,getClass()
在DerivedClass.class
的实例上调用时将始终返回DerivedClass
,即使从超类BaseClass
调用也是如此。调用super.toString()
并不会改变它,实际上完全没有必要,因为默认情况下会继承超类实现。
请注意,这只是演示调用getClass()
时可以期待的内容。在现实生活中,getClass()
实际上是final native
方法。覆盖它是不可能或不必要的。
答案 2 :(得分:0)
你的第一个问题是:
的System.out.println(d); //不确定为什么/如何运作!
这是一个很好的问题!毕竟,您将println
方法的引用d
传递给DerivedClass
的实例。为什么这会导致实际调用名为toString()
的方法?
这个问题的答案在于适用于println
方法的Javadoc。编译器(javac
)正确编译您的代码,表示您有兴趣调用println
的{{1}}方法。请注意,println是重载的方法,编译器必须根据传递的参数解析正确的方法。在这种情况下,该方法解析为println(Object x),其中指出:
打印一个对象,然后终止该行。此方法首先调用String.valueOf(x)来获取打印对象的字符串值,然后表现为调用print(String)然后调用println()。
然后您访问Object
方法并查看:
String.valueOf()
宾果!这会关闭第一个循环,调用public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
&#39; BaseClass
或toString()
。
调用DerivedClass
&#39; d
的实际原因与getClass()
引用的值有关。您可能知道,除了声明的参数之外,Java中的每个实例方法(如this
)都会收到一个名为toString()
引用的不可见参数。在此特定情况下,由于this
引用指向this
,因此将在该引用上调用所有方法。 d
的类显然是d
。