1 非静态代码块
非静态代码块特点
①可以为实例变量(非静态的属性)初始化
②每次创建对象的时候,都会执行一次,且先于构造器执行
③若有多个非静态的代码块,那么按照定义的顺序从上到下依次执行
④代码块中既可以调用非静态的变量和方法,也可以可以调用静态的变量和方法
测试代码:
public class BlockTest {
public static void main(String[] args) {
MyClass my1 = new MyClass();
//MyClass my2 = new MyClass("java");
}
}
class MyClass {
private String str;
{
System.out.println("非静态代码块1");
}
public MyClass() {
System.out.println("无参构造");
}
public MyClass(String str) {
this.str = str;
System.out.println("有参构造");
}
{
System.out.println("非静态代码块2");
}
}
运行结果:
非静态代码块1
非静态代码块2
无参构造
2 实例初始化
实例初始化过程:创建对象时,为对象进行初始化的操作
①为成员变量显式赋值
②执行非静态代码块
③执行构造器
Java编译器会把这三个部分的代码,合成一个叫做 <init>([形参列表])
实例初始化方法
即编译后的.class字节码信息中,是没有构造器这个概念。
<init>([形参列表])
实例初始化方法的代码就是由三个部分组成:
①成员变量显式赋值的代码
②非静态代码块中的代码
③构造器中的代码
其中①和②按定义顺序依次执行,③最后执行。
而且,有几个构造器,就会有几个实例初始化方法。那么当你创建对象的时候,调用对应的构造器时,其实执行的是对应的实例初始化方法 <init>([形参列表])
代码示例:
public class InitTest {
public static void main(String[] args) {
Demo d1 = new Demo();
//Demo d2 = new Demo("java");
}
}
class Demo{
{
System.out.println("非静态代码块1");
}
private String str = assign();//调用方法,为str进行显式赋值
public Demo(){
System.out.println("无参构造");
}
public Demo(String str){
this.str = str;
System.out.println("有参构造");
}
{
System.out.println("非静态代码块2");
}
public String assign(){
System.out.println("为成员变量赋值");
return "hello";
}
}
3 子类实例初始化
(1)先执行父类的实例初始化方法
它由三部分组成:
-
成员变量的显式赋值
-
非静态代码块
-
构造器
(2)再执行子类的实例初始化方法
它由三部分组成:
-
成员变量的显式赋值
-
非静态代码块
-
构造器
super()或super(实参列表) 表面是调用父类的构造器,其实是调用父类对应的实例初始化方法
super()或super(实例列表) 表面是在子类构造器的首行,其实是在子类实例初始化方法的首行
代码示例:
public class InitTest2 {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father {
private String strFather = assignFather();
{
System.out.println("父类的非静态代码块");
}
public Father(){
System.out.println("父类的无参构造");
}
public String assignFather(){
System.out.println("父类的assignFather()");
return "father";
}
}
class Son extends Father {
private String strSon = assignSon();
{
System.out.println("子类的非静态代码块");
}
public Son(){
//super() ==> 调用父类的实例初始化方法,而且它在子类实例初始化方法的首行
System.out.println("子类的无参构造");
}
public String assignSon(){
System.out.println("子类的assignSon()");
return "son";
}
}
运行结果:
父类的assignFather()
父类的非静态代码块
父类的无参构造
子类的assignSon()
子类的非静态代码块
子类的无参构造
子类为成员变量显式赋值方法重写父类显式赋值方法时,调用的子类重写的方法,代码示例:
public class InitTest3 {
public static void main(String[] args) {
Son s = new Son();
}
}
class Father {
private String strFu = assign();
{
System.out.println("父类的非静态代码块");
}
public Father(){
System.out.println("父类的无参构造");
}
public String assign(){
System.out.println("父类的assign()");
return "father";
}
}
class Son extends Father {
private String strSon = assign();
{
System.out.println("子类的非静态代码块");
}
public Son(){
//super() ==>调用父类的实例初始化方法,而且它在子类实例初始化方法的首行
System.out.println("子类的无参构造");
}
public String assign(){
System.out.println("子类的assign()");
return "son";
}
}
运行结果:
子类的assign()
父类的非静态代码块
父类的无参构造
子类的assign()
子类的非静态代码块
子类的无参构造