初始化执行顺序疑惑为啥打印null呢

浩哥爱学习 2021-05-18 09:14:16
class Person{
String str= "aa";
Person(){
show();
}
public void show(){
System.out.println(str);
}
}
class Student extends Person{
private String str = "bb";
@Override
public void show() {
System.out.println(str);
}
}
class Test3{
public static void main(String[] args){
Person p = new Student() ;
}
}

这个为啥打印null呢,父类的构造的调用的show方法为啥是子类的show呢
...全文
13725 10 打赏 收藏 举报
写回复
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
冰思雨 2021-05-24
封装和继承的概念的理解。 类里面的成员函数,无参情况下,只能访问所属类的成员变量,这是封装特性。 继承的意思是,子类可以继承父类的函数。 这里面,父类的函数,当然只能访问父类的成员变量咯。和子类的成员变量没有什么关系的,否则,就不叫封装了。 再者,继承的时候,除了访问关键字之外,同名属性不能继承的。这个与方法不同,同名函数可以覆盖/重写,但是,同名属性不存在这种情况。 楼主的代码里面,存在父子类中同名属性的情况,那么,父类使用父类的属性,子类使用子类的属性,使用的意思,就是通过函数调用来实现的,继承的函数由于封装特性存在,所以,不会因为是继承来的函数就会改变访问的属性对象。 怎样突破封装? 子类覆盖(或重写)函数,使得函数访问自己的成员变量即可。
  • 打赏
  • 举报
回复
浩哥爱学习 2021-05-22
引用 12 楼 浩哥爱学习 的回复:
[quote=引用 11 楼 爱吃蛋炒饭。 的回复:][quote=引用 2 楼 demo0813 的回复:]因为创建是子类Student对象,this指向student对象,所以调用子类Student的show 打印null是因为类的加载顺序,父类构造方法调用的时候子类方法的时候,子类Student成员变量还未初始化,所以是null
大佬能看看我的代码吗?
package 测试类;
public class Test1 {
    public static void main(String[] args){
        Vip v = new Vip("张三");
        v.shopping();
        v.doSome();
        System.out.println(v);
    }
}
class Customer {
    String name;
    public Customer(){}
    public Customer(String name){
        super();
        this.name = name;
    }

    public void doSome(){
        System.out.println(this.name + " do some!父类");
        System.out.println(name + " do some!父类");
        System.out.println("Customer的toString: "+toString());
    }
}
class Vip extends Customer{

    String name; // 实例变量

    public Vip(){
    }
    public Vip(String name){
        super(name);
        // this.name = null;
    }
    public void shopping(){
        System.out.println(this.name + "正在购物!子类");
        System.out.println(super.name + "正在购物!子类");
        System.out.println(name + "正在购物!子类");
        System.out.println("Vip的toString: "+toString());
    }
}
/* 运行结果
null正在购物!子类
张三正在购物!子类
null正在购物!子类
Vip的toString: 测试类.Vip@1b6d3586
张三 do some!父类
张三 do some!父类
Customer的toString: 测试类.Vip@1b6d3586
测试类.Vip@1b6d3586
 */
我以前认为this在哪,指向的就是哪里,可现在看来我是错的,那我这个代码又该如何解释呢?[/quote]我也疑惑 继承后 子类调用继承的方法dosome为啥还是父类的属性[/quote]应该是当子类和父类的属性名相同时,遵循一个"就近原则",调用继承父类dosome方法就直接在父类的位置找这个属性值
  • 打赏
  • 举报
回复
浩哥爱学习 2021-05-22
引用 11 楼 爱吃蛋炒饭。 的回复:
[quote=引用 2 楼 demo0813 的回复:]因为创建是子类Student对象,this指向student对象,所以调用子类Student的show 打印null是因为类的加载顺序,父类构造方法调用的时候子类方法的时候,子类Student成员变量还未初始化,所以是null
大佬能看看我的代码吗?
package 测试类;
public class Test1 {
    public static void main(String[] args){
        Vip v = new Vip("张三");
        v.shopping();
        v.doSome();
        System.out.println(v);
    }
}
class Customer {
    String name;
    public Customer(){}
    public Customer(String name){
        super();
        this.name = name;
    }

    public void doSome(){
        System.out.println(this.name + " do some!父类");
        System.out.println(name + " do some!父类");
        System.out.println("Customer的toString: "+toString());
    }
}
class Vip extends Customer{

    String name; // 实例变量

    public Vip(){
    }
    public Vip(String name){
        super(name);
        // this.name = null;
    }
    public void shopping(){
        System.out.println(this.name + "正在购物!子类");
        System.out.println(super.name + "正在购物!子类");
        System.out.println(name + "正在购物!子类");
        System.out.println("Vip的toString: "+toString());
    }
}
/* 运行结果
null正在购物!子类
张三正在购物!子类
null正在购物!子类
Vip的toString: 测试类.Vip@1b6d3586
张三 do some!父类
张三 do some!父类
Customer的toString: 测试类.Vip@1b6d3586
测试类.Vip@1b6d3586
 */
