回过头来再看的时候真的已经不知道它们分别是什么东西了,JLS上也就只是说它们是关键字。但是它们真正到底是什么呢?
对于super,《The Java Programming Language》上这样说:In field access and method invocation, super acts as a reference to the current object as an instance of its superclass.可以理解为在需要访问the hidden field和进行父类方法调用的时候,super表现为指向作为父类的一个实例的当前对象的一个引用。所以super只是act as a reference,但不是reference,对吗?我们也不可以将super赋给一个父类变量,比如在子类中:Super s = super;(报错)。当我们在构造方法中使用super()或其他形式的时候super又是什么呢?
对于this,JLS上这样表述:When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed.这里:this也只是代表一个引用的值,还是没说this除了是keyword外还是什么,但是又说的this的类型。反正搞得一团乱,下面的代码输出的结果我也不理解:class Super {
}class SubClass extends Super{
    public void foo() {
        System.out.println(this.getClass());
        System.out.println(super.getClass());
    }
}希望大家帮忙解惑,说说它们是什么。怎么使用它们就不用说了,所有的书上都差不多教我们怎么用了。谢谢~

解决方案 »

  1.   

    它们是引用:一个指向当前对象和当前对象的父类对象的引用,也就是对象在内存中的地址每一个对象在内存中都有自己的地址,每一个对象也自己对应着一个自己父类对象(有几个子类对象就有几个父类对象,当然这父类对象在内存中同样有地址)。所以this 和 super 就是子类实例对象的地址和子类父类对象的地址。
      

  2.   

    补充,当一个对象建立完毕,那么它的this和super就产生了也就是说可以使用了!ps.我为什么不能编辑自己的帖子啊
      

  3.   

    楼主:以下是你的话
    “我们也不可以将super赋给一个父类变量,比如在子类中:Super s = super;(报错)。当我们在构造方法中使用super()或其他形式的时候super又是什么呢?”我来回答:首先:this和super是一个特殊的变量,它存储的是引用,这个变量的产生又依赖对象实例的产生(说它们特殊是因为这两个变量是jvm帮我们完成的,我们根本不需要自己去定义也无法去定义。)你这里“Super s = super” 首先 “Super s”java编译器会把它理解为声明一个叫s 的Super类的引用
    显然你没定义自然找不到,加入你定义了一个Super的类,那好!我们看 “= super”,这里面的super java编辑器一定会把它当成是 关键字super,关键字super能这样用吗?你可能会说他存储的是引用啊,那我把一个引用赋给一个变量可以吧!问题是:首先:你定义的类Super的引用应该是new Super()来产生的,跟这个关键字super里的引用是八辈子打不到一块去的。
    第二,你这super我们已经说过了他存在的意义2楼,而且它依赖于先产生对象实例,这也非常吻合它存在的意义。所以你这句 "Super s = super"可以说是 “不知道在说什么”。
      

  4.   

    http://blog.csdn.net/ZangXT/archive/2009/09/24/4587985.aspx
      

  5.   

    都是引用,指向同一个内存地址,不一样的是对这两个东西的解释,这要从类的内存布局说起。
    一个class,如果继承于其他类,那么前面的内存部分是父类的东西,后面部分才是自己的,当你访问父类,只要能把this转成父类引用,编译器根本不会意识到目前在操作的是子类,super = (father)this。 upcast,
    为了RTTI,需要downcast,编译器会对这两个类作内部作一些处理,使他们能表现正确的行为,比如多重继承,虚拟继承等,先忽略这些,父类和子类就是一个简单的内存空间堆叠关系,并没有真正“产生”一个父类。
      

  6.   

    class Super {
    }class SubClass extends Super{
        public void foo() {
            System.out.println(this.getClass());
            System.out.println(super.getClass());
        }
    }
    在你这段代码里,
    this就是class SubClass这个类(的对象的引用)
    super就是class Super这个类(的对象的引用)而
    System.out.println(this.getClass());
    System.out.println(super.getClass());
    的执行结果完全看你的用哪个对象在调用getClass()这个方法比如你实例化了一个SubClass的对象sub
    你sub.foo();
    那this.getClass()的结果我相信你完全能理解
    应该是sub这个对象对应的类——SubClass那super.getClass()的结果呢?
    楼主的想法可能是这样——Super
    但是这是不对的,
    因为这里仅仅是在sub这个对象里调用了父类中的getClass()这个方法
    而这个方法的意义是返回你当前对象对应的类
    所以super.getClass()的结果
    应该是sub这个对象(当前对象)对应的类——SubClass至于super()这是构造函数中的特定用法
    表示调用父类的构造函数,
    必须出现(如果出现的话)子类构造函数的第一行
      

  7.   

    学习了。java是解释性的语言,因此this和super不应该是地址。理解为引用可能更自然些
      

  8.   

    对于你那段代码,两个输出结果是一致的,因为继承时,公共方法是会覆盖的,所以父类的getClass与子类的getClass是一样的。
      

  9.   

    两点:1、两者都是引用
    2、两者依赖于对象实例的产生,由jvm完成这套机制。
      

  10.   

    补充,lz的代码两个的结果都是subclass
    getclass返回的是运行时的对象的类,而上述程序运行时的对象是sub,所以都返回sub
      

  11.   

    如果这样呢?class Super {    public void foo() {
            System.out.println(this.getClass());
            System.out.println(super.getClass());
        }}class SubClass extends Super {    public static void main(String[] args) {
            new SubClass().foo();
        }}这个结果还是一样的。说以导致getClass输出结果一致本质原因是 方法的覆盖
      

  12.   

    this 表示当前类的对象,super 表示对父类的某个构造器的调用
      

  13.   

    都是引用  this----当前对象,super ---基类对象(父类对象)
      

  14.   

      
    super调用老子的东东。。
    this就儿子自己玩自己的
      

  15.   

    已经说了super不是引用,还有那么人来强调这点~唉
      

  16.   

    其实不用局限于我给的那两行代码,我只是突然想看看是什么结果然后就写下了~问题的中心还是要围绕super和this这两个关键字到底是什么?如果真的可以认为是reference,我想标准肯定会直接用reference来进行描述而不是用act as和denote the value of a reference~谢谢ZangXT,兄弟写得好深,看不懂,唉~有时候也想过只要知道怎么用就行了管它那么多,就像我们直接new Object();结果一看源码,Object中根本没有Object()这个构造方法,想想如果有会怎么样?哈哈~我们的super()又要被拿出来谈了~只希望能彻底搞清楚,不想局限于某一细节。大家继续吧,要给力啊~
      

  17.   

    super 是指父类对象  super()指父类构造方法,如果有参数,()里加对应的参数。this是自身对象    this()指自身类的构造方法,如果有参数,()里加对应的参数。
      

  18.   

    this就是class SubClass这个类(的对象的引用)
    super就是class Super这个类(的对象的引用)而
    System.out.println(this.getClass());
    System.out.println(super.getClass());
    的执行结果完全看你的用哪个对象在调用getClass()这个方法比如你实例化了一个SubClass的对象sub
    你sub.foo();
    那this.getClass()的结果我相信你完全能理解
    应该是sub这个对象对应的类——SubClass那super.getClass()的结果呢?
    楼主的想法可能是这样——Super
    但是这是不对的,
    因为这里仅仅是在sub这个对象里调用了父类中的getClass()这个方法
    而这个方法的意义是返回你当前对象对应的类
    所以super.getClass()的结果
    应该是sub这个对象(当前对象)对应的类——SubClass至于super()这是构造函数中的特定用法
    表示调用父类的构造函数,
    必须出现(如果出现的话)子类构造函数的第一行
      

  19.   

    super可以调用到父类的属性、方法
    this是当前类的
      

  20.   

    都说的好复杂哦,其实每个对象都有一个名为this 的引用,它指向当前对象本身
    (1)this调用本类中的属性,也就是类中的成员变量。——this.成员变量名(2)this调用本类中的其他方法——this.成员方法名(参数) (3)this调用本类中的其他构造方法——this(参数表) (4)返回对象的值——return thissuper表示父类对象(1)引用父类的成员变量——super.成员变量(2)调用父类的成员方法——super.成员方法名(参数表)(3)调用父类的构造方法——super(参数表)注意!!子类构造方法中的this()和super()调用只能有一个,不能同时使用
      

  21.   

    可以把this当做非static方法的参数,而不是对象的成员。
      

  22.   

    this是当前对象的引用,super是父类对象的引用~
      

  23.   

    this当前类的对象引用
    super父类对象的引用
      

  24.   

    我说点可以吗?其实你们的解释一般看起来所这个样子的,但有的时候会出现问题,我们来看这样一个例子class Sup{
    private int i=2;
    public Sup(){
    this.foo();
    }
    public  void foo(){
    System.out.println(i);
    }

    }
    public class test1 extends Sup{
    private int i=22;
    public test1(){
    //System.out.println("hello");
    i=222;
    }
    public  void foo(){
    System.out.println(i);
    }
    public static void main(String args[]){
    new test1();
    //
    }
    }大家把这个例子跑一遍  希望对你们有所帮助
      

  25.   

    不能简单的说this表示子类  super表示父类
    而是说this表示正在编译的类  
    上面那个文件输出之后会得到0 
      

  26.   

    把这个程序该一下  
    [code=Java0]
    class Sup{
    private int i=2;
    public Sup(){
    this.foo();
    }
    public  void foo(){
    System.out.println(this.i);
    }
    [/code]
      

  27.   

    this指向本类对象
    super指向父类(基类)的对象
      

  28.   

    this携带当前对象的引用(地址) super携带父类对象的引用(地址)
      

  29.   

    楼上们其实都犯了一个错误,其实楼主给出的英文里的说明已经非常明确地说明了,this是一个对象的引用,而super仅仅是一个指示编译器调用超类方法的特有的关键字,这里一定要记住!super不是一个引用,只是一个关键字!很多人犯的错误。
      

  30.   


    return this;可以
    但return super;就不行  是这个原因吗?
      

  31.   

    我发现国产的书籍没他妈几个能看的 书上说的是super携带父类引用
      

  32.   


    同意,我原来也是一直以为super是父类的引用,学习了!!!
      

  33.   

    其实很多时候大家都错误地认为是那样(super指向父类的一个对象,this指向当前对象),然后一直用着也挺爽。我也不太清楚它们到底是什么,根据《The Java programming Language》和JLS:super表现为指向作为父类的一个实例的当前对象的一个引用(感觉有点绕,英文原话我不记得),对于this:When used as a primary expression, the keyword this denotes a value that is a reference to the object for which the instance method was invoked (§15.12), or to the object being constructed.高手可以指出不妥指出或者给出更详尽的解释,让大家彻底搞清楚,而不是仅仅知道怎么去用它们。
      

  34.   

    Java关键字this、super使用总结
     
    一、this
            Java关键字this只能用于方法方法体内。当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是this。因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this,这在“Java关键字static、final使用总结”一文中给出了明确解释。并且this只和特定的对象关联,而不和类关联,同一个类的不同对象有不同的this。下面给出一个使用this的综合实例,以便说明问题:
     
    package org.leizhimin;
    public class Test6 {
     private int number;
     private String username;
     private String password;
     private int x = 100;
     public Test6(int n) {
      number = n;  // 这个还可以写为: this.number=n;
     }
     public Test6(int i, String username, String password) {
      // 成员变量和参数同名,成员变量被屏蔽,用"this.成员变量"的方式访问成员变量.
      this.username = username;
      this.password = password;
     }
     // 默认不带参数的构造方法
     public Test6() {
      this(0, "未知", "空"); // 通过this调用另一个构造方法
     }
     public Test6(String name) {
      this(1, name, "空"); // 通过this调用另一个构造方法
     }
     public static void main(String args[]) {
      Test6 t1 = new Test6();
      Test6 t2 = new Test6("游客");
      t1.outinfo(t1);
      t2.outinfo(t2);
     }
     private void outinfo(Test6 t) {
      System.out.println("-----------");
      System.out.println(t.number);
      System.out.println(t.username);
      System.out.println(t.password);
      f(); // 这个可以写为: this.f();
     }
     private void f() {
      // 局部变量与成员变量同名,成员变量被屏蔽,用"this.成员变量"的方式访问成员变量.
      int x;
      x = this.x++;
      System.out.println(x);
      System.out.println(this.x);
     }
     
     //返回当前实例的引用
     private Test6 getSelf() {
      return this; 
     }
    }
     
    运行结果如下:-----------
    0
    未知

    100
    101
    -----------
    0
    游客

    100
    101
     
            看着上面的例子,说明在什么情况下需要用到this:
            第一、通过this调用另一个构造方法,用发是this(参数列表),这个仅仅在类的构造方法中,别的地方不能这么用。
            第二、函数参数或者函数中的局部变量和成员变量同名的情况下,成员变量被屏蔽,此时要访问成员变量则需要用“this.成员变量名”的方式来引用成员变量。当然,在没有同名的情况下,可以直接用成员变量的名字,而不用this,用了也不为错,呵呵。
            第三、在函数中,需要引用该函所属类的当前对象时候,直接用this。
            其实这些用法总结都是从对“this是指向对象本身的一个指针”这句话的更深入的理解而来的,死记不然容易忘记而且容易搞错,要理解!
     
    二、super
     
            super关键和this作用类似,是被屏蔽的成员变量或者成员方法或变为可见,或者说用来引用被屏蔽的成员变量和成员成员方法。
    不过super是用在子类中,目的是访问直接父类中被屏蔽的成员,注意是直接父类(就是类之上最近的超类)。下面是一个综合运用super的例子,有两个类:一个Father类,一个Father类的子类Son,通过这两个类完全演示了super的用法,一下是代码:
     
    package org.leizhimin;
    public class Father {
     public String v="Father";
     public String x="输出了Father类的public成员变量x!!!";
     
     public Father() {
      System.out.println("Father构造方法被调用!");
     }
     
     public Father(String v){
      this.v="Father类的带参数构造方法!运行了.";
     }
     public void outinfo(){
      System.out.println("Father的outinfo方法被调用");
     } 
     public static void main(String[] args) {
      // TODO 自动生成方法存根
     }
    }
     
    package org.leizhimin;
    public class Son extends Father{
     public String v="Son";
     
     public Son() {
      super();      //调用超类的构造方法,只能放到第一行.
      System.out.println("Son无参数构造方法被调用!");
      //super();      //错误的,必须放到构造方法体的最前面.
     } 
     
     public Son(String str){
      super(str);
      System.out.println("Son带参数构造方法被调用!");
     }
     //覆盖了超类成员方法outinfo()
     public void outinfo(){ 
      System.out.println("Son的outinfo()方法被调用");
     } 
     
     public void test(){
      
      String v="哈哈哈哈!";   //局部变量v覆盖了成员变量v和超类变量v
      
      System.out.println("------1-----");
      System.out.println(v);   //输出局部变量v
      System.out.println(this.v);  //输出(子类)成员变量v
      System.out.println(super.v); //输出超类成员变量v 
      
      System.out.println("------2-----");
      System.out.println(x);   //输出超类成员变量v,子类继承而来
      System.out.println(super.x); //输出超类成员变量v
      
      System.out.println("------3-----");
      outinfo();   //调用子类的outinfo()方法
      this.outinfo();  //调用子类的outinfo()方法
      super.outinfo(); //调用父类的outinfo()方法
     } 
     
     public static void main(String[] args) {
      new Son().test();
      
     }
    }
     
    子类Son运行结果:
     
    Father构造方法被调用!
    Son无参数构造方法被调用!
    ------1-----
    哈哈哈哈!
    Son
    Father
    ------2-----
    输出了Father类的public成员变量x!!!
    输出了Father类的public成员变量x!!!
    ------3-----
    Son的outinfo()方法被调用
    Son的outinfo()方法被调用
    Father的outinfo方法被调用
     
            说明:次例子仅仅为了说明super的用法,实际在设计类的时候一般都尽可能私有(private)化。
     
            通过上面的例子,下面总结一下super的用法:
            第一、在子类构造方法中要调用父类的构造方法,用“super(参数列表)”的方式调用,参数不是必须的。同时还要注意的一点是:“super(参数列表)”这条语句只能用在子类构造方法体中的第一行。
            第二、当子类方法中的局部变量或者子类的成员变量与父类成员变量同名时,也就是子类局部变量覆盖父类成员变量时,用“super.成员变量名”来引用父类成员变量。当然,如果父类的成员变量没有被覆盖,也可以用“super.成员变量名”来引用父类成员变量,不过这是不必要的。
            第三、当子类的成员方法覆盖了父类的成员方法时,也就是子类和父类有完全相同的方法定义(但方法体可以不同),此时,用“super.方法名(参数列表)”的方式访问父类的方法。
     
            this、super的用法也不过这些,只有理解了其中的原理,才不会跌入陷阱!
     
    参考资料
    Thinking in Java
    Java2参考大全
      

  35.   

    super 与 this 就不多说了。楼主的代码我想说一下
    class Super {
    }class SubClass extends Super{
        public void foo() {
            System.out.println(this.getClass());
            System.out.println(super.getClass());
        }
    }你们看看getClass() 是谁的方法。 是Object ,你如果想得到不同的结果就重写这个方法。但这个方法是不能重写的。所以无论你是supper supper supper 多少个继续 调用getClass 都是返回调用此方法的那个对象的运行时类
      

  36.   

    super:父类
    this:本类只是一个引用,没啥特别的,不要想复杂了
      

  37.   

    我觉得这么说lz应该就能理解:1
    一个子类被创建,那这个子类对象在内存中的东西包括“新产生父类对象”加上“自己新定义的东西那一部分”,这样才是一个完整的子类对象。所以说每(创建)一个子类对象都(要创建)包含着一个父类对象。这个子类对象里面的父类对象跟你自己new一个父类对象的区别在哪里呢?本质没区别唯一区别就在:前者已经封装在子类里,它是子类的,别人不能用,而后者是独立的!所以你不能用子类的super去赋值于一个父类声明的引用。你应该自己去new一个独立的父类对象去完成赋值。而且由于引用应该是指能指向完整的一个“独立对象”,而super只是指向子类里的父类对象部分,所以super不能算是一个真正的引用,自然也不能拿它去赋值。
    2
    this引用和super(约等于)引用(子类内部的父类部分的地址)
    this引用跟我用new出来的引用一样,你可以用他来赋值:class A {
        void f(){
            A a = this;
        }
    }这完全没问题。而super不行原因在1已经说了。
    既然有了this指向自身(也就是说它也能指向其自身的父类部分),那为什么还需要super呢?
    那是因为会碰到子类“重写父类成员”的情况,你用this.成员名,总会优先调用子类的,那么父类的总调用不到,于是super就是为了能调用父类被重写的成员而诞生。
      

  38.   

    至于this()是子类构造器 super()是父类构造器,这个我的理解就是一个硬性的规定。
    (同时在方法体里(构造器里也一样)调用跟构造器同名的方法,都会被解读为成员方法而不是构造器)而且用法是:只能是构造器的第一句语句。——2个信息:1.只能在构造器中使用;2. 必须放在第一句
      

  39.   

    super代表的是引用父类中的方法,,而this代表的是子类中重写之后的方法.
      

  40.   

    一定要刨根,那很多"结论"都要推翻。
    先从C++说起,这个能看到机器码。C++里,所有类都会有构造函数,没有的也会给你生成一个默认的(java一样),在语法层面这绝对是正确的,或者说逻辑上正确,实际呢?class Super
    {
    public:
    //Super(){}
    int aa;
    };int main()
    {
    Super su;
    su.aa = 1;
    }赋值语句是为了让编译器生成这个类。反汇编,按道理该有个缺省构造函数,但是什么都没有,程序跑起来堆栈调整完就是
    mov         dword ptr [ebp-4],1
    在某些地方,这种行为称为trivial,c++里大量存在,构造,拷贝等,决不浪费一行机器指令。
    把那行注释去掉,反汇编,能看到call xxx ,push ebp,move ebp,esp 之类熟悉的调用,虽然什么都没干,但是的确跑到一个函数里转了一圈。如果以上还说的过去,那下面这行 
    int n=int(4)
    从语法角度,生成一个int类对象,构造函数参数是4,怎么也该有个调用过程,反汇编,就一行,
    mov         dword ptr [ebp-8],4
    语法和实现是两回事,不看汇编码,语法的完全一样,挑不出毛病;编译器做的过程却不对,结果是对的。回到java,指针是什么,引用是什么,语法角度能争论半天,其实都一样,都是指针。都是指向一个内存的代号。在看内存布局,SubClass实例里,Super内存在前,SubClass的在后,仅此而已,SubClass的引用和SubClass里Super部分的引用都是同一个地方,如果语法支持,这两个可以随便怎么转--虚函数除外。
    剩下就是super到底是什么,其实只是个语法,java编译器根据它生成bytecode而已。
    下面是我这里的foo,两个getClass完全一样,
    public void foo();
         0  getstatic java.lang.System.out : java.io.PrintStream [15]
         3  aload_0 [this]
         4  invokevirtual java.lang.Object.getClass() : java.lang.Class [21]
         7  invokevirtual java.io.PrintStream.println(java.lang.Object) : void [27]
        10  getstatic java.lang.System.out : java.io.PrintStream [15]
        13  aload_0 [this]
        14  invokespecial java.lang.Object.getClass() : java.lang.Class [21]
        17  invokevirtual java.io.PrintStream.println(java.lang.Object) : void [27]
        20  return
    从实现层面解释,super和this指向同一个地方,getClass()得到的是"这个地址"所在类的名称,在此之前,class对象已经建好,所以查询出来都是SubClass的名称。
    bytecode中有这行: local: this index: 0 type: SubClass
    当我在Super和SubClass中都加入一个函数fo,并且SubClass.fo()中写super.fo()
        1  invokespecial Super.fo() : void [34]
    这回直接invoke了,完全就是一个reference的行为.可见是编译器在搞鬼,它正确的解释了语法中的super,却对我们造成了迷惑。所以我认为"super acts as a reference"这句话写的非常精确,不是reference,编译的时候让你以为是个reference
      

  41.   

    这个讨论很精彩.学习了.记得java有四部分组成:java语法,java class文件格式,java api,java虚拟机.我认为单从语法规则的角度可能只有些生硬的规定,知其然不知其所以然.从JLS的角度由于其过于宽松而只有一个非常抽象的规定.
    从jvm的实现的角度,我想楼主和我们能会有一个更清楚的认识
    郑重推荐一本书: inside java virtual machine
      

  42.   

    很多时候自己太去抠一些字眼了~也许就当它们是关键字去用就比较好了。越挖越多,JLS也翻了不少地方,很蛋疼,哈哈
      

  43.   

    看了这么多, 我有想说的话: 
    1.首先,楼主的说法是对的,super不是引用,而是作为一个看似引用的行为。这点大家都说了,没有什么好解释的了。
    2.我也有了一个困惑,就是楼主想得到一个super对象的引用。这时,就要明确一个问题,究竟有几个对象。也就是说只有SubClass这一个对象还是同时有Object,Super,SubClass三个对象。楼主的问题应该只有后者为真的情况下才有意义。那若此,就是说先创建父类的对象,并且要求父类对象与子类无关,完全放在一个独立的内存地址里的。然后,子类会隐含的拥有一个父类对象的引用。如果能搞到这个引用,问题不就解决了。但是这样在真正设计时会显得毫无意义,比如说你有一个“Fruit”的基类,和一个扩展它的Apple类。当你创建Apple类时,你的原意不是想得到一个关于Apple类的对象,它是作为Apple的对象而存在的。如果你想返回一个Fruit类的对象,你返回Apple对象的引用难道不能得到Fruit类的属性和行为吗?所以,得到一个完全独立的Fruit似乎就显得没有那么重要了。
      

  44.   

    我是这么理解的··this只能代表当前类的对象·而super则只能指负累对象··一般情况下我使用super是因为要将参数传给父类的构造方法而使用的,也可以对父类的成员变量赋值··我觉得当我使用super的时候无形中就已经构造了一个父类的对象了··
      

  45.   

    this  表示当前类对象调用;
    super 表示对父类的某个构造器的调用……
      

  46.   

    super父对象
    this 当前对象
      

  47.   

    super()可以用来调用父类中的构造方法和父类定义的方法
    this()表示当前类对象调用;