关于Java:为什么在父方法中返回子类名?

Why is the child Class name returned in a parent method?

我有一个名为Entity的类,它是一个abstract超级类,用于我在整个程序中使用的许多其他对象(例如,Apple类)。

在许多方法中,我通过打印从中打印语句的类名以及实际调试消息来打印调试语句。然而,令我惊讶的是,当我从Apple的一个实例调用继承的方法时,会打印Apple的类名,而不是打印Entity的类名(该方法实际所在的类名)。

为了举一个更容易发布代码片段的相关示例,我这样重写了toString()

1
2
3
4
5
6
7
8
9
public abstract class Entity {

    private String name;

    @Override
    public String toString() {
        return getClass().getSimpleName() +"" + (name != null ? name : super.hashCode());
    }
}

因为我不在Apple类中进一步重写此方法,所以我希望返回字符串的第一部分是Entity,而不是Apple。但是它返回Apple(这实际上很好,它在这个用例中是这样工作的,但仍然有点令人困惑)。

我试图查看Object#getClass()的实现,但由于它被声明为native方法,因此无法实现。

public final native Class getClass();

有人能解释为什么会这样吗?


你打电话给getClass()。它总是返回对与对象的实际执行时间类型相关联的Class对象的引用,而不是调用它的表达式的编译时类型的类。例如:

1
2
Object foo ="this is a string";
Class<?> clazz = foo.getClass();

clazz指的是String类,不是Object类。

您不需要查看getClass()的实现—只需查看文档:

The Class object that represents the runtime class of this object.

注意"运行时"位,如"在执行时确定,而不是在编译时确定"。

在这种情况下,我认为返回toString()结果中的执行时间类名称是完全合理的,但是如果您真的想要Entity类,您可以使用Entity.class代替。