黑马程序员技术交流社区

标题: 关于构造函数中的this和super [打印本页]

作者: 张金    时间: 2012-10-5 21:03
标题: 关于构造函数中的this和super
这两个问题在对象实例化过程中该怎么理解,自己没怎么弄明白?
1,为什么super()和this()调用语句不能同时在一个构造函数中出现?
2,为什么super()和this()调用语句只能作为构造函数的第一句出现?
作者: 李志群    时间: 2012-10-5 22:27
this:代表是一个对象,代表那个对象呢?
哪个对象调用this所在的函数,this就代表那个对象,this就是当前对象的一个引用。
this:表现形式一:当局部标量和成员 变量同名的时候,可以用this来区分。
      表现形式二:构造函数之间的调用可以使用this关键字,后面跟上小括号,指定具体ude实参即可明确要调用的构造函数。
  特殊情况:注意:调用本类中构造函数的this语句必须要定义在构造函数的第一行。因为初始化动作先完成。

this和super调用构造函数只能定义构造函数的第一行,不能同事出现,为什么都定义在第一行啊?因为初始化的动作要先执行。

super代表的是父类。
用法和this相似,this代表本类对象的引用,super代表父类所属的空间。
注意:子父类中通常不会出现同名的属性。
      父类中既然定义了该属性,子类其实就没有必要在定义该属性了。】
上面说的是区别  还有就是子类实例化的过程 this和super  这个 在继承中就可以体现了 我给你讲讲嘿嘿
一个对象在内存中的产生过程:
1,将该对象所需的类文件加载进内存,
2,在内存进行空间的方法区的空间分配。
3,通过new在堆内存中开辟空间,
4,对象中的属性进行默认初始化。
5,调用与之对象的构造函数进行初始化。
6,通过构造函数的super调用父类中的构造函数初始化。
7,对象中的属性进行显示初始化。
8,构造代码块初始化。
9,该构造函数内部自定义内容进行初始化。
举个小例子  希望楼主看下 看不明白 给我回复 我给您讲讲哦
package mianxiang;
/*
* 练习:对象在内存中的初始化过程。
* 一个对象在内存中的产生过程:
1,将该对象所需的类文件加载进内存,
2,在内存进行空间的方法区的空间分配。
3,通过new在堆内存中开辟空间,
4,对象中的属性进行默认初始化。
5,调用与之对象的构造函数进行初始化。
6,通过构造函数的super调用父类中的构造函数初始化。
7,对象中的属性进行显示初始化。
8,构造代码块初始化。
9,该构造函数内部自定义内容进行初始化。
* */
class fu{
fu(){
  show();
}
void show()
{
  System.out.println("fu show run");
}
}

class zi extends fu
{
int num = 8;
{
  //构造代码块
  System.out.println("cons code num= "+num);
}
zi()
{
//super();隐式的
  //显示初始化隐式的
  //构造代码块 隐式的
  System.out.println("cons function num = "+num);
}
void show()
{
  System.out.println("zi show num= "+num);
}
}
public class InitTest {
/**
  * @param args
  */
public static void main(String[] args) {
  // TODO Auto-generated method stub
  new zi();
  /*
   * 打印结果。 zi show num= 0
   cons code num= 8
   cons function num = 8
   *
   * */
}
}

图解例子.jpg (71.78 KB, 下载次数: 44)

图解例子.jpg

作者: 黑马乔荣柱    时间: 2012-10-5 23:07
子类构造器是用super隐式或显示来调用父类构造器的。
隐式是指在子类构造器中没有手动编写使用super和this时,系统自动在子类构造器中第一行语句之前隐式默认加上super()来调用父类无参构造器,此时如果父类没有super()所对应无参构造器,则会出错。
反之显式使用super或this时,系统不会在此子类构造器中再提供隐式的super(),即会用显示使用的super或this来代替隐式的super()。
因为隐式的super()默认是在第一行语句之前,所以显示使用的super需要放在第一行才可以覆盖隐式的super()。
注:this()同理。另外this()和super()均代表构造函数,只能在构造函数中调用,而不能在普通的成员方法中调用,也不能作为普通成员方法使用。
作者: 张金    时间: 2012-10-7 00:20
李志群 发表于 2012-10-5 22:27
this:代表是一个对象,代表那个对象呢?
哪个对象调用this所在的函数,this就代表那个对象,this就是当前 ...

多谢大神哈哈。
作者: 张金    时间: 2012-10-7 00:21
彼岸花 发表于 2012-10-5 23:07
子类构造器是用super隐式或显示来调用父类构造器的。
隐式是指在子类构造器中没有手动编写使用super和this ...

一起努力,加油,支持你。
作者: 黑马连家华    时间: 2012-10-7 00:38
老师说,子类实例化的时候需要父类构造函数的支持来实例化这个子类对象...
作者: AngieFans85    时间: 2012-10-7 08:21
本帖最后由 马镱洵 于 2012-10-7 08:35 编辑
李志群 发表于 2012-10-5 22:27
this:代表是一个对象,代表那个对象呢?
哪个对象调用this所在的函数,this就代表那个对象,this就是当前 ...


