Java初始化

1.      自动初始化

    变量使用之前进行初始化是良好的编程习惯。和C/C++相比,Java提供了完善的初始化机制,对于类的成员变量如果没有手动进行初始化,Java会进行默认初始化,C++不会做这种事情:

public class InitializeDefault {

	byte a;
	short b;
	int c;
	long d;
	float e;
	double f;
	char g;
	boolean h;
	
	public static void main(String[] args) {
		InitializeDefault t = new InitializeDefault();
		System.out.println("byte = " + t.a + "\n"
				+ "short = " + t.b + "\n"
				+ "int = " + t.c + "\n"
				+ "long = " + t.d + "\n"
				+ "float = " + t.e + "\n"
				+ "double = " + t.f + "\n"
				+ "char = " + (int)t.g + "\n"
				+ "boolean = " + t.h + "\n");
	}
}	

    以上代码的输出为:

byte = 0
short = 0
int = 0
long = 0
float = 0.0
double = 0.0
char = 0
boolean = false

    所有变量都被设置成默认值了。对于函数内部的局部变量,和C/C++相同,Java不会自动对它们进行初始化,但是Java会提示编译时错误。

    对于自动进行的初始化操作,总是在用户主动初始化(如构造函数)之前发生,这是显然的。

2.      手动初始化

    成员变量手动初始化有3种方式:定义变量时直接初始化、初始化块、构造函数。直接初始化、初始化块在构造函数调用之前执行。

public class InitializeManual {
	
	InitializeManual(int a, short b) {
		this.a = a;
		this.b = b;
		System.out.println("constructor called");
	}
	
	// 定义时直接初始化
	int a = f1();
	short b = 99;
	
	int f1() {
		System.out.println("func f1 called");
		return 99;
	}
	
	// 初始化块
	{
		System.out.println("initialization block called");
		a = 50;
	}
	
	public static void main(String[] args) {
		InitializeManual t = new InitializeManual(1, (short) 2);
		System.out.println(t.a + " " + t.b);
	}
}

    输出结果为:

func f1 called
initialization block called
constructor called
1 2

    变量a调用函数f1()进行初始化,从结果可见定义变量时直接赋值、初始化块先于构造函数执行。直接赋值、初始化块的进行顺序取决于在类内的位置,从上向下依次执行,上例中成员变量a直接赋值操作在初始化块之前,所以先调用f()函数。

3.      静态变量

    静态变量对于一个类只有一个实例,与C/C++中的全局变量很像。静态变量的初始化先于非静态变量进行。虚拟机加载一个类时,静态变量就开始初始化了。什么时候一个类要被加载呢?有多种情况:(1)定义了一个类的对象;(2)访问类的静态数据或函数。还有其他几种使用到类的情况都会触发加载操作。加载只进行一次,静态变量也只初始化一次。

public class InitializeStatic {
	static int a;
	int b;

	// 构造函数
	InitializeStatic() {
		System.out.println("construct called");
		a = 10;
		b = 20;
	}
	
	// 初始化块
	{
		System.out.println("non static init block");
		b = 2;
	}
	
	// 静态初始化块
	static {
		System.out.println("static init block");
		a = 1;
		c = 2;
	}
	
	// 直接赋值
	static int c = f();
	
	static int f() {
		System.out.println("static func f called");
		return 99;
	}
	
	public static void main(String[] args) {
		InitializeStatic t = new InitializeStatic();
		System.out.println("a = " + t.a + " b = " + t.b + " c = " + t.c);
	}
}	

    以上代码的输出为:

static init block
static func f called
non static init block
construct called
a = 10 b = 20 c = 99

    代码中new了一个InitializeStatic对象,先进行静态成员的初始化,然后进行非静态成员的初始化,最后进行构造函数。静态变量可以在定义时初始化或在静态初始化块中初始化,这两种代码的初始化顺序取决于在类内部的声明顺序,由上而下执行,和非静态变量的初始化顺序类似。

     如果在main函数中只访问InitializeStatic的静态成员变量,不创建对象,即把InitializeStatic的main函数改成如下形式:

public static void main(String[] args) {
	System.out.println("InitializeStatic.a = " + InitializeStatic.a);
}
    则InitializeStatic的输出为:
static init block
static func f called
InitializeStatic.a = 1

    这时只进行了静态成员变量的初始化操作,非静态变量还没有初始化。

4.      继承初始化

    继承时的初始化比较复杂。所有静态变量的初始化先于非静态变量的初始化,即先进行基类和派生类的静态初始化,然后进行基类初始化,最后进行派生类初始化。基类和派生类静态变量都有直接初始化和初始化块两种方式,初始化顺序按声明顺序,见上文第3点。基类初始化和派生类初始化见第1、2点。
class Base {
	{
		System.out.println("base init block");
	}
	
	static {
		System.out.println("base static init block");
	}
	
	Base() {
		System.out.println("base constructor");
	}
}

class Derive extends Base {
	{
		System.out.println("derive init block");
	}
	
	static {
		System.out.println("derive static init block");
	}
	
	Derive() {
		System.out.println("derive constructor");
	}
}

public class InitializeInherit {
	public static void main(String[] args) {
		Derive d = new Derive();
	}
}
    以上代码输出为:

base static init block
derive static init block
base init block
base constructor
derive init block
derive constructor









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值