黑马程序员技术交流社区

标题: 基础班第二次考试选择题(关于构造函数调用的理解) [打印本页]

作者: huyang936    时间: 2015-2-3 22:14
标题: 基础班第二次考试选择题(关于构造函数调用的理解)
本帖最后由 huyang936 于 2015-2-5 00:37 编辑
  1. <p>package cn.itcast;
  2. /****************调用出错******************************************************************************/
  3. class Person {
  4. String name;//加static
  5. String department;
  6. int age;//加static
  7. int num = age;
  8. public Person()
  9. {
  10.   System.out.println(name+"::"+age);
  11. }
  12. public Person(String n) {
  13.   name = n;
  14. }

  15. public Person(String n, int a) {
  16.   name = n;
  17.   age = a;
  18. }

  19. public Person(String n, String d, int a) {
  20.   // 完成Person(String n, int a)的逻辑
  21.   this(name,age); //【【【此处调用出错】】】
  22.   department = d;
  23. }
  24. }




  25. /****************加static后,错误解除******************************************************************************/
  26. package cn.itcast;
  27. class Person {
  28. static String name;//加static
  29. String department;
  30. static int age;//加static
  31. int num = age;
  32. public Person()
  33. {
  34.   System.out.println(name+"::"+age);
  35. }
  36. public Person(String n) {
  37.   name = n;
  38. }

  39. public Person(String n, int a) {
  40.   name = n;
  41.   age = a;
  42. }

  43. public Person(String n, String d, int a) {
  44.   // 完成Person(String n, int a)的逻辑
  45.   this(name,age); //【【【问题解除】】】
  46.   department = d;
  47. }
  48. }

  49. </p>
复制代码


第23道选择题:
1. 给出下面的不完整的类代码
  class Person {
    String name, department;
    int age;
    public Person(String n){ name = n; }
    public Person(String n, int a){ name = n; age = a; }
    public Person(String n, String d, int a) {
      // 完成Person(String n, int a)的逻辑
      department = d;
    }
  }
  下面的哪些表达式可以加到构造方法中的注释处? (   )
A. Person(n,a);
B. this(Person(n,a)); //构造函数的名字不能当方法名调用;
C. this(n,a);
D. this(name,age); //构造方法的参数也不能直接传实例变量名


D选项:“构造方法的参数也不能直接传实例变量名”:
如下图测试的那样,加static后就能使用呀,这个到底是怎么理解的呢???求解释!!!

****************************************************************************************************************************************
晚上回来又看了看这个问题,在网上找到了我认为合理的解释,大家不妨也看下
问题原因:
Cannot refer to an instance field name while explicitly invoking a constructor
明确调用一个构造器的时候不能引用类的一个实例域
原因分析:

全都没讲到点子上。报错这和final没有任何关系。举个列子

public int i=1;
public MyThing(){
   super(i);
}

原因很简单,我们假如可以通过编译器。我问一个问题,调用构造器是干什么的?
大家都知道,创建一个对象并初始化对象中的数据域。红色字体很重要,在上面的列子中new MyThing()的作用就是为了初始化这个对象的数据域i,试问在没有通过构造器初始化之前,i的值是不确定的。我们怎么能使用一个不确定的i值来初始化对象。

打个比方:我们去银行取5元钱,但是必须首先交5块钱手续费(也就是首先明确初始化)。我能不能给银行的人说:你把5元先取给我,然后我再把这钱给你交手续费呢???

当然例子不是很恰当,但说的意思差不多。总之,必须要先明确初始化实例域,才能创建好对象,进而才能使用对象的数据域。在没有实例化之前就想使用他,就像没有取出5元钱就想先用这钱一样,不可能。

public int i=1;
public MyThing(int j){
   super(j);
}
上面的代码就可以,为什么,因为编译器知道,你如果想构造这个对象,必须传过来一个确定的值来初始化。


报错.png (128.22 KB, 下载次数: 26)

调用报错

调用报错

图片2.png (129.79 KB, 下载次数: 25)

错误解除

错误解除