"1,将该对象所需的类文件加载进内存,
2,在内存进行空间的方法区的空间分配。
3,通过new在堆内存中开辟空间,
4,对象中的属性进行默认初始化。
5,调用与之对象的构造函数进行初始化。
6,通过构造函数的super调用父类中的构造函数初始化。
7,对象中的属性进行显示初始化。
8,构造代码块初始化。
9,该构造函数内部自定义内容进行初始化。"

同学,这个顺序明显不对啊,我重新给你排下顺序吧:
1 2 3  6 4 7 8 5 9
有一点需要说明的是:
通过构造函数的super调用父类中的构造函数初始化时,会先将父类和子类的所有非静态成员进行默认初始化,然后是父类非静态成员显式初始化 -> 父类构造代码块 -> 父类构造方法 -> 子类非静态成员显式初始化 -> 子类构造代码块 -> 子类构造方法.
作者: AngieFans85    时间: 2012-10-7 08:43
对于LZ,这样的问题你不需要去问为什么,就是语法要求而已.
作者: 李志群    时间: 2012-10-7 16:28
马镱洵 发表于 2012-10-7 08:21
"1,将该对象所需的类文件加载进内存,
2,在内存进行空间的方法区的空间分配。
3,通过new在堆内存中开 ...

要是你感觉不对 你去看毕老师 视频吧  这是毕老师总结的 您别和我说 0 0!!!!
作者: AngieFans85    时间: 2012-10-7 17:40
李志群 发表于 2012-10-7 16:28
要是你感觉不对 你去看毕老师 视频吧  这是毕老师总结的 您别和我说 0 0!!!! ...

你在搞笑的,你确定毕老师是你那样排的顺序吗.你认为毕老师会认为构造代码块会比构造方法还要晚执行吗...
作者: 李志群    时间: 2012-10-7 19:05
马镱洵 发表于 2012-10-7 17:40
你在搞笑的,你确定毕老师是你那样排的顺序吗.你认为毕老师会认为构造代码块会比构造方法还要晚执行吗... ...

要视频不?  可以 给你。 和你讲 没意义 谢谢!  回去自己看下 在给别人讲!
作者: 李志群    时间: 2012-10-7 19:24
毕老师视频给您上传完了 自己去看看吧  在回来说别人的错误,,还有就是不要老挑别人的 ,,,先找自己的错误,做人的基本常识。
和我说的那位哥们 请您看完视频在说。。。

11-面向对象(对象在内存中的初始化过程).haozip01.zip

2 MB, 下载次数: 138

11-面向对象(对象在内存中的初始化过程).haozip02.zip

2 MB, 下载次数: 145

11-面向对象(对象在内存中的初始化过程).haozip03.zip

2 MB, 下载次数: 146

11-面向对象(对象在内存中的初始化过程).haozip04.zip

2 MB, 下载次数: 141

11-面向对象(对象在内存中的初始化过程).haozip05.zip

2 MB, 下载次数: 146

11-面向对象(对象在内存中的初始化过程).haozip06.zip

2 MB, 下载次数: 141

11-面向对象(对象在内存中的初始化过程).haozip07.zip

2 MB, 下载次数: 153

11-面向对象(对象在内存中的初始化过程).haozip08.zip

2 MB, 下载次数: 134

11-面向对象(对象在内存中的初始化过程).haozip09.zip

2 MB, 下载次数: 130

11-面向对象(对象在内存中的初始化过程).haozip10.zip

2 MB, 下载次数: 159

11-面向对象(对象在内存中的初始化过程).haozip11.zip

1.44 MB, 下载次数: 142


作者: 李志群    时间: 2012-10-7 19:25
文件太大 给分压缩的,,自己下载就可以看了 希望楼主 也可以看看 呵呵  来这个论坛 都是来互相学习的。。。
作者: 李志群    时间: 2012-10-7 19:34
刚上传的分卷说明忘记上传了····

11-面向对象(对象在内存中的初始化过程).zip_2345好压分卷说明.zip

502 Bytes, 下载次数: 151


作者: AngieFans85    时间: 2012-10-7 20:25
李志群 发表于 2012-10-7 19:05
要视频不?  可以 给你。 和你讲 没意义 谢谢!  回去自己看下 在给别人讲! ...

你真的认为毕老师会认为构造代码块会比构造方法还要晚执行吗,你是想说毕老师犯了一个低级错误吗?
毕老师的视频有几个没听过啊.
构造代码块和构造方法谁先执行,你不会自己去试一遍吗?我都不知道这有什么争的,编译器和解释器还会骗你吗.
作者: 李志群    时间: 2012-10-7 21:19
马镱洵 发表于 2012-10-7 20:25
你真的认为毕老师会认为构造代码块会比构造方法还要晚执行吗,你是想说毕老师犯了一个低级错误吗?
毕老师 ...