我以前认为this在哪,指向的就是哪里,可现在看来我是错的,那我这个代码又该如何解释呢?[/quote]我也疑惑 继承后 子类调用继承的方法dosome为啥还是父类的属性
  • 打赏
  • 举报
回复
引用 2 楼 demo0813 的回复:
因为创建是子类Student对象,this指向student对象,所以调用子类Student的show 打印null是因为类的加载顺序,父类构造方法调用的时候子类方法的时候,子类Student成员变量还未初始化,所以是null
大佬能看看我的代码吗?
package 测试类;
public class Test1 {
    public static void main(String[] args){
        Vip v = new Vip("张三");
        v.shopping();
        v.doSome();
        System.out.println(v);
    }
}
class Customer {
    String name;
    public Customer(){}
    public Customer(String name){
        super();
        this.name = name;
    }

    public void doSome(){
        System.out.println(this.name + " do some!父类");
        System.out.println(name + " do some!父类");
        System.out.println("Customer的toString: "+toString());
    }
}
class Vip extends Customer{

    String name; // 实例变量

    public Vip(){
    }
    public Vip(String name){
        super(name);
        // this.name = null;
    }
    public void shopping(){
        System.out.println(this.name + "正在购物!子类");
        System.out.println(super.name + "正在购物!子类");
        System.out.println(name + "正在购物!子类");
        System.out.println("Vip的toString: "+toString());
    }
}
/* 运行结果
null正在购物!子类
张三正在购物!子类
null正在购物!子类
Vip的toString: 测试类.Vip@1b6d3586
张三 do some!父类
张三 do some!父类
Customer的toString: 测试类.Vip@1b6d3586
测试类.Vip@1b6d3586
 */
我以前认为this在哪,指向的就是哪里,可现在看来我是错的,那我这个代码又该如何解释呢?
  • 打赏
  • 举报
回复
引用 5 楼 PNZ.BeijingL 的回复:
因为是new Student(),所以调用的是子类Student.show(), 实例化对象的顺序是,实例化父类成员变量,父类构造, 子类成员变量,子类构造。 因此: 程序先初始化了父类:实例化成员的 str= "aa"; 然后执行其构造,因为实例化是个子类,调用子类show方法,这个时候子类str=null ,所以输出空 程序再初始化子类: 实例化子类成员str="bb" ;然后执行子类构造, 因为子类没有构造所以会自动执行无参的空构造器, 你可以再给student增加相同一个构造,初始化子类的时候,就由于bb初始化了,会多输出bb信息
正解!
  • 打赏
  • 举报
回复
=PNZ=BeijingL 2021-05-21
父类初始化,它的show方法不进栈吗,所以调的子类方法

栈内存本身是不存储方法的,只是你调用的时候才入栈,调用完就出栈,
这就是为什么程序中有死循环或者递归的时候,程序一直不停压栈造城栈内存溢出的原因
  • 打赏
  • 举报
回复
=PNZ=BeijingL 2021-05-19
因为是new Student(),所以调用的是子类Student.show(),
实例化对象的顺序是,实例化父类成员变量,父类构造, 子类成员变量,子类构造。
因此:
程序先初始化了父类:实例化成员的 str= "aa"; 然后执行其构造,因为实例化是个子类,调用子类show方法,这个时候子类str=null ,所以输出空
程序再初始化子类: 实例化子类成员str="bb" ;然后执行子类构造, 因为子类没有构造所以会自动执行无参的空构造器,

你可以再给student增加相同一个构造,初始化子类的时候,就由于bb初始化了,会多输出bb信息
  • 打赏
  • 举报
回复
mmip 2021-05-19
因为创建是子类Student对象,this指向student对象,所以调用子类Student的show 打印null是因为类的加载顺序,父类构造方法调用的时候子类方法的时候,子类Student成员变量还未初始化,所以是null
  • 打赏
  • 举报
回复
你 new 了一个子类对象,用父类去接的.
  • 打赏
  • 举报
回复
浩哥爱学习 2021-05-19
引用 5 楼 PNZ.BeijingL 的回复:
因为是new Student(),所以调用的是子类Student.show(), 实例化对象的顺序是,实例化父类成员变量,父类构造, 子类成员变量,子类构造。 因此: 程序先初始化了父类:实例化成员的 str= "aa"; 然后执行其构造,因为实例化是个子类,调用子类show方法,这个时候子类str=null ,所以输出空 程序再初始化子类: 实例化子类成员str="bb" ;然后执行子类构造, 因为子类没有构造所以会自动执行无参的空构造器, 你可以再给student增加相同一个构造,初始化子类的时候,就由于bb初始化了,会多输出bb信息
父类初始化,它的show方法不进栈吗,所以调的子类方法
  • 打赏
  • 举报
回复
发帖
Java SE
加入

6.2w+

社区成员

Java 2 Standard Edition
社区管理员
  • Java SE
申请成为版主
帖子事件
创建了帖子
2021-05-18 09:14
社区公告
暂无公告