昨天下午去面试的时候遇到一道题,大家看看。
class SuperClass {
SuperClass() throws Exception {
System.out.println(this.getClass().getName());
}
void show() {
System.out.println(super.getClass().getName());
show2();
}
void show2() {}
}public class SubClass extends SuperClass {
SubClass() throws Exception {}
void show() {
super.show();
System.out.println(super.getClass().getName());
}
void show2() {
System.out.println(super.getClass().getSuperclass().getName());
}
public static void main(String args[]) throws Exception {
SuperClass s = new SubClass();
s.show();
}
}先自己做一下,然后再debug看看。我写的答案是:
SuperClass
Object
SuperClass我理解的运行流程是:1. SuperClass s = new SubClass();
首先主线程进入main,此时加载两个.class文件进方法区,当new SubClass()时,在堆区实例化这两个类,依次调用SuperClass()和SubClass()(还有Object)。(SuperClass)
SuperClass() throws Exception {
System.out.println(this.getClass().getName());
}这个this应该是父类的实例啊?(没搞懂!)
打印结果是:SuperClass2. s.show();
应用变量s引用的是SubClass的实例,s.show调用的是子类的覆盖方法show(),(SubClass)
void show() {
super.show();
System.out.println(super.getClass().getName());
}进入方法后,压入方法栈,运行super.show()父类实例的show()方法:(SuperClass)
void show() {
System.out.println(super.getClass().getName());
show2();
}这个super又应该是SuperClass的父类实例(Object的实例)。
打印结果是:Object 然后show2(),这个应该是父类的实例的方法,是个空方法,所以什么都不打印。 最后出栈,运行(SubClass.show()的第2个语句)
System.out.println(super.getClass().getName());
打印结果是:SuperClass实际的运行结果是:
SubClass
SubClass
SuperClass
SubClass
大家来讨论下,这是什么原因?
class SuperClass {
SuperClass() throws Exception {
System.out.println(this.getClass().getName());
}
void show() {
System.out.println(super.getClass().getName());
show2();
}
void show2() {}
}public class SubClass extends SuperClass {
SubClass() throws Exception {}
void show() {
super.show();
System.out.println(super.getClass().getName());
}
void show2() {
System.out.println(super.getClass().getSuperclass().getName());
}
public static void main(String args[]) throws Exception {
SuperClass s = new SubClass();
s.show();
}
}先自己做一下,然后再debug看看。我写的答案是:
SuperClass
Object
SuperClass我理解的运行流程是:1. SuperClass s = new SubClass();
首先主线程进入main,此时加载两个.class文件进方法区,当new SubClass()时,在堆区实例化这两个类,依次调用SuperClass()和SubClass()(还有Object)。(SuperClass)
SuperClass() throws Exception {
System.out.println(this.getClass().getName());
}这个this应该是父类的实例啊?(没搞懂!)
打印结果是:SuperClass2. s.show();
应用变量s引用的是SubClass的实例,s.show调用的是子类的覆盖方法show(),(SubClass)
void show() {
super.show();
System.out.println(super.getClass().getName());
}进入方法后,压入方法栈,运行super.show()父类实例的show()方法:(SuperClass)
void show() {
System.out.println(super.getClass().getName());
show2();
}这个super又应该是SuperClass的父类实例(Object的实例)。
打印结果是:Object 然后show2(),这个应该是父类的实例的方法,是个空方法,所以什么都不打印。 最后出栈,运行(SubClass.show()的第2个语句)
System.out.println(super.getClass().getName());
打印结果是:SuperClass实际的运行结果是:
SubClass
SubClass
SuperClass
SubClass
大家来讨论下,这是什么原因?
因此,super.getClass()等价于this.getClass().
jdk文档里面说:
The Class object that represents the runtime class of this object.
返回的是运行时的实际类型。
SubClass
SupreClass
Object
Superclass
坐等真相!
貌似理解错误~
这个好像是多态,有继承,有重写,父类引用指向子类实例化....
1:SubClass //new SubClass()自动调用父类的无参数构造函数,this.getClass().getName(),这里的this还是指向new出来的那个子类实例
然后就是多态吧,s.show()调用子类对父类重写的show函数,如下:
super.show();//这里调用父类的函数
void show() {
System.out.println(super.getClass().getName()); //这里直接输出第二个值SubClass,我觉得SuperClass s = new SubClass();是实例的对象指向了子类对象,所以还是输出了子类实例化的对象 show2(); //这是输出的第三个值,输出的才是SubClass的真实父类SuperClass }System.out.println(super.getClass().getName()) //第四个输出值和第二个原因一样把我觉得
这个才自学java么多久,错了请大家指出,我会改正,呵呵
getClass()永远是返回实例的实际Class,所以s.super.getClass仍然返回SubClass运行过程应该是这样的 :
1) SubClass (由SuperClass()方法输出)
2) SubClass (SubClass.show() --> SuperClass.show()输出)
3) SuperClass (SubClass.show() --> SuperClass.show() --> SubClass.show2()输出)
这里super.getClass()是SubClass,super.getClass().getSuperClass()是SuperClass
4) SubClass (SubClass.show()输出)
LZ只要能理解以下的代码,就能理解问题的结果了SuperClass sc = new SubClass();
System.out.println(sc.getClass());
SuperClass sc2 = (SupperClass)sc; //强行转换为父类,看看有没有效果?
System.out.println(sc2.getClass());
参考这个帖子的三楼:
http://topic.csdn.net/u/20110612/22/a76763f4-ab32-4a1f-8fa0-608224e0a52b.html按楼主的例子:第一:不管是T1的getClass()还是Date的getClass(),他们都是非覆盖式的从Object继承来的。第二:Object的getClass()方法的释义是:返回此 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.
**/ 释义指出,要返回此Object运行时类,这外当然不可能指Object自己了,否则所有类调用getClass()方法都返回Object.class了。 那到底谁是Object的运行时类呢,不是Object自己,当然就只能是他的儿子、或各种孙子了,到底是谁呢,举个例子:
Date作为直接继承Object的类,作为Object的儿子,如果调用Date.getClass(),返回的是什么呢?在Date中,无论是this.getClass()还是super.getClass(),毫无疑问都指向了Object.getClass()。根据上一段解释,Object.getClass()返回不可能是Object.class,那没得说,只能是Date.class了。 根据上段:new Date()时,Date是Object的运行时类。 同理:根据LZ的例子,new T1()时,运行是类不可能是T1他老子Date,更不会他各种老老子(如Object),只能是自己。 再回到Object.getClass()释义,返回的只能是T1.class第三:如果想要从T1中得到Date.class,可以用T1.getClass().getSuperClass();
我先承认我的基础很差,
super引用的是父类的实例,this引用的是当前自身的实例。
在同一类中,super.getClass()怎么会等价于this.getClass().
而且跟是不是final方法没有关系。
为什么这个this引用的是SubClass的实例?
new SubClass()自动调用父类的无参数构造函数来创建父类的实例(think in java 上说是:当创建一个导出类时,该对象包含了一个基类的子对象),
父类的构造方法:
SuperClass() throws Exception {
System.out.println(this.getClass().getName());
}这个this在父类构造器中,父类会根据方法区的class字节段在堆区生成字节块用以代表父类的实例,然后初始化成员变量后调用构造器,而此时的this.getClass()怎么不是the runtime class of SuperClass
你的SubClass类里面定义getClass()了没?没有吧!
那这个getClass()是哪里的呢?当然是继承来的!
从那里继承来的呢?从老祖宗Object继承来的。老祖宗那里就明确说了:孩子们,你们听着,getClass()这个方法你们都可以调用,但是谁也不能给我覆盖掉。你们也没有必要覆盖,到底是哪个儿子还是孙子调用的,运行时,老祖宗我心里明镜似的,肯定会返回给你实际的类型的。
super是子类向上转型的父类代表的引用变量吗?子类show()方法
void show() {
super.show();
System.out.println(super.getClass().getName());
}这个super引用的还是子类的实例,那这个方法会进入死循环。
super返回一个逻辑上被视为父类的实例,目的是让你能通过它访问父类中被重写的方法或被隐藏的字段。
至于getClass方法,从未被重写,所以你用不用super返回的结果都是一样的。
实例怎么会只有一个?
think in java(P129) 上说是:当创建一个导出类时,该对象包含了一个基类的子对象。
在创建子类实例时,会依次创建父类的实例,那不然父类public的成员变量子类是如何访问的。
super实际上引用的是什么?
我的基础确实还很不扎实,麻烦在说一下!
super引用的是父类的实例,this引用的是当前自身的实例。
他们getClass(),当然是返回各自的实例!
实例有N个,每创建一个类就有一个Objet的实例。但是这个实例与运行时类是有区别的。Object的getClass()方法返回的是运行时类,不是实例。JDK源代码中Object.getClass()就是这么解释的。
也就是对应类的class对象,父类在产生实例时会伴随着产生他对应的class对象。所以还是回到老问题:super到底引用的是什么?
假如有这样一个实例:
class Father extends Object{
//......
}
class Son extends Father{
//......
}当在Son中通过Super()引用父亲类的构造方法时,Super表示是就是父类Father当在Son中通过super引用 Father的资源(标记为资源F),资源F分且只分为两种:
一种是Father自己的;
一种是Father他父类Object的,当Father的父类不是Object时,依次类推.所以可以这样理解为Son通过Super引用其父类(包括父类的父类....)的资源
恩,这句话没说错!我查阅了一下JDK Documentation,上面对this和super也没作详细的解释。
只是说super是关键字,及他的3个作用:
use the super keyword to invoke a superclass's constructor.
you can invoke the overridden method through the use of the keyword super.
You can also use super to refer to a hidden field (although hiding fields is discouraged).