非静态代码块和实例初始化方法 非静态代码块和构造器和显式赋值之间的执行顺序

非静态代码块和实例初始化方法

类的成员: (1)属性 (2)方法 (3) 构造器

类的第四成员:代码块

作用:为属性初始化

一、非静态代码块

1、语法格式
【修饰符】 class 类名 【extends 父类】{
{
非静态的代码块
}
}

2、执行特点
(1)在创建对象的时候自动执行,每创建一个对象就执行一次
如果有多个非静态的代码块,按照顺序执行
(2)先与构造器执行的
(3)非静态代码块与属性的显示赋值他两谁在上面谁先执行
(4)如果创建了子类的对象,会先执行父类的非静态代码块、父类的属性的显试赋值、父类的构造器

3、实例初始化(…)
(1) .java代码编译为 .class时,会把diamante重新组装,如果类中有n个构造器,就会重新组装为n个实例化初始方法。
无参构造 -> ()
有参构造 -> (形参列表)

(2)实例初始化方法由三个部分组成
(A)属性的显式赋值语句
(B)非静态代码块语句
(C)构造器语句
其中(A)(B)是按照顺序组装的,但是(C)无论放在那里,都在最后

(3)创建子类对象的时候会先调用父类的实例化方法

public class TestNonStaticBlock {
	public static void main(String[] args) {
		Son s1 = new Son();

		
		//构造器是最后执行的所以num的值是3
		System.out.println(s1.getNum());//3
		
	}
}

class Father{
	Father(){
		System.out.println("父类的无参构造");
	}
	{
		System.out.println("父类的非静态的代码块1");
	}
	
	{
		System.out.println("父类的非静态的代码块2");
	}
	
	private int i= getNumberI();//为i属性赋值的
	
	public int getNumberI() {
		System.out.println("getNumberI()");
		return 1;
	}

	public int getI() {
		return i;
	}

	
}

class Son extends Father{
	
	Son(){
		System.out.println("无参构造");
		num = 3;
	}
	{
		System.out.println("非静态的代码块1");
		num = 2;
	}
	
	{
		System.out.println("非静态的代码块2");
	}
	
	private int num= getNumber();//为num属性赋值的
	
	public int getNumber() {
		System.out.println("getNum()");
		return 1;
	}

	public int getNum() {
		return num;
	}
	
	
}



在这里插入图片描述

下面程序运行时的内存顺序
在这里插入图片描述

非静态代码块和构造器和显式赋值之间的执行顺序(题目很重要,有时间得看一下)

练习一
public class TestInit1 {
	public static void main(String[] args) {
		A obj = new A(20);
	}
}
class A{
	private int a = getInt();
	
	{
		a++;
		System.out.println("(1)A非静态代码块");
		System.out.println("(1)a = " + a);
	}
	
	A(int num){
		a = num;
		System.out.println("(2)A有参构造");
		System.out.println("(2)a = " + a);
	}
	
	private int getInt(){
		System.out.println("(3)A->getInt");
		System.out.println("(3)a = " + a);
		return 1;
	}
}

/*
(3)A->getInt
(3)a = 0
(1)A非静态代码块
(1)a = 2
(2)A有参构造
(2)a = 20
 */

在这里插入图片描述

练习二
/*
实例初始化的过程:
	(1)实例初始化:调用/执行 实例初始化的方法<init>(...)
	(2)实例初始化方法的方法体由三个部分组成
	第一 属性显示赋值
	第二 非静态代码块
	第三 构造器
	(3)创建子类对象的时候会先执行父类的实例初始化方法
 */

public class TestInit2 {
	public static void main(String[] args) {
		A obj = new B(20);
	}
}
class A{
	private int a = getInt();
	
	{
		a++;
		System.out.println("(1)非静态代码块");
		System.out.println("(1)a = " + a);
	}
	
	A(int num){
		a = num;
		System.out.println("(2)A:有参构造");
		System.out.println("(2)a = " + a);
	}
	
	public int getInt(){
		System.out.println("(3)A->getInt");
		System.out.println("(3)a = " + a);
		return 1;
	}
}
class B extends A{
	private int b = getIntValue();
	
	{
		b++;
		System.out.println("(1)B:非静态代码块");
		System.out.println("(1)b = " + b);
	}
	
	B(int num){
		super(num);
		b = num;
		System.out.println("(2)B:有参构造");
		System.out.println("(2)b = " + b);
	}
	
