[200127] Java类初始化与实例初始化 - Thinking in Java学习日志

类初始化

类初始化顺序

在这里插入图片描述

类初始化实例

父类定义

package com.phycanva.demonstrate;

public class Father_init{
	private int i = test();				//非静态变量显式赋值
	private static int j = method();	//静态变量显式赋值
	static {							//静态代码块
		System.out.println("父类静态代码块");
	}
	Father_init(){						//构造器
		System.out.println("父类构造器");
	}
	{									//非静态代码块
		System.out.println("父类非静态代码块");
	}
	public int test(){
		System.out.println("父类非静态变量显式赋值");
		return 1;
	}
	public static int method(){	
		System.out.println("父类静态变量显式赋值");
		return 1;
	}
}	

子类定义

package com.phycanva.demonstrate;

public class Son_init extends Father_init{
	
	private int i = test();				//非静态变量显式赋值
	private static int j = method();	//静态变量显式赋值
	static {							//静态代码块
		System.out.println("子类静态代码块");
	}
	Son_init(){							//构造器
		System.out.println("子类构造器");
	}
	{									//非静态代码块
		System.out.println("子类非静态代码块");
	}
	public int test(){
		System.out.println("子类非静态变量显式赋值");
		return 1;
	}
	public static int method(){	
		System.out.println("子类静态变量显式赋值");
		return 1;
	}
	
	public static void main(String[] args) {
	}
}

在main函数里没有进行任何实例化操作,所有的类初始化的动作,都会被反映在标准输出中

运行结果:

父类静态变量显式赋值
父类静态代码块
子类静态变量显式赋值
子类静态代码块

小结

类初始化从main函数所在类开始,以下行为会触发类初始化:

(1)创建类的实例。为某个类创建实例的方式包括:使用new操作符来创建实例,通过反射来创建实例,通过反序列化的方式来创建实例。
(2)调用某个类的类方法(静态方法)。
(3)访问某个类变量或为某个类变量。或为该变量赋值
(4)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。例如:Class,forName(“Person”),如果系统还未初始化Person类,则先初 始化Person类,然后返回Person类对应的java.lang.Class对象。
(5)初始化某个类的子类。子类的父类都会被初始化。
(6)直接使用java.exe命令运行某个主类,主类先被初始化。
-----注意: 对于一个final型的类变量,如果该变量的值在编译期就可以确定下来,那么这个类变量相当于“宏变量”,java编译器会在编译时直接把这个类变量出现的地方全部替换为它的值。因此即使程序使用静态变量,也不会导致该类的初始化。如下代码将不会打印出静态初始化块

以上内容转载自Mr_Monkey95512 - 什么时候进行java类的初始化

类初始化可以理解为是“静态初始化”,执行的是“静态变量显式赋值代码”和“静态代码块”,它们内部遵循代码书写的先后顺序;此外,在继承关系中初始化遵循父→子顺序。

实例初始化

实例初始化顺序

在这里插入图片描述

实例初始化实例

代码在 类初始化实例 的基础上在main函数中增添实例化语句:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("子类实例1");
		Son_init s1 = new Son_init();
		System.out.println("子类实例2");
		Son_init s2 = new Son_init();	
	}

运行结果:

父类静态变量显式赋值
父类静态代码块
子类静态变量显式赋值
子类静态代码块
子类实例1
子类非静态变量显式赋值
父类非静态代码块
父类构造器
子类非静态变量显式赋值
子类非静态代码块
子类构造器
子类实例2
子类非静态变量显式赋值
父类非静态代码块
父类构造器
子类非静态变量显式赋值
子类非静态代码块
子类构造器

可以看到输出由三个部分组成:类初始化、实例1初始化、实例初始化2,且两个实例初始化结果相同,我们提取实例1初始化的结果:

子类实例1
子类非静态变量显式赋值
父类非静态代码块
父类构造器
子类非静态变量显式赋值
子类非静态代码块
子类构造器

在第二行中出现了“子类非静态变量显式赋值”,而非“父类非静态变量显式赋值”。这是因为在调用非静态方法的时候,我们传入的this指向的是一个子类的对象,此时调用的test()方法就是子类重写的test()。

小结

实例初始化可以理解为是“非静态初始化”,执行的是“非静态变量显式赋值代码”和“非静态代码块”,它们内部遵循代码书写的先后顺序,在以上代码执行结束后最后执行构造器;此外,在继承关系中初始化遵循父→子顺序,并且需要注意其覆写效应。

后记

由于仍处于学习阶段,文章中的内容很可能不够准确也不够全面。文中若有错误出现,敬请指出,一定虚心改正;有需要补充修改的地方,也请各位不吝赐教,十分乐意与大家交流学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值