黑马程序员技术交流社区

标题: 关于构造函数赋值的问题 [打印本页]

作者: heima_xyu    时间: 2014-5-5 18:16
标题: 关于构造函数赋值的问题
public class Test5 {
public static void main(String[] args)
{
  //建立Chinese类的对象zhangsan,并调用sayHello()方法
  Chinese zhangsan=new Chinese("张三",22);
  zhangsan.sayHello();
}
}
//建立Person类
class Person{
//将姓名和年龄属性私有化
private String name;
private int age;
//构造函数2,必须传入名字和年龄才能建立对象
Person(String name,int age)
{
  this.name=name;
  this.age=age;
}
public int getAge()
{
  return age;
}
public String getName()
{
  return name;
}
//打招呼的方式并非共性,由子类来复写
void sayHello(){}
}
//建立Chinese继承Person
class Chinese extends Person{
private String name;
private int age;
Chinese(String name,int age)
{
  super(name,age);
}
//中国人特有的打招呼方法
public void sayHello()
{
  //System.out.println("我叫"+getName()+",今年"+getAge()+"岁了。");  //该结果为我叫张三,今年22岁了,这样没问题,
  System.out.println("我叫"+name+",今年"+age+"岁了。");       //该结果为我叫null,今年0岁了  
}
}
/*
1.为什么?super(name,age)不是等价于this.name=name;this.age=age;吗?
可是打印结果name为null,age为0.说明并没有赋值。
2.继承的getAge()和getName()却能返回传入的“张三”和22.
这又说明构造函数确实接收了,希望能解答我的疑惑
*/



作者: 张然龙    时间: 2014-5-5 18:29
本帖最后由 张然龙 于 2014-5-5 18:38 编辑

你的排版不对。。  发帖子有个专用的粘贴代码的方框。
你理解错了 你父类和子类同时定义的 name 和age  你用super将参数传递给父类了,而你子类的name和age属性却并未进行初始化赋值,这就导致了你的name和age还是初始化的值,string的初始化值为null  int类型初始化值为0。

你调用的恰恰是你子类的name和age  而不是父类中的name和age所以显示结果为null  和0。


你这个题有两种解决方案 我一个一个说:


第一种 :将子类的打印语句修改成这样:

  1. class Chinese extends Person
  2. {
  3.         private String name;
  4.         private int age;
  5.         Chinese(String name,int age)
  6.         {
  7.           super(name,age);
  8.         }
  9.         //中国人特有的打招呼方法
  10.         public void sayHello()
  11.         {
  12.           System.out.println("我叫"+super.name+",今年"+super.age+"岁了。"); //将name属性和age属性前边加上super 这样访问的是父类已经初始化后的属性,而不是子类中的name和age。
  13.         }
  14. }
复制代码


第二种 :
代码如下↓

  1. class Chinese extends Person
  2. {
  3.         private String name;
  4.         private int age;
  5.         Chinese(String name,int age)
  6.         {
  7.           super(name,age);
  8.           this.name=name;//父类构造函数初始化完毕后自动读到这里,给子类的成员变量初始化,这样就可以用子类中的属性来打印输出了!!
  9.           this.age=age;
  10.         }
  11.         //中国人特有的打招呼方法
  12.         public void sayHello()
  13.         {
  14.           //System.out.println("我叫"+getName()+",今年"+getAge()+"岁了。");  //该结果为我叫张三,今年22岁了,这样没问题,
  15.           System.out.println("我叫"+name+",今年"+age+"岁了。");       //该结果为我叫null,今年0岁了  
  16.         }
  17. }
复制代码







作者: heima_xyu    时间: 2014-5-5 18:49
张然龙 发表于 2014-5-5 18:29
你的排版不对。。  发帖子有个专用的粘贴代码的方框。
你理解错了 你父类和子类同时定义的 name 和age  你 ...

哈哈,谢谢!确实只是给父类初始化,并没有给子类初始化,不过你的第一种方法行不通,刚刚调试了,父类没有实例化。
作者: 张然龙    时间: 2014-5-5 18:53
第一种行得通  ,使用super.name和super.age去调用父类中的成员变量

代码如下↓

  1. public class Demo4 {
  2. public static void main(String[] args)
  3. {
  4.   //建立Chinese类的对象zhangsan,并调用sayHello()方法
  5.   Chinese zhangsan=new Chinese("张三",22);
  6.   zhangsan.sayHello();
  7. }
  8. }
  9. //建立Person类
  10. class Person
  11. {
  12.         //将姓名和年龄属性私有化
  13.         String name;
  14.         int age;
  15.         //构造函数2,必须传入名字和年龄才能建立对象
  16.         Person(String name,int age)
  17.         {
  18.           this.name=name;
  19.           this.age=age;
  20.         }
  21.         public int getAge()
  22.         {
  23.           return age;
  24.         }
  25.         public String getName()
  26.         {
  27.           return name;
  28.         }
  29.         //打招呼的方式并非共性,由子类来复写
  30.         void sayHello(){}
  31. }
  32. //建立Chinese继承Person
  33. class Chinese extends Person
  34. {
  35.         private String name;
  36.         private int age;
  37.         Chinese(String name,int age)
  38.         {
  39.           super(name,age);
  40.         }
  41.         //中国人特有的打招呼方法
  42.         public void sayHello()
  43.         {
  44.           //System.out.println("我叫"+getName()+",今年"+getAge()+"岁了。");  //该结果为我叫张三,今年22岁了,这样没问题,
  45.           System.out.println("我叫"+super.name+",今年"+super.age+"岁了。");       //该结果为我叫null,今年0岁了  
  46.         }
  47. }
复制代码

作者: 程序爱好者    时间: 2014-5-5 19:04
super(name,age)是调用父类的构造方法,给父类赋值,并没有给本类赋值
this.name=name;this.age=age;  这个是给本类的属性赋值。
所以你的代码改为
  Chinese(String name,int age)

  {
          super(name,age);
          this.name=name;this.age=age;
  }
public void sayHello()

{
         System.out.println("我叫"+name+",今年"+age+"岁了。");   
  }


或者是:

Chinese(String name,int age)

{
         super(name,age);
}
public void sayHello()

  {
       System.out.println("我叫"+super.name+",今年"+super.age+"岁了。");  
  }








作者: heima_xyu    时间: 2014-5-5 19:05
张然龙 发表于 2014-5-5 18:53
第一种行得通  ,使用super.name和super.age去调用父类中的成员变量

代码如下↓

嗯,之前行不通,是因为将父类的name和age属性私有化了,因此不能直接调用super.name。
不过有了新的疑问,父类没有创建对象,那么Person的name和age的值是在内存中怎么存在的
作者: gentleman    时间: 2014-5-5 19:33
在Java继承中,成员变量没有覆盖一说,应该叫隐藏。覆盖只是针对成员方法来说的。当调用子类构造函数构建子类对象的时候,必然会先调用父类的构造函数,如果不写带参数的 super(name,age);也会自动加一个空参数的 super();
System.out.println("我叫"+name+",今年"+age+"岁了。");       //这里其实是省略了this. 调用的是本对象的name和age,而你没有初始化赋值所以会出现String为空,int为0的情况
作者: 张然龙    时间: 2014-5-7 22:00
没有问题的话把帖子给结了哈!




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