super和this到底是什么

dreamhunter_lan 2010-11-16 12:57:42
回过头来再看的时候真的已经不知道它们分别是什么东西了,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());
}
}

希望大家帮忙解惑,说说它们是什么。怎么使用它们就不用说了,所有的书上都差不多教我们怎么用了。谢谢~
...全文
1166 69 打赏 收藏 转发到动态 举报
写回复
用AI写文章
69 条回复
切换为时间正序
请发表友善的回复…
发表回复
ab11808 2010-11-25
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 genguyige 的回复:]
不能简单的说this表示子类 super表示父类
而是说this表示正在编译的类


上面那个文件输出之后会得到0
[/Quote]

????????俺是初学者,不明白为什么会得到0呢???
凉岑玉 2010-11-25
  • 打赏
  • 举报
回复
我是这么理解的··this只能代表当前类的对象·而super则只能指负累对象··一般情况下我使用super是因为要将参数传给父类的构造方法而使用的,也可以对父类的成员变量赋值··我觉得当我使用super的时候无形中就已经构造了一个父类的对象了··
ssd189 2010-11-25
  • 打赏
  • 举报
回复
看了这么多, 我有想说的话:
1.首先,楼主的说法是对的,super不是引用,而是作为一个看似引用的行为。这点大家都说了,没有什么好解释的了。
2.我也有了一个困惑,就是楼主想得到一个super对象的引用。这时,就要明确一个问题,究竟有几个对象。也就是说只有SubClass这一个对象还是同时有Object,Super,SubClass三个对象。楼主的问题应该只有后者为真的情况下才有意义。那若此,就是说先创建父类的对象,并且要求父类对象与子类无关,完全放在一个独立的内存地址里的。然后,子类会隐含的拥有一个父类对象的引用。如果能搞到这个引用,问题不就解决了。但是这样在真正设计时会显得毫无意义,比如说你有一个“Fruit”的基类,和一个扩展它的Apple类。当你创建Apple类时,你的原意不是想得到一个关于Apple类的对象,它是作为Apple的对象而存在的。如果你想返回一个Fruit类的对象,你返回Apple对象的引用难道不能得到Fruit类的属性和行为吗?所以,得到一个完全独立的Fruit似乎就显得没有那么重要了。
dreamhunter_lan 2010-11-25
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 ddc 的回复:]

一定要刨根,那很多"结论"都要推翻。
先从C++说起,这个能看到机器码。C++里,所有类都会有构造函数,没有的也会给你生成一个默认的(java一样),在语法层面这绝对是正确的,或者说逻辑上正确,实际呢?
C/C++ code

class Super
{
public:
//Super(){}
int aa;
};

int main()
{
Sup……
[/Quote]
很多时候自己太去抠一些字眼了~也许就当它们是关键字去用就比较好了。越挖越多,JLS也翻了不少地方,很蛋疼,哈哈
fantasy0126 2010-11-25
  • 打赏
  • 举报
回复
这个讨论很精彩.

学习了.

记得java有四部分组成:java语法,java class文件格式,java api,java虚拟机.

我认为单从语法规则的角度可能只有些生硬的规定,知其然不知其所以然.从JLS的角度由于其过于宽松而只有一个非常抽象的规定.
从jvm的实现的角度,我想楼主和我们能会有一个更清楚的认识
郑重推荐一本书: inside java virtual machine
Eminas 2010-11-25
  • 打赏
  • 举报
回复
super()可以用来调用父类中的构造方法和父类定义的方法
this()表示当前类对象调用;
ajh9990 2010-11-25
  • 打赏
  • 举报
回复
super父对象
this 当前对象
ddc 2010-11-25
  • 打赏
  • 举报
回复
一定要刨根,那很多"结论"都要推翻。
先从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
uastation 2010-11-25
  • 打赏
  • 举报
回复
this 表示当前类对象调用;
super 表示对父类的某个构造器的调用……
liulefirst 2010-11-22
  • 打赏
  • 举报
回复
super代表的是引用父类中的方法,,而this代表的是子类中重写之后的方法.
xiguadaxia 2010-11-22
  • 打赏
  • 举报
回复
至于this()是子类构造器 super()是父类构造器,这个我的理解就是一个硬性的规定。
(同时在方法体里(构造器里也一样)调用跟构造器同名的方法,都会被解读为成员方法而不是构造器)

而且用法是:只能是构造器的第一句语句。——2个信息:1.只能在构造器中使用;2. 必须放在第一句





xiguadaxia 2010-11-22
  • 打赏
  • 举报
回复
我觉得这么说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就是为了能调用父类被重写的成员而诞生。
dreamhunter_lan 2010-11-21
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 nihaoma00100 的回复:]

楼上们其实都犯了一个错误,其实楼主给出的英文里的说明已经非常明确地说明了,this是一个对象的引用,而super仅仅是一个指示编译器调用超类方法的特有的关键字,这里一定要记住!super不是一个引用,只是一个关键字!很多人犯的错误。
[/Quote]
终于又多了一个不是瞎说的了~唉
dreamhunter_lan 2010-11-21
  • 打赏
  • 举报
回复
其实很多时候大家都错误地认为是那样(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.

高手可以指出不妥指出或者给出更详尽的解释,让大家彻底搞清楚,而不是仅仅知道怎么去用它们。
龙飞tgbmlp 2010-11-21
  • 打赏
  • 举报
回复
[Quote=引用 47 楼 zouzhiao 的回复:]
引用 44 楼 nihaoma00100 的回复:

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

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

同意,我原来也是一直以为super是父类的引用,学习了!!!
HeartWasNot 2010-11-21
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 binwenstars 的回复:]

都是引用 this----当前对象,super ---基类对象(父类对象)
[/Quote]额,这才是基础解释
卑微的去爱你 2010-11-21
  • 打赏
  • 举报
回复
[Quote=引用 44 楼 nihaoma00100 的回复:]

楼上们其实都犯了一个错误,其实楼主给出的英文里的说明已经非常明确地说明了,this是一个对象的引用,而super仅仅是一个指示编译器调用超类方法的特有的关键字,这里一定要记住!super不是一个引用,只是一个关键字!很多人犯的错误。
[/Quote]
我发现国产的书籍没他妈几个能看的 书上说的是super携带父类引用
qingyuan18 2010-11-21
  • 打赏
  • 举报
回复
super:父类
this:本类

只是一个引用,没啥特别的,不要想复杂了
tingzuoshou 2010-11-21
  • 打赏
  • 举报
回复
有点看不下去,太长了
steely_chen 2010-11-21
  • 打赏
  • 举报
回复
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 都是返回调用此方法的那个对象的运行时类
加载更多回复(46)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