Java super.getClass() 陷阱

来源:互联网 发布:windows私有云 编辑:程序博客网 时间:2024/04/25 22:45

看到Java笔试题中有一道关于super的题,题目如下:下面程序的输出结果是多少?

import java.util.Date;public class Test extends Date {    public static void main(String[] args) {        new Test().test();    }     public void test(){        System.out.println(super.getClass().getName());        System.out.println(this.getClass().getName());    }}
很奇怪,结果都是Test 

有人这样作答(第一种观点):

在test方法中,直接调用getClass().getName()方法,返回的是Test类名,由于getClass()在Object类中定义成了final,子类不能覆盖该方法,所以,在 test方法中
调用getClass().getName()方法,其实就是在调用从父类继承的getClass()方法,等效于调用super.getClass().getName()方法,所以,super.getClass().getName()方法返回的也应该是Test。
这个好像解释不通,好像是用结论来推原因,不能因为定义成final的就都得到的是同一个东西,因为getClass是这样定义的:

public final native Class<?> getClass();
而并不是

public final String getClass(){    return “Test”;};
所以,单靠final解释不通。

有人是这样解释的(第二种观点):

通过查阅Object类的getClass方法的API文档,发现,是这样解释的:

返回此 Object 的运行时类。返回的 Class 对象是由所表示类的 static synchronized方法锁定的对象

注释如下:

    /**     * Returns the runtime class of this {@code Object}. The returned     * {@code Class} object is the object that is locked by {@code     * static synchronized} methods of the represented class.     *     * <p><b>The actual result type is {@code Class<? extends |X|>}     * where {@code |X|} is the erasure of the static type of the     * expression on which {@code getClass} is called.</b> For     * example, no cast is required in this code fragment:</p>     *     * <p>     * {@code Number n = 0;                             }<br>     * {@code Class<? extends Number> c = n.getClass(); }     * </p>     *     * @return The {@code Class} object that represents the runtime     *         class of this object.     * @see    Class Literals, section 15.8.2 of     *         <cite>The Java&trade; Language Specification</cite>.     */    public final native Class<?> getClass();
仔细想想,发现这种观点靠谱,这样解释能解释的通,但还有一点不太明白,为什么super.getClass().getName()和this.getClass().getName()得到的结果一样呢,那么super的做用是什么呢?问题来了。

为此,有人查了super的含义,说super不是超类的引用,因为不能使用super.super.getClass()而是表示在子类中调用父类的方法或属性而已,并且给出例子:

class B extends A{    public void print(){        System.out.println(super.getClass());        //调用A类中的getclass()方法,A是Object的子类,A中的getClass()是Object中的,运行时期的实例是B类,所以输出的依然是Class B        System.out.println(this.getClass());         //调用B类中的getclass()方法,此方法从A继承的,A从Object继承的,运行时期的实例是B类,所以输出的是Class B    }}

上面的super.getClass()和this.getClass()都是调用的Object中的getClass(),而super.getClass()和this.getClass()都是通过实例化B类,调用print(),从而调用这两个方法,运行时期的类都是B,Object中的getClass()返回的是运行时期的类名,所以输出都是Class B


通过super引出的例子作为总结,还是比较清楚的,个人认为此题的考点在于对java的API文档是否熟悉,如果知道getClass是final的并且得到的是被锁定的运行时类,那么此问题就知道答案了,刚好super在这里起误导作用,导致最后答错。


通过这道题还是能学到不少东西的,首先是final的作用,其次是被锁定的运行时类,最后就是super的作用啦。


本人结合网上观点加个人分析写了这篇文章,如有观点错误请留言指正。

0 0
原创粉丝点击