	public int getIntValue(){
		System.out.println("(3)B->getIntValue");
		System.out.println("(3)b = " + b);
		return 1;
	}
}

/*
(3)A->getInt
(3)a = 0
(1)非静态代码块
(1)a = 2
(2)A:有参构造
(2)a = 20
(3)B->getIntValue
(3)b = 0
(1)B:非静态代码块
(1)b = 2
(2)B:有参构造
(2)b = 20
 */

在这里插入图片描述

练习三

(里面有关于多态重写的问题,比较复杂好好看看)
如果看了不是很懂的话再去看看练习四的注释

/*
实例初始化的过程:
	(1)实例初始化:调用/执行 实例初始化的方法<init>(...)
	(2)实例初始化方法的方法体由三个部分组成
	第一 属性显示赋值
	第二 非静态代码块
	第三 构造器
	(3)创建子类对象的时候会先执行父类的实例初始化方法
	
	(4) 注意:通常面试题当中注意方法重写的问题
	
父类A的实例初始化的方法<init>(...)
❤❤(1)a = getInt();  --> 等价于a = this.getInt()  这个this表示当前的对象,表示正在创建的对象,现在正在创建的是子类的对象,那么通过子类的对象调用getInt()是执行子类的重写的getInt()
(2){
		a++;
		System.out.println("(1)非静态代码块");
		System.out.println("(1)a = " + a);
	}
(3)构造器
        a = num;
		System.out.println("(2)A:有参构造");
		System.out.println("(2)a = " + a);

子类B的实例初始化的方法<init>(...)
(1)b = getInt();
(2){
		b++;
		System.out.println("(1)B:非静态代码块");
		System.out.println("(1)b = " + b);
	}
(3)构造器
		super(num);
		b = num;
		System.out.println("(2)B:有参构造");
		System.out.println("(2)b = " + b);
 */
public class TestInit3 {
	public static void main(String[] args) {
		A obj = new B(20);
	}
}
class A{
	private int a = getInt();//这个地方有一个陷阱,注意是重写
	
	{
		a++;
		System.out.println("(1)非静态代码块");
		System.out.println("(1)a = " + a);
	}
	
	A(int num){
		a = num;
		System.out.println("(2)A:有参构造");
		System.out.println("(2)a = " + a);
	}
	
	public int getInt(){
		System.out.println("(3)A->getInt");
		System.out.println("(3)a = " + a);
		return 1;
	}
}
class B extends A{
	private int b = getInt();
	
	{
		b++;
		System.out.println("(1)B:非静态代码块");
		System.out.println("(1)b = " + b);
	}
	
	B(int num){
		super(num);
		b = num;
		System.out.println("(2)B:有参构造");
		System.out.println("(2)b = " + b);
	}
	
	public int getInt(){
		System.out.println("(3)B->getInt");
		System.out.println("(3)b = " + b);
		return 1;
	}	
}

/*
 (3)A->getInt
 (3)a = 0
 (1)非静态代码块
 (1)a = 2
 (2)A:有参构造
 (2)a = 20
 */

在这里插入图片描述

练习四
/*
 *Override或者Overwrite  重写  覆盖
 *this在类中,就看的是A类中的getInt(),就近原则,因为这个getInt没有被覆盖掉
 *如果getInt()被重写,被覆盖,即使在A类中,通过子类的对象this,看到的只有子类重写后的getInt()方法 
 * 
 */

public class TestInit4 {
	public static void main(String[] args) {
		A obj = new B(20);
	}
}
class A{
	private int a = getInt();//因为getInt() 方法是private,在子类中不可见不会被重写
	//虽然这个地方也是this.getInt(),但是子类中是私有的,所以根据就近原则调用的父类的getInt()
	{
		a++;
		System.out.println("(1)非静态代码块");
		System.out.println("(1)a = " + a);
	}
	
	A(int num){
		a = num;
		System.out.println("(2)A:有参构造");
		System.out.println("(2)a = " + a);
	}
	
	private int getInt(){
		System.out.println("(3)A->getInt");
		System.out.println("(3)a = " + a);
		return 1;
	}
}
class B extends A{
	private int b = getInt();
	
	{
		b++;
		System.out.println("(1)B:非静态代码块");
		System.out.println("(1)b = " + b);
	}
	
	B(int num){
		super(num);
		b = num;
		System.out.println("(2)B:有参构造");
		System.out.println("(2)b = " + b);
	}
	
	private int getInt(){
		System.out.println("(3)B->getInt");
		System.out.println("(3)b = " + b);
		return 1;
	}	
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值