Java 构造器初始化

原创 2013年12月03日 17:33:13

可以用构造器来进行初始化,但是成员变量的自动初始化是在构造器被调用之前发生的,即成员变量的自动初始化不能被阻止

如以下例子:

public class Counter {
	int count;
	Counter(){
		count = 7;
	}
}
count首先是为0,当调用其构造方法后,才使得count为7.


1.初始化顺序

在类的内部,变量定义的先后顺序决定了其初始化顺序。但变量的初始化操作会在调用任何方法之前完成,包括构造方法,哪怕变量的定义散布于方法定义之间。

如以下例子:

class Window{
	Window(int i){
		System.out.println("Window("+i+")");
	}
}

class House{
	Window window1 = new Window(1);
	House(){
		System.out.println("----I'm contructor method----");
	}
	Window window2 = new Window(2);
	void f(){
		System.out.println("-----I'm f()-----");
	}
	Window window3 = new Window(3);
}

public class Demo {
	
	public static void main(String[] args) {
		House house = new House();
		house.f();
	}
}
当运行这个代码时,其结果为:

Window(1)
Window(2)
Window(3)
----I'm contructor method----
-----I'm f()-----
由此可以看出,Window的几个对象均在House的构造器和f()方法之前便已完成初始化。

2、静态数据的初始化
无论创建多少对象,静态数据都只占据一份存储域。static关键字不能应用于局部变量,因此它只能作用于域。

可以通过一个例子来看静态数据的初始化是如何进行的:

package com.hd.demo;

class Bowl{
	
	Bowl(int i){
		System.out.println("Bowl("+i+")");
	}
	
	void f(int i){
		System.out.println("f("+i+")");
	}
}

class Table{
	static Bowl bolw1 = new Bowl(1);
	Table(){
		System.out.println("----I'm Table contructor method----");
	}
	
	void f(){
		System.out.println("-----I'm f() method in Table-----");
	}
	static Bowl bolw2 = new Bowl(2);
}

class Cupboard{
	Bowl bowl3 = new Bowl(3);
	static Bowl bowl4 = new Bowl(4);
	Cupboard(){
		System.out.println("----I'm Cupboard contructor method----");
		bowl4.f(1);
	}
	void f(){
		System.out.println("-----I'm f() method in Cupboard-----");
	}
	static Bowl bowl5 = new Bowl(5);
}

public class StaticDemo {
	public static void main(String[] args) {
		System.out.println("creating new Cupboard() in main");
		new Cupboard();
		System.out.println("creating new Cupboard() in main");
		new Cupboard();
		table.f();
		cupboard.f();
	}
	static Table table = new Table();
	static Cupboard cupboard = new Cupboard();
}
其运行结果如下:
Bowl(1)
Bowl(2)
----I'm Table contructor method----
Bowl(4)
Bowl(5)
Bowl(3)
----I'm Cupboard contructor method----
f(1)
creating new Cupboard() in main
Bowl(3)
----I'm Cupboard contructor method----
f(1)
creating new Cupboard() in main
Bowl(3)
----I'm Cupboard contructor method----
f(1)
-----I'm f() method in Table-----
-----I'm f() method in Cupboard-----
以上代码有几个需要注意的地方,一个是StaticDemo中在main方法的下面定义了静态数据成员table和cupboard。它们会在main方法执行之前先进行初始化。另一个是Cupboard类中,先定义了一个非静态的bowl3成员。最后就是在main方法中又new了Cupboard对象。

通过以上运行结果可以得出以下结果:

1)、静态初始化只有在必要的时候才会进行,如果不创建Table对象,那么bowl1和bowl2就不会创建。

2)、静态数据只有在第一次被访问时才会进行初始化,此后便不再被初始化。比如,在main方法中new Cupboard,初始化了非静态成员bowl3,而静态成员bowl4和bowl5不再被初始化。

3)、初始化的顺序是先静态对象,后是非静态对象。

3、显示的静态初始化

先看一段代码:

class Cup{
	Cup(int mark){
		System.out.println("Cup("+mark+")");
	}
	
	void f(int mark){
		System.out.println("f("+mark+")");
	}
}

class Cups{
	static Cup cup1 ;
	static Cup cup2 ;
	
	static {
		cup1 = new Cup(1);
		cup2 = new Cup(2);
	}
}



public class ExplicitStatic {
	public static void main(String[] args) {
		Cups.cup1.f(1);	  //(1)
	}
	//static Cups cups1 = new Cups();  //(2)
	//static Cups cups2 = new Cups();  //(3)
}
其运行结果如下:

Cup(1)
Cup(2)
f(1)
假设注释掉(1)的代码,解除(2)或(3)的代码,那么结果就会为:

Cup(1)
Cup(2)
如果同时解除(2)和(3)的代码,其运行结果都是一样的。因为上面已经提到,静态数据只有在第一次被访问时才会初始化,此后便不再初始化。

4、非静态实例初始化

先看一段代码:

class Mug{
	Mug(int i){
		System.out.println("Mug("+i+")");
	}
	
}

public class Mugs {
	Mug mug1;
	Mug mug2;
	{
		mug1 = new Mug(1);
		mug2 = new Mug(2);
	}
	
	Mugs(){
		System.out.println("无参构造器");
	}
	Mugs(int i){
		System.out.println("有参构造器");
	}
	
	public static void main(String[] args) {
		new Mugs();
		new Mugs(1);
	}
}
运行结果:

Mug(1)
Mug(2)
无参构造器
Mug(1)
Mug(2)
有参构造器
可以看到,因为少了一个static关键字,因此,每new一个对象,mug1和mug2都会初始化一次,并且也是在构造器执行之前完成。


写这篇博客是因为在《Java思想编程》中看到专门讲构造器初始化的知识,感觉自己有很多不懂的地方,看了两三遍才明白。现在再总结一下,算是加深印象吧。







Java 用构造器确保初始化

随着计算机革命的发展,“不安全”的编程方式已逐渐成为编程代价高昂的主因之一。 初始化和清理(cleanup)正是涉及安全的两个问题。许多C程序的错误都源于程序员忘记初始化变量。特别是在使用程序库时,如...
  • u011171255
  • u011171255
  • 2017年02月07日 14:41
  • 247

java中构造器执行前的初始化动作

1.首先需要肯定的是静态类成员
  • zhexuehan
  • zhexuehan
  • 2014年11月13日 16:38
  • 925

从头认识java-4.7 构造器初始化(3)

接着上一章节。(4)显性初始化静态域通过静态代码块来初始化某些属性域。package com.ray.testobject; public class Test { private stat...
  • raylee2007
  • raylee2007
  • 2015年10月27日 23:26
  • 1496

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)

我们大家都知道,对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序以此是(静态变量、静态初始化块)>(变量、初始化块)>构造器。我们也可以通过下面的测试代码来验证这一点:  Jav...
  • caomiao2006
  • caomiao2006
  • 2016年05月29日 19:10
  • 1192

JAVA编程思想(第4版) 构造器初始化及顺序

用构造器来进行初始化。但是无法阻止自动初始化的进行,它将在构造器被调用之前发生。如下代码: public class Count { int i; Count(){ i=8; } }i...
  • u014621130
  • u014621130
  • 2015年04月07日 19:22
  • 978

java中初始化与构造器

当Java创建一个对象时,系统先为该对象的所有实例属性分配内存(前提是该类已经被加载过了),接着程序开始对这些实例属性执行初始化,其初始化顺序是:先执行初始化块或声明属性时制定的初始值,再执行构造器里...
  • nankeyimengxihe
  • nankeyimengxihe
  • 2016年03月11日 21:57
  • 1141

子类调用父类构造器时的Java类成员初始化顺序

我们先看一个经典的例子: class Root{ static{ System.out.println("Root的静态初始化块"); } { System.out.println("...
  • login_sonata
  • login_sonata
  • 2017年02月26日 16:25
  • 288

朝花夕拾——你了解构造器初始化顺序吗?

在java程序中,创建java对象,其初始化顺序总是先调用最顶层父类的初始化操作,包括初始化块和构造器,然后再向下调用其他类的初始化操作。 类和实例的初始化顺序可以参考 朝花夕拾——看清java实例变...
  • u010794180
  • u010794180
  • 2015年07月28日 17:26
  • 1660

成员变量、this和super问题、类的初始化过程问题

继承中的问题目录继承中的问题目录 代码块 结果 说明 成员变量、this和super问题、类的初始化过程问题代码块://Java class Fu{ public int num = 10; ...
  • hduxiejun
  • hduxiejun
  • 2016年10月14日 21:59
  • 327

关于类初始化String域与构造器初始化String域的区别

public class practice2 {        //类定义String        String st1 = new String("abc");        practic...
  • u013399093
  • u013399093
  • 2015年01月12日 22:25
  • 1213
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java 构造器初始化
举报原因:
原因补充:

(最多只允许输入30个字)