作者: kenfine    时间: 2015-2-3 22:52
我是这么理解的,加上static后,this(name,age); 这条语句接收的不是new对象的参数,而是类里面静态的name和age,而且默认值分别是null和0
作者: 小鹏_sJQBO    时间: 2015-2-3 22:53
楼主加油
作者: kenfine    时间: 2015-2-3 22:54
{:3_53:}你的帖子让我又增加了对this的认识
作者: 466273082    时间: 2015-2-3 23:14
楼主,加油呀,赞
作者: Novice.Jin    时间: 2015-2-3 23:56
学习了~~~~~~~~~
作者: 会飞d猪    时间: 2015-2-4 07:14
还在纠结这个题。。。
作者: 白衣布士    时间: 2015-2-4 12:38
感谢分享,楼主加油!!!:lol
作者: yanqiuqiu    时间: 2015-2-4 13:12
加油啊!!!!
作者: x1071765330    时间: 2015-2-4 13:14
加油!楼主!!
作者: huyang936    时间: 2015-2-4 21:24
kenfine 发表于 2015-2-3 22:52
我是这么理解的,加上static后,this(name,age); 这条语句接收的不是new对象的参数,而是类里面静态的name ...

这个问题最纠结的是:不加static,成员变量的默认初始化也优先于调用的构造函数初始化,所以,不加static,name和age中的值已经有值了null和0;那么问题来了,加static可以,不加问什么不行呢???
作者: kenfine    时间: 2015-2-4 21:55
我用的是eclipse开发做的,那里有显示哪一个和哪一个是一样的。我这么理解吧:如果用static 的话,this(name,age)用的是类中的类变量,而不加则用的是对象的变量。
作者: kenfine    时间: 2015-2-4 21:59
补充:加了static成员变量在类加载的时候就已经初始化了,而且优于对象出现,不依赖对象了,而构造函数的作用不是恰好就是创建对象使用的?
作者: huyang936    时间: 2015-2-5 00:29
kenfine 发表于 2015-2-4 21:55
我用的是eclipse开发做的,那里有显示哪一个和哪一个是一样的。我这么理解吧:如果用static 的话,this(nam ...

嗯 谢谢 回复 我刚刚在网上找了 这个 问题解释 你也可以看下(我修改了帖子)
作者: clairetoto2012    时间: 2015-2-5 07:24
好贴,学习受教了!
作者: 邓士林    时间: 2015-2-5 09:00
我看了你这个问题也是吓了一跳,为什么呢?给大家看两段代码:
  1. public Person(<font color="#ff0000">String n, String d,</font> int a) {
  2.   // 完成Person(String n, int a)的逻辑
  3. <font color="#ff0000">  this(name,age);</font> //【【【此处调用出错】】】
  4.   department = d;
  5. }
复制代码
  1.         Person1<font color="#ff0000">(int age,String name</font>,String depart)
  2.         {
  3. <font color="#ff0000">                this(age,name);</font>
  4.                 this.depart = depart;
  5.         }
复制代码
可以看到代码2片段中是没有错误的,为什么?因为此处的age和name是传进来的局部变量,而楼主的代码为什么错误,因为name和age是类的成员变量,类的普通成员变量是依托对象而存在,而静态成员变量是依托于类而存在。静态成员变量优先于构造函数存在。
现在解释为什么加static和不加static:
不加static:我们建立对象,调用三个参数的构造方法,但是在之前并没有age和name
加上static:成员变量优先于构造函数存在,类加载的时候也存在了,所以在构造的时候就没问题。


作者: huyang936    时间: 2015-2-5 18:54
邓士林 发表于 2015-2-5 09:00
我看了你这个问题也是吓了一跳,为什么呢?给大家看两段代码:可以看到代码2片段中是没有错误的,为什么? ...

嗯 谢谢回复分享
我当时的疑惑是这样的:
这个问题最纠结的是:不加static,成员变量的默认初始化也优先于调用的构造函数初始化,所以,不加static,name和age中的值已经有值了null和0
现在的理解:
虽然对象在加载过程中,成员变量的默认初始化是优先于所有构造方法的,但编译器不会这样理解,
这样做违背了使用构造器的初衷:
构造器就是用来初始化对象的成员变量的(在没有显式初始化之前更是这样),
即:在构造函数之前,该变量是不确定的,所以也就不能当作实参进行值传递了
这也只是我现在的理解,不对的地方请阁下不吝指教,呵呵
作者: 朋好友    时间: 2015-2-5 20:35
感谢楼主分享
作者: 小马范    时间: 2015-2-5 21:11
huyang936 发表于 2015-2-4 21:24
这个问题最纠结的是:不加static,成员变量的默认初始化也优先于调用的构造函数初始化,所以,不加static ...

你的this(name,age) 不是调用的是构造函数Person(String n, int a),如果this(name,age)语句可以执行,那么久需要在属性name和age上加 static
作者: 沌沌愚人心    时间: 2015-2-5 23:15
楼主加油!
作者: liuka    时间: 2015-2-7 08:53
受教受教!




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