你的位置:首页 > Java教程

[Java教程]super和this


关于super和this有一个奇怪的现象:
例1:
class grandfather{  String name="grandfather";}class father extends grandfather{  String name="father";  void show(){    System.out.println("father.show-->"+this.name+"--"+super.name);  }}class son extends father{   void rs(){    super.show();    this.show();  }}public class super_this2 {  public static void main(String[] args) {    son s=new son();    s.rs();  }} 


运行结果:
father.show-->father--grandfather
father.show-->father--grandfather


使用super.show()和使用this.show()输出的结果是一样的。存在这种现象的还有这种现象还有super.getClass()和this.getClass()等。

例2:
public class super_this2{  public static void main(String[] args) {    new super_this2().test();  }  public void test(){    System.out.println(super.getClass());    System.out.println(this.getClass());  }} 





运行结果: 

class super_this2
class super_this2

 
现在我们分析这个现象。
1.在例1的子类中覆盖show()
例3:

class grandfather{  String name="grandfather";}class father extends grandfather{  String name="father";  void show(){    System.out.println("father.show-->"+this.name+"--"+super.name);  }}class son extends father{  void show(){    System.out.println("son.show-->"+this.name+"--"+super.name);  }  void rs(){    super.show();    this.show();  }}public class super_this2{  public static void main(String[] args) {    son s=new son();    s.rs();  }} 



运行结果:



father.show-->father--grandfather
son.show-->father--father

这说明
A.super.方法/变量调用的确实是父类的方法/变量;this.方法/变量调用的确实是当前对象的方法/变量
 
2.而如果子类没有覆盖show()时,子类输出结果和父类一样,比如例1,再比如下面的例子:
例4:

public class Test2 {  public static void main(String[] args) {    ch c=new ch();    c.m6();    c.m7();    c.m8();    }  static class fa{    final void m6(){      System.out.println("father's m6");    }    static void m7(){      System.out.println("father's m7");    }    void m8(){      System.out.println("father's m8");    }  }  static class ch extends fa{    void m8(){      System.out.println("child's m8");    }   } }




运行结果:
father's m6
father's m7
child's m8


这里,m6,m7,m8都被继承了,然后m6,m7没有被覆盖,输出的是父类的结果。m8被重写输出子类的结果。

这说明:
B.如果子类没有重写或隐藏父类的某个方法和变量,那么子类调用继承的方法或变量来自父类。

所以A和B综合的结果是:AB.super.方法/变量调用的确实是父类的方法/变量;this.方法/变量调用的确实是当前对象的方法/变量,但如果this所在对象没有重写或隐藏父类的方法或变量,那么它调用的继承来的方法或变量来自父类
3.如果在例1的son类中添加 String name="son";
例5:

