浅论创建子类对象时是否创建了父类对象

这仅仅是我个人的理解,因为是初学者,可能存在理解错误或理解不到位的情况,如有发现,望指出,谢谢!


我们都知道在创建子类对象时,调用子类构造方法前,必须调用父类的构造方法。

那么调用构造方法就代表着创建对象了吗


假设1:
如果创建子类对象没有创建父类对象,那么我们子类继承过来的属性和通过super调用的方法来自哪里?

// 父类A
public class A {
    int i;
    public A() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm a ");
    }

    public void hello() {
        System.out.println("Hello, i'm a");
    }
}
// 子类B
public class B extends A{
    public B() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm b");
    }
    // 重写父类方法
    public void hello() {
    // 调用父类的方法
        super.hello();
        System.out.println("Hello, i'm b");
    }
}
// 通过子类对象去调用父类属性和方法
public class Demo1 {
    public static void main(String[] args) {
        B b = new B();
        b.i = 10;
        System.out.println(b.i);
        b.hello();      
    }
}

结果:
结果

假设2:
1.如果创建子类对象时创建父类对象, 多重继承的子类会浪费很多空间;我们知道所有类都继承与Object类,那样内存中充满了许多相同的Object对象,浪费空间。

// 多重继承 C继承B,B继承A
// 父类A
public class A {
    public A() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm a");
    }
}
// 父类B
public class B extends A {
    public B() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm b");
    }
}
// 子类C
public class C extends B {
    public C() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm c");
    }
}
// 测试 
public class Demo2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        C c = new C();
    }

}

多重继承结果:
多重继承结果
2.如果一个子类是抽象类的子对象,那么创建该子类时,能创建一个抽象类的对象吗?(抽象类不能创建对象).如果能创建,岂不是违反了java的语法规则。

// 实现类会调用抽象类的构造函数,但不意味着创建了抽象类对象
// 抽象父类A
public abstract class A {
    public A() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm a ");
    }
    public abstract void show();
}
// 实现类B
public class B extends A {
    public B() {
        // TODO Auto-generated constructor stub
        System.out.println("I'm b");
    }
    @Override
    public void show() {
        // TODO Auto-generated method stub

    }
}
// 虽然调用了抽象类的构造方法,但没有创建抽象类对象,因为抽象类不能创建对象
public class Demo3 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        B b = new B();
    }

}

抽象类结果:
抽象类结果


创建子类对象时,不会创建父类对象。

明确:
1.创建对象指的是在堆区开辟空间(new)
2.编译器在运行子类构造器之前,必须先执行父类构造器;且调用父类构造器的语句必须在子类构造器的第一行。
3.构造方法的作用是为堆区中的对象的属性初始化,不是创建对象。

类加载时机:
生成该类对象的时候,会初始化该类及该类的所有父类;
访问该类的静态成员的时候(子类中访问父类中定义的静态变量时,只会初始化父类,不会造成子类的初始化);
class.forName(“类名”);

成员方法什么时候加载呢?
成员方法在方法区,方法区的特点是唯一存在,那么成员方法只存在一份。当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。需要注意的是,当我们创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时,不再分配入口地址,也就是说,方法的入口地址被所有的对象共享,当所有的对象都不存在时,方法的入口地址才被取消。

实例化对象的过程:
1.为对象分配内存,执行默认初始化;
2.执行显式初始化,即类成员变量声明时的赋值语句与实例初始化块。 两者顺序执行,并且初始化块中可以对在其之后
声明的属性进行操作(但不能引用)。即:

Class Cat
{
    {
    brand = "Tom";
    }
    String brand;
}

3.执行构造方法;
4.返回对象在内存中的首地址等重要信息。

子类为什么能调用父类的方法?
子类会有一个父类的亚对象,拥有父类的完全属性和方法,但没有自己独立的空间,依赖于子类对象的空间,但不完全属于子类,可以通过super调用,注意:这里的super不是引用,因为亚对象不是真正意义的对象(没有自己的空间),而是一种标识符。

// 亚对象没有自己的空间,需要依赖于子类对象的空间
// 父类
public class A {
    public A() {
        // TODO Auto-generated constructor stub
        System.out.println(this);
    }
}
// 子类
public class B extends A {
    public B() {
        // TODO Auto-generated constructor stub
        System.out.println(this);
    }
}
// 比较内存地址是否相同
public class Demo4 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        B b = new B();
    }

}

结果:
这里写图片描述

// 父类的亚对象,有父类的所有属性和方法
// 子类有亚对象,也就有了父类的所有属性和方法,只是private修饰的变量和方法,子类无法使用
// 父类
public class A {
    private int i;

    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
    }

}
// 子类
public class B extends A {

}
// 看子类能不能通过父类提供public方法访问父类的private属性
public class Demo5 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        B b = new B();
        b.setI(10);
        System.out.println("i=" +b.getI());
    }

}

结果:
这里写图片描述

总结

创建子类对象时,并没有创建父类对象,只是子类对象中有一个父类的亚对象。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值