A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 乔_博_文 中级黑马   /  2013-3-5 22:39  /  2571 人查看  /  20 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 乔_博_文 于 2013-3-6 20:32 编辑

+++++++++++++++++++++++++++++++
//定义一个父类:Person
public class Person
{
        String name;
        int age;

        public Person()
        {
                this.sayHello();
        }
        
        public void sayHello()
        {
                System.out.println("hello~");
        }
}

++++++++++++++++++++++++++++++++++
//定义一个子类:Student
public class Student extends Person
{
        int id;

        public Student(String name, int age, int id)
        {
                super.name = name;
                super.age = age;
                this.id = id;
        }

        public void sayHello()
        {
                System.out.println("hello,I'm "+name);
        }
}
++++++++++++++++++++++++++++++++++

//测试类:StudentDemo
public class StudentDemo
{
        public static void main(String[] args)
        {
                Student s = new Student("zhangsan",20,1301);
                s.sayHello();
        }        
}
+++++++++++++++++++++++++++++++++++++++


以上代码输出结果如下:
hello,I'm null
hello,I'm zhangsan
————————————————
疑问1:第一个“hello,i'm null”是怎么得来的?它为什么会被输出?
疑问2:Person类里边构造方法中的 this.sayHello(); 调用的是哪个方法?难道不是本类中的 sayHello() 吗?
            为什么调用的是子类Student中的 sayHello() ?

恳请高人回答,坐等,感激不尽!~







评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

20 个回复

倒序浏览
1.”new Student("zhangsan",20,1301);“执行时,会调用Person类的Student(String name, int age, int id)构造方法。
2.在构造方法Student(String name, int age, int id)中的第一行有句隐式的代码“super()”,所以会调用父类的public Person()构造方法。
3.Student类是Person类的子类,Student重写了父类的sayHello方法。所以this.sayHello();中的sayHello方法就是Student类的方法。
4.在执行sayHello时,public Student(String name, int age, int id) 构造方法中的下面三行代码还未执行到,这时的name属性的值为null。所以
hello,i'm null就输出了。
回复 使用道具 举报
首先,你这个代码有问题,一个文件里只允许有一个public类,你这一编译就报错了
回复 使用道具 举报
对于“hello,i'm null”为什么会输出,那是因为在创建子类的对象时,Java虚拟机首先执行父类的构造方法,然后再执行子类的构造方法,所以会先调用到父类的sayHello方法,而后调用到子类的sayHello方法,故会有如下输出结果:
hello,I'm null
hello,I'm zhangsan

第二个疑问:
this.sayHello();   //this关键字代表的是当前类的对象,调用的是父类里的sayHello方法

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

回复 使用道具 举报

//定义一个父类:Person
class Person
{
        String name;
        int age;

        public Person()
        {
                this.sayHello();
        }
        
        public void sayHello()
        {
                System.out.println("hello~");
        }
}


//定义一个子类:Student
class Student extends Person
{
        int id;

        public Student(String name, int age, int id)
        {
                        //子类中所有的构造函数默认第一行都是super();
                        //  super();       调用父类空参数的构造方法。
                        //        this.sayHello(); 此句与super起同样的效果。调用的是Student类的sayHell(),因为复写了父类方法。
                super.name = name;
                super.age = age;
                this.id = id;
        }

        public void sayHello()//复写了父类中的sayHello()
        {
                System.out.println("hello,I'm "+name);
        }
}


//测试类:StudentDemo
class StudentDemo
{
        public static void main(String[] args)
        {
                Student s = new Student("zhangsan",20,1301);//当建立对象时,就调用了super();此时name还没加载。第一次打印name为null;
                s.sayHello();//第二次对象已建立,name为"zhangsan"
        }        
}

回复 使用道具 举报
克零岚 发表于 2013-3-5 23:05
对于“hello,i'm null”为什么会输出,那是因为在创建子类的对象时,Java虚拟机首先执行父类的构造方法,然 ...

