Java 在toString()方法中使用getClass().getName()
我定义了以下类:Java 在toString()方法中使用getClass().getName(),java,polymorphism,Java,Polymorphism,我定义了以下类: class BaseClass { public String toString() { return "I am a: " + getClass().getName(); } } class DerivedClass { public String toString() { return super.toString(); } } 在main()函数中,我有以下代码: BaseClass b
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()
到底是如何工作的?在我对toString()
的DerivedClass重写中,我调用了super.toString()
,它似乎应该实际返回“我是:基类”,因为我们正在父类上调用toString()
我怀疑这可能与我的基类toString()
利用了getClass().getName()
有关,因此当我通过子类对象调用它时,Java一定在检测我的实际对象类型-但我不知道它如何知道如何做到这一点
如果这听起来像是一个noob问题,很抱歉,但我仍然在思考多态性的概念。如果有人能解释为什么它是这样工作的,我将非常感谢您的见解。getClass()
是一种多态方法。它返回调用它的对象的实际具体类。由于d
id类型为DerivedClass
,其getClass()
方法返回DerivedClass.class
如果方法实现是正确的,您将得到预期的结果
return "I am a: " + BaseClass.class.getName();
getClass()
是一种多态方法。它返回调用它的对象的实际具体类。由于d
id类型为DerivedClass
,其getClass()
方法返回DerivedClass.class
如果方法实现是正确的,您将得到预期的结果
return "I am a: " + BaseClass.class.getName();
想象一下你的课程是这样的:
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;
}
}
类基类{
@凌驾
公共字符串toString(){
返回“我是一个:”+getClass().getName();
}
公共类getClass(){
返回BaseClass.class;
}
}
类DerivedClass扩展了基类{
@凌驾
公共类getClass(){
返回DerivedClass.class;
}
}
由于重写的工作方式,getClass()
在DerivedClass
的实例上调用时,即使从超类基类调用,也将始终返回DerivedClass.class
。调用super.toString()
不会改变这一点,实际上完全没有必要,因为超类实现是默认继承的
请注意,这只是调用getClass()
时可以预期的演示。在现实生活中,getClass()
实际上是一种最终本机方法。重写它是不可能或不必要的。想象一下您的类是这样的:
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;
}
}
类基类{
@凌驾
公共字符串toString(){
返回“我是一个:”+getClass().getName();
}
公共类getClass(){
返回BaseClass.class;
}
}
类DerivedClass扩展了基类{
@凌驾
公共类getClass(){
返回DerivedClass.class;
}
}
由于重写的工作方式,getClass()
在DerivedClass
的实例上调用时,即使从超类基类调用,也将始终返回DerivedClass.class
。调用super.toString()
不会改变这一点,实际上完全没有必要,因为超类实现是默认继承的
请注意,这只是调用getClass()
时可以预期的演示。在现实生活中,getClass()
实际上是一种最终本机方法。覆盖它是不可能或不必要的。您的第一个问题是:
系统输出打印Ln(d);//不知道为什么/如何工作
这是一个好问题!毕竟,您正在将println
方法的引用d
传递给DerivedClass
的一个实例。为什么这会导致实际调用名为toString()
的方法
这个问题的答案在Javadoc中找到了相应的println
方法。编译器(javac
)正确编译您的代码,表示您有兴趣调用接受对象的println
方法。请注意,println是一个重载方法,编译器必须根据传递的参数解析正确的方法。在这种情况下,该方法将解析为以下状态:
打印一个对象,然后终止该行。此方法首先调用String.valueOf(x)以获取打印对象的字符串值,然后调用print(String)和println()
然后访问String.valueOf()
方法并查看:
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
宾果!这将关闭第一个循环,要么调用基类
的toString()
,要么调用派生类
调用d
的getClass()
的实际原因与此
引用的值有关。您可能知道,Java中的每个实例方法(如toString()
one)除了声明的参数外,还接收一个名为this
引用的不可见参数。在这种特殊情况下,由于this
引用指向d
,因此所有方法都在该引用上调用。d
的类别显然是DerivedClass
您的第一个问题是:
系统输出打印Ln(d);//不知道为什么/如何工作
这是一个好问题!毕竟,您正在将println
方法的引用d
传递给DerivedClass
的一个实例。为什么这会导致实际调用名为toString()
的方法
这个问题的答案在Javadoc中找到了相应的println
方法。汇编