class grandfather{  String name="grandfather";}class father extends grandfather{  String name="father";  void show(){    System.out.println("father.show-->"+this.name+"--"+super.name);  }}class son extends father{  String name="son";//隐藏father类的name属性  void rs(){    super.show();    this.show();  }}public class super_this2{  public static void main(String[] args) {    son s=new son();    s.rs();  }} 



运行结果和例1一样:


father.show-->father--grandfather
father.show-->father--grandfather  

但如果像下面这样不隐藏而直接修改name属性
例6:
class grandfather{  String name="grandfather";}class father extends grandfather{  String name="father";//  void show(){    System.out.println("father.show-->"+this.name+"--"+super.name);  }}class son extends father{//  String name="son"; // 去掉  public son(){    name="son";//不隐藏父类的name , 在构造方法中直接修改  }  void rs(){    super.show();    this.show();  }}public class super_this2{  public static void main(String[] args) {    son s=new son();    s.rs();  }} 



运行结果:



father.show-->son--grandfather
father.show-->son--grandfather  

这说明:
C.隐藏变量不会对父类变量产生影响,但是对继承来的变量进行修改会对父类的变量产生直接影响。

现在你把例6的father类中的 String name="father"去掉试试:
class grandfather{  String name="grandfather";}class father extends grandfather{//  String name="father";// 去掉  void show(){    System.out.println("father.show-->"+this.name+"--"+super.name);  }}class son extends father{//  String name="son"; // 去掉  public son(){    name="son";  }  void rs(){    super.show();    this.show();  }}public class super_this2{  public static void main(String[] args) {    son s=new son();    s.rs();  }}



运行结果:

father.show-->son--son
father.show-->son--son

原因正如C所说的,String name="father"隐藏了爷爷类的String name="grandfather",所以后面修改name="son"不会对爷爷类产生影响,现在去掉隐藏后,对继承的name属性的修改就会影响爷爷类的name属性。

 
4.提2个问题:(1)方法体里面的this和super与调用它们对象是什么关系,(2)this和super与方法体里面的this和super是什么关系?
即这里son对象调用了superthissuperthis调用了superthis,那么对象ssuperthis是什么关系?supersuper,this是什么关系?thissuper,this是什么关系?
class grandfather{  String name="grandfather";  public String toString(){    return "grandfather toString";  }  public static String toString2(){    return "grandfather static toString";  }}class father extends grandfather{  String name="father";  void show(){    System.out.println("father.show-->"+this.name+"--"+super.name);    System.out.println("father.show-->"+this.toString()+"--"+super.toString());    System.out.println("father.show-->"+this.toString2()+"--"+super.toString2());  }  public String toString(){    return "father toString";  }  public static String toString2(){    return "father static toString";  }}class son extends father{String name="son";  void rs(){    super.show();    System.out.println("===========================");    this.show();  }  public String toString(){    return "son toString";  }  public static String toString2(){    return "son static toString";  }}public class super_this2{  public static void main(String[] args) {    son s=new son();    s.rs();  }}



运行结果
father.show-->father--grandfather
father.show-->son toString--grandfather toString
father.show-->father static toString--grandfather static toString
===========================
father.show-->father--grandfather
father.show-->son toString--grandfather toString
father.show-->father static toString--grandfather static toString  



 
D.外部的super和this只能决定程序调用的是父类的还是子类的,不会对它们方法体里面的super和this产生影响,super指所在类的父类,使用super将决定调用所在类的父类的方法,this则分两种情况,1.变量和静态方法(static),priavate方法,fianl方法,作为构造方法使用,编译期就确定this为所在类的对象,2.其他方法this在运行期间确定为运行的对象。所以综合AB结果是:ABD.外部的super和this只能决定程序调用的是父类的还是子类的,不会对它们方法体里面的super和this产生影响,super指所在类的父类,使用super将决定调用所在类的父类的方法,即super.方法/变量调用的是所在类父类的方法/变量;this则分三种情况,1.变量和静态方法(static),priavate方法,fianl方法以及它作为构造方法使用时,编译期就确定this所在类的对象,2.其他方法在运行期间确定为运行的对象。3.确定this所指对象后,如果该对象没有重写或隐藏父类的方法或变量,那么它调用的继承来的方法或变量来自父类。
 
总之super和this的法就是找到它们所指的对象,然后调用这个对象的方法,ABD说的就是super和this所指的对象,然后怎么调用这个对象的方法。
套用在上面的例子:
1.super和this只能决定程序调用的是父类的还是子类的show(),superthis不影响superthis。show()是普通方法,所以this确定为son对象,所以this.show()指son的show()方法,但是son没有覆盖show()方法,所以这个show()来自father,然后super所在类的父类也是father,所以super.show()也来自father。即superthis都调用了父类的show()方法。
2.然后this.name和this.toString2()都是编译期间就确定this为所在的对象,所以name和toString2是fanther的属性和方法,父类也存在name和toString2();this.String()是普通方法,确定为运行的对象son
所以输出:
father.show-->father--grandfather
father.show-->son toString--grandfather toString
father.show-->father static toString--grandfather static toString

3.在1中superthis都调用了父类的show()方法,2super.show()和this.show()都按照2里面的方式一样运行,所以super.show()和this.show()输出结果一样(superthis不影响superthis)
 
总结:
外部的super和this只能决定程序调用的是父类的还是子类的,不会对它们方法体里面的super和this产生影响,super指所在类的父类,使用super将决定调用所在类的父类的方法,即super.方法/变量调用的是所在类父类的方法/变量;this则分三种情况,1.变量和静态方法(static),priavate方法,fianl方法以及它作为构造方法使用时,编译期就确定this所在类的对象,2.其他方法在运行期间确定为运行的对象。3.确定this所指对象后,如果该对象没有重写或隐藏父类的方法或变量,那么它调用的继承来的方法或变量来自父类。

.隐藏变量不会对父类变量产生影响,但是对继承来的变量进行修改会对父类的变量产生直接影响。

 
最后看一道题:
class father{  void show(){    System.out.println("father getClass-->"+this.getClass()+"--"+super.getClass());    System.out.println("father getSuperclass-->"+this.getClass().getSuperclass()+"--"+super.getClass().getSuperclass());  }}class son extends father{  void rs(){    super.show();    System.out.println("===========================");    this.show();  }}public class super_this3{  public static void main(String[] args) {    son s=new son();    s.rs();  }} 



father getClass-->class son--class son
father getSuperclass-->class father--class father
===========================
father getClass-->class son--class son
father getSuperclass-->class father--class father



主要是因为super.getClass()返回的是son.class,然后son.class.getName()输出son。
getClass是final方法,this.getClass肯定来自父类。getClass的源码:
Java_java_lang_Object_getClass(JNIEnv *env, jobject this){  if (this == NULL) {    JNU_ThrowNullPointerException(env, NULL);    return 0;  } else {    return (*env)->GetObjectClass(env, this);  }}



this指正在运行的对象。所以getClass返回son.class

 
文章原创,谢绝转载,欢迎指正。