不好意思,没整明白。我也知道父类里的this....是调用的是父类的sayHello(),可是你把这个this.sayHello()语句注释掉,就没有那个“hello,I'm null”的输出了,由此可见这个this的调用跟子类的sayHello()也有关系,可是我不知道是什么关系。。。
回复 使用道具 举报
寂寞,好了。 发表于 2013-3-5 22:59
首先,你这个代码有问题,一个文件里只允许有一个public类,你这一编译就报错了 ...

呵呵,我会告诉你我是在三个类文件写的如上代码吗?
回复 使用道具 举报
乔_博_文 发表于 2013-3-5 23:12
不好意思,没整明白。我也知道父类里的this....是调用的是父类的sayHello(),可是你把这个this.sayHello( ...

this.sayHello()没有注释
回复 使用道具 举报
乔_博_文 发表于 2013-3-5 23:12
不好意思,没整明白。我也知道父类里的this....是调用的是父类的sayHello(),可是你把这个this.sayHello( ...

下面是你的代码,标注的数字(1)(2)....(6)是执行的顺序,参照我上面给的说明你就明白了
//定义一个父类:Person
public class Person
{
        String name;
        int age;

        public Person()
        {
                this.sayHello();                     (2)
        }
        
        public void sayHello()
        {
                System.out.println("hello~");            (3)
        }
}

++++++++++++++++++++++++++++++++++
//定义一个子类:Student
public class Student extends Person
{
        int id;

        public Student(String name, int age, int id)                  (4)
        {
                super.name = name;         
super.age = age;
                this.id = id;
        }

        public void sayHello()
        {
                System.out.println("hello,I'm "+name);                 (6)
        }
}
++++++++++++++++++++++++++++++++++

//测试类:StudentDemo
public class StudentDemo
{
        public static void main(String[] args)
        {
                Student s = new Student("zhangsan",20,1301);             (1)
                s.sayHello();                                                           (5)
        }        
}
+++++++++++++++++++++++++++++++++++++++


以上代码输出结果如下:
hello,I'm null
hello,I'm zhangsan
回复 使用道具 举报
  1. public class Student extends Person
  2. {
  3.         int id;

  4.         public Student(String name, int age, int id)
  5.         {
  6.                 //这里隐含着一个  super();
  7.                 super.name = name;
  8.                 super.age = age;
  9.                 this.id = id;
  10.         }

  11.         public void sayHello()
  12.         {
  13.                 System.out.println("hello,I'm "+name);
  14.         }
  15. }
复制代码
1  子类和父类  类名前的public 修饰要去掉,因为文件名称要和被public修饰的类名相同,你有三个类名,不知道该命名哪个
2   子类构造函数第一行隐含着 super(); 调用父类构造函数,因为父类构造函数只有一个调用 sayHello方法  而且此方法被子类复写了。所以会调用子类的sayHello方法,此时没有
    赋值给name 自动初始化为null  这就是第一个行结果的原因
3  执行完父类构造函数后  继续执行下面的  用 name给 父类name赋值了 ,在主函数中 s.sayHello();运行  输出第二行结果。
4  此文件我给完整的修改好后应该如下。
  1. //定义一个父类:Person
  2. class Person //去掉public
  3. {
  4.         String name;
  5.         int age;

  6.         public Person(String name,int age)//添加参数
  7.         {
  8.               this.name=name;//给name和age赋值
  9.                           this.age=age;
  10.                                 this.sayHello();
  11.         }
  12.         
  13.         public void sayHello()
  14.         {
  15.                 System.out.println("hello~");
  16.         }
  17. }

  18. //++++++++++++++++++++++++++++++++++
  19. //定义一个子类:Student
  20. class Student extends Person //去掉public
  21. {
  22.         int id;

  23.         public Student(String name, int age, int id)
  24.         {
  25.                 super(name,age);
  26.                                 //super.name = name;//去父类中赋值了 这里注释掉
  27.                 //super.age = age;
  28.                 this.id = id;
  29.         }

  30.         public void sayHello()
  31.         {
  32.                 System.out.println("hello,I'm "+name);
  33.         }
  34. }
  35. //++++++++++++++++++++++++++++++++++

  36. //测试类:StudentDemo
  37. public class StudentDemo
  38. {
  39.         public static void main(String[] args)
  40.         {
  41.                 Student s = new Student("zhangsan",20,1301);
  42.                 s.sayHello();
  43.         }        
  44. }
  45. //+++++++++++++++++++++++++++++++++++++++
复制代码

评分

参与人数 1技术分 +1 收起 理由
洪建超 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 邹学良 于 2013-3-7 12:14 编辑

hello,i'm null”之所以会被输出
是因为在调用SUPER()后,Person类里边构造方法中的 this.sayHello
表面上看this代表的是Person的当前实例
实际上代码是放在System的构造器中的,相当于:
public Student(String name, int age, int id)
        {      this.sayHello();      //Person中this.sayHello对于JAVA编译而言所在的位置
                super.name = name;
                super.age = age;
                this.id = id;

所以this最终代表的是Student的当前实例,
编译类型是Person而实际引用一个Student对象。
指向的是Person name的初始值NULL
所以结果会输出结果如下:
hello,I'm null
hello,I'm zhangsan
回复 使用道具 举报
[野狼]~@ 发表于 2013-3-5 23:09
//定义一个父类:Person
class Person
{

可能我理解能力比较差,让我消化消化先
回复 使用道具 举报
门文通 发表于 2013-3-5 23:25
1  子类和父类  类名前的public 修饰要去掉,因为文件名称要和被public修饰的类名相同,你有三个类名,不知 ...

您这么一讲我清楚了好多,谢谢:hug:
回复 使用道具 举报
邹学良 发表于 2013-3-5 23:32
hello,i'm null”之所以会被输出
是因为在调用SUPER()后,Person类里边构造方法中的 this.sayHello
表面 ...

谢谢你的回答,现在已经明白了
回复 使用道具 举报
克零岚 发表于 2013-3-5 23:23
下面是你的代码,标注的数字(1)(2)....(6)是执行的顺序,参照我上面给的说明你就明白了
//定义一个父 ...

确实清晰不少,哈哈,有劳啦
回复 使用道具 举报
乔_博_文 发表于 2013-3-5 23:47
您这么一讲我清楚了好多,谢谢

没事  互相学习嘛
回复 使用道具 举报
乔_博_文 发表于 2013-3-5 23:47
您这么一讲我清楚了好多,谢谢

没事  互相学习嘛
回复 使用道具 举报
已经明白啦,谢谢各位的指教,灰常灰常感谢
回复 使用道具 举报
package fuzi;
public class StudentDemo
{
        public static void main(String[] args)
        {
               Student s = new Student("zhangsan",20,1301);
                s.sayHello();
                System.out.println(s);//打印地址  fuzi.Student@1bbf1ca
        }        
}
class Person
{
        String name;
        int age;
        public Person()
        {
         System.out.println(this); //打印地址   ,与子类对象的地址一致fuzi.Student@1bbf1ca
            this.sayHello();                  
        }
        
        public void sayHello()
        {
                System.out.println("hello~");
        }
}
class Student extends Person
{
        int id;
        public Student(String name, int age, int id)
        {
                super.name = name;
                super.age = age;
                this.id = id;
        }
        public void sayHello()
        {
                System.out.println("hello,I'm "+name);
        }
}
//从上面的测方式可以知道,this和s都是指向同一地址(子类对象的地址)
下面是我猜的一个初始化图:


初始化.png (22.13 KB, 下载次数: 19)

初始化

初始化
回复 使用道具 举报
谢洋 发表于 2013-3-5 23:55
package fuzi;
public class StudentDemo
{

确实很有帮助,谢谢你的分析
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马