在toString()方法中使用getClass()。getName()

时间:2016-08-31 20:17:32

标签: java polymorphism

我定义了以下类:

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必须检测我的实际对象类型 - 但我不知道它是怎么知道的......

很抱歉,如果这听起来像一个菜鸟问题,但我仍然围绕着多态的概念。如果有人能够解释为什么它的工作方式如此,我会很感激任何见解。

3 个答案:

答案 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; BaseClasstoString()

调用DerivedClass&#39; d的实际原因与getClass()引用的值有关。您可能知道,除了声明的参数之外,Java中的每个实例方法(如this)都会收到一个名为toString()引用的不可见参数。在此特定情况下,由于this引用指向this,因此将在该引用上调用所有方法。 d显然是d