那行吧 随便你了呵呵 你看好我的例子 在说  视频上面都有 你自己看下
作者: AngieFans85    时间: 2012-10-7 21:27
李志群 发表于 2012-10-7 19:34
刚上传的分卷说明忘记上传了····

我刚刚看了你的这个视频了,老毕明明说的是构造代码块的优先级比构造方法的优先级要高.
你倒真是挺执着的.
作者: AngieFans85    时间: 2012-10-7 21:41
李志群 发表于 2012-10-7 21:19
那行吧 随便你了呵呵 你看好我的例子 在说  视频上面都有 你自己看下

我看了你的代码啊,你的代码写的很清楚啊,是构造代码块比构造方法优先执行啊.
老毕的视频我也看了啊,你看看老毕的视频的总结是怎么写的:

我不知道你这人怎么就这么执着呢.
作者: AngieFans85    时间: 2012-10-7 21:44
李志群 发表于 2012-10-7 21:19
那行吧 随便你了呵呵 你看好我的例子 在说  视频上面都有 你自己看下

我好心给你指出错误,并给出正确的顺序,你偏偏要把老毕搬出来,还让我先找自己的错误,还说这是做人的基本常识...
我能说什么呢,我只想说,我还不至于蠢到不知道答案就敢给人纠正错误,好像我是个喜欢不懂装懂的人一样.
行,以后你的帖子我不回复就是了.
作者: 李志群    时间: 2012-10-7 23:15
马镱洵 发表于 2012-10-7 21:44
我好心给你指出错误,并给出正确的顺序,你偏偏要把老毕搬出来,还让我先找自己的错误,还说这是做人的基本常 ...

随便您 呵呵 你看好我发的视频 和例子 在说 你看看我发那视频讲的是什么  。。你和我讲的是一个吗 你就说啊。。。看好我楼上发的视频 你下载好好看下 谢谢
作者: AngieFans85    时间: 2012-10-7 23:56
李志群 发表于 2012-10-7 23:15
随便您 呵呵 你看好我发的视频 和例子 在说 你看看我发那视频讲的是什么  。。你和我讲的是一个吗 你就说 ...

好啊,我看你能撑多久.
你自己听听你发的那视频,从6分20秒时开始听,看看老毕说的是什么.怎么,你以为我没有听过吗,老毕7个G多的完整的视频我都早下载过了.
现在又看看你发的例子:
  1. class fu {

  2.         fu() {
  3.                 show();
  4.         }

  5.         void show() {
  6.                 System.out.println("fu show run");
  7.         }

  8. }

  9. class zi extends fu {

  10.         int num = 8;
  11.         {
  12.                 // 构造代码块
  13.                 System.out.println("cons code num= " + num);
  14.         }

  15.         zi() {
  16.                 // super();隐式的
  17.                 // 显示初始化隐式的
  18.                 // 构造代码块 隐式的
  19.                 System.out.println("cons function num = " + num);
  20.         }

  21.         void show() {
  22.                 System.out.println("zi show num= " + num);
  23.         }

  24. }

  25. public class InitTest {

  26.         public static void main(String[] args) {
  27.                 new zi();
  28.                 /*
  29.                  * 打印结果。 zi show num= 0 cons code num= 8 cons function num = 8
  30.                  */
  31.         }

  32. }
复制代码
这是你自己写的代码吧,你自己不写好注释了,程序运行结果为:
zi show num= 0// 结果1
cons code num= 8// 结果2
cons function num = 8// 结果3

结果1: 父类的构造方法先调用到(因为父类没有成员属性,也没有构造代码块,所以父类就执行构造方法.),构造方法中调用到show()方法,由于多态,所以其实是调用到的子类的show()方法,从而出现结果1.
结果2: 父类的构造方法执行完后,就轮到子类了.首先是将子类的成员变量进行显式初始化(子类成员与父类成员的默认初始化,在子类的构造方法里调用到super()语句时,就开始执行了.所以结果1中,num的值为0就是因为在父类的构造方法还没有执行完毕时,子类的成员变量只有默认初始化时的值,子类的成员还没有进行显式初始化,所以num的值为0.),子类成员显式初始化后,num的值就为8.然后就执行子类的构造代码块,所以输出结果2.
结果3: 子类在成员的显示初始化与构造代码块分别执行完后,才轮到子类的构造方法开始执行,于是才有结果3.

我看你现在还能说什么,你继续争下去啊,我很期待.
作者: AngieFans85    时间: 2012-10-8 00:02
李志群 发表于 2012-10-7 23:15
随便您 呵呵 你看好我发的视频 和例子 在说 你看看我发那视频讲的是什么  。。你和我讲的是一个吗 你就说 ...

另外,我已经在18楼把毕老师在视频中的总结截图给你看了,你居然还要挣扎,有意义吗?

看到没有,第6和第7的顺序,你现在还一如既往地认为是老毕说构造代码块的执行顺序比构造方法的执行顺序要晚吗?
要不要我们另外开贴,让大家都进来参观一下?需要吗?




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2