Java学习笔记 —— 对象与内存控制(二)

不得不提的知识点一 —— Java构造器的职能

Java对象是由构造器创建的吗?大多数人可能会回答是!但实际情况是:构造器只是负责对Java对象实例变量执行初始化(也就是赋初值),在执行构造器代码之前,该对象所占内存已经被分配下来,这些内存中存储的都是默认值,0、false或是null。

不得不提的知识点二 —— 静态代码块

当创建任何Java对象时,静态代码块总是会在对象初始化时进行初始化,在同一个JVM下,重复实例化多个Java对象,静态代码块只执行一次;如下面这段代码所示:

class Parent{
	static{
		System.out.println("Parent的静态代码块");
	}
	public Person(){
		System.out.println("Parent的无参构造函数");
	}
}
class Men extends Parent{
	static{
		System.out.println("Men的静态代码块");
	}
	public Men(){
		System.out.println("Men的无参构造函数");
	}
}
public class InitTest{
	public static void main(String[] args){
		new Men();
		// new Men(); //再次调用实例化Men
	}
}

输出结果为:

Parent的静态代码块
Men的静态代码块
Parent的无参构造函数
Men的无参构造函数

当在一次调用实例化Men时,输出结果为:

Parent的静态代码块
Men的静态代码块
Parent的无参构造函数
Men的无参构造函数
Parent的无参构造函数
Men的无参构造函数

细心的你,也许会发现,静态代码块出现的位置总是会出现在最上面,并且由父及子,这没什么奇怪的,我们之前已经说过了,静态代码块总是会在对象初始化时完成初始化。
有了这么一个前话,下面,我们的讲解将不再考虑静态初始化代码块的执行时间。

父类构造器

当创建任何Java对象时,程序总是会先依次调用父类非静态初始化块、父类构造器(总是从Object类开始)执行初始化,最后才调用本类的非静态初始化块、构造器执行初始化。这个调用时隐式进行的,也可以通过super进行显式调用。

  • 关于super与this

子类构造器的第一行使用super()显示调用父类构造器的无参构造方法,也可写入参数,指定调用父类的有参构造方法;与super()相对的是this(),this()放在构造方法的第一行,用于显示调用本类的构造方法,同样可指定参数。由于super() 与 this() 只能放在构造器中且只能放在第一行,所以构造器中只能由super()或this()中的一个且在第一行。既没有super(),又没有this()的情况,将会隐式调用无参构造方法。

执行步骤如下;
1、执行Object类的非静态初始化(如果有的话)
2、隐式或显式调用Object类的一个或多个构造器执行初始化
3、执行Parent类的非静态初始化(如果有的话)
4、隐式或显式调用Parent类的一个或多个构造器执行初始化
5、执行Son类的非静态初始化块(如果有的话)
6、隐式或显式调用Son类的一个或多个构造器执行初始化

class Creature{
	{
		System.out.println("Creature的非静态初始化块");
	}
	public Creature() {
		System.out.println("Creature无参构造器");
	}
	public Creature(String name) {
		this();
		System.out.println("Creature带有name参数的构造器,name参数:" + name);
	}
}
class Animal extends Creature{
	{
		System.out.println("Animal的非静态初始化块");
	}
	public Animal(String name) {
		super(name);
		System.out.println("Animal带一个参数的构造器,name参数:" + name);
	}
	public Animal(String name, int age) {
		this(name);
		System.out.println("Animal带2个参数的构造器,age:" + age);
	}
}
class Wolf extends Animal{
	{
		System.out.println("Wolf的非静态初始化块");
	}
	public Wolf() {
		super("灰太狼", 3);
		System.out.println("Wolf无参构造器");
	}
	public Wolf(double weight) {
		this();
		System.out.println("Wolf的带weight参数的构造器,weight:" + weight);
	}
}
public class InitTest {
	public static void main(String[] args) {
		new Wolf(5.6);
	}
}

运行结果

Creature的非静态初始化块
Creature无参构造器
Creature带有name参数的构造器,name参数:灰太狼
Animal的非静态初始化块
Animal带一个参数的构造器,name参数:灰太狼
Animal带2个参数的构造器,age:3
Wolf的非静态初始化块
Wolf无参构造器
Wolf的带weight参数的构造器,weight:5.6

访问子类对象的实例变量

子类方法可以访问父类的实例变量,这是因为子类继承父类就会获得父类的成员变量和方法,但父类的方法不能访问子类的实例变量,因为父类根本无法知道它将被哪个子类继承,它的子类将会增加怎样的成员变量

未完,待续…

所谓迷茫,就是你的才华还配不上你的梦想

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值