java静态变量重复new_java中普通变量、静态变量、静态代码块初始化的顺序辨析...

1.普通变量的初始化

看如下程序

class Window{

public Window(int maker) {

System.out.println("Window("+maker+")");

}

}

class House{

Window w1=newWindow(1);

public House() {

System.out.println("House()");

w3=newWindow(33);

}

Window w2=newWindow(2);

void f(){

System.out.println("f()");

}

Window w3=newWindow(3);

}

public class Test {

public static void main(String[] args) {

House h=newHouse();

h.f();

}

}

/*

结果如下:

Window(1)

Window(2)

Window(3)

House()

Window(33)

f()

*/

分析:普通变量在类中的任何方法(包括构造函数)之前初始化(规则一)。

2.静态变量的初始化

class Bowl{

public Bowl(int maker) {

System.out.println("Bowl("+maker+")");

}

void f1(int maker){

System.out.println("f1("+maker+")");

}

}

class Table{

static Bowl bowl1=newBowl(1);

static Bowl bowl2=newBowl(2);

public Table() {

System.out.println("Table()");

bowl2.f1(1);

}

void f2(int maker){

System.out.println("f2("+maker+")");

}

}

class Cupboard{

Bowl bowl3=newBowl(3);

static Bowl bowl4=newBowl(4);

static Bowl bowl5=newBowl(5);

public Cupboard() {

System.out.println("cupboard()");

bowl4.f1(2);

}

void f3(int maker){

System.out.println("f3("+maker+")");

}

}

public class Test {

static Table table=newTable();

static Cupboard cupboard=newCupboard();

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.f2(1);

cupboard.f3(1);

}

}

/*

结果如下:

Bowl(1)

Bowl(2)

Table()

f1(1)

Bowl(4)

Bowl(5)

Bowl(3)

cupboard()

f1(2)

creating new cupboard() in main

Bowl(3)

cupboard()

f1(2)

creating new cupboard() in main

Bowl(3)

cupboard()

f1(2)

f2(1)

f3(1)

*/

分析:

1.首先程序总共有4个类(Bowl,Table,Cupboard,Test),Bowl没有静态变量和静态方法;Table中有静态变量bowl1、bowl2;Cupboard中有普通变量bowl3,静态变量bowl4、bowl5;Test中有静态变量table、cupboard。

2.根据规则:使用static命名的变量或者使用static{}包括起来的区域,都在类被加载时进行初始化(规则二)。

3.虚拟机首先加载Test,需要初始化table变量,加载Table类。Table类中有静态变量bowl1,bowl2,初始化它们,输出"Bowl(1),Bowl(2)",再调用构造函数来new对象,输出"Table(),f1(1)"。然后加载Cupboard类,初始化静态变量bowl4,bowl5,输出"Bowl(4),Bowl(5)",调用构造函数来new对象,首先初始化普通变量bowl3,输出"Bowl(3)",然后构造函数,输出"cupboard(),f1(2)"。

4.执行main方法,先输出"creating new cupboard() in main",执行new Cupboard(),这时静态变量都初始化了,不必继续初始化。初始化一般变量bowl3,输出"bowl3",然后调用构造函数,输出"cupboard(),f1(2)"。在输出"creating new cupboard() in main",同理输出"bowl3,cupboard(),f1(2)",最后继续执行main函数,输出"f2(1),f3(1)"。

3.静态代码块的初始化

class Spoon{

public Spoon(int maker) {

System.out.println("Spoon("+maker+")");

}

static int i;

static Spoon s=newSpoon(1);

static{

System.out.println("static code ");

i=47;

}

}

public class Test {

public static void main(String[] args) {

new Spoon(2);

}

}

/*

Spoon(1)

static code

Spoon(2)

*/

/*

如果写成

static{

System.out.println("static code ");

i=47;

}

static Spoon s=newSpoon(1);

结果为:

static code

Spoon(1)

Spoon(2)

*/

分析:静态代码块跟静态变量都是类加载时进行初始化的(同等条件下,初始化顺序由书写顺序决定)

4.非静态代码块

class Spoon{

public Spoon(int maker) {

System.out.println("Spoon("+maker+")");

}

static int i;

static Spoon s=newSpoon(1);

static{

System.out.println("static code ");

i=47;

}

int a;

//非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中

{

System.out.println("non-static instatnce");

a=1;

}

}

public class Test {

public static void main(String[] args) {

new Spoon(2);

new Spoon(3);

}

}

/*

non-static instatnce

Spoon(1)

static code

non-static instatnce

Spoon(2)

non-static instatnce

Spoon(3)

*/

分析:

1.main函数执行new Spoon(2)语句,首先加载Spoon类,先初始化静态变量s,s调用new Spoon(1),此时类Spoon已经加载,所以不用管静态变量和静态代码块了,然后调用非静态代码块和构造函数,输出"non-static code,spoon(1)"。

2.初始化静态代码块,输出"static code"。

3.执行new spoon(2)语句输出“non-static instatnce,Spoon(2)“。

4.执行"new spoon(3)"语句输出”non-static instatnce,Spoon(3)”。

可以尝试调换静态变量s和静态代码块的顺序,发现只是1和2的先后顺序改变而已。

在看下面这个程序

classT{

publicT() {

System.out.println("T constructor");

}

}

classSpoon{

publicSpoon(intmaker) {

System.out.println("Spoon("+maker+")");

}

inta;

//非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中

{

System.out.println("non-static instatnce");

a = 1;

}

T t1 = newT();

}

publicclassTest {

publicstaticvoidmain(String[] args) {

newSpoon(2);

}

}

/*

non-static instatnce

T constructor

Spoon(2)

*/

通过这个程序,可以发现非静态变量和非静态代码块顺序由书写顺序决定。

5.总结:

以Dog类为例

1.当第一次执行到需要使用Dog类时(如Dog d = new Dog),java首先通过寻找classpath来找到Dog.class,进行加载.

2.初始化Dog类的静态变量和静态代码块(按书写顺序,若静态变量或代码块中还有new Dog,此时不用再管静态变   量和代码块了,如第五个程序中的"static Spoon s = new Spoon(1)")。

3.系统给类分配足够大的内存空间,初始化非静态变量和非静态代码块(顺序由书写顺序决定)

4.最后执行Dog类的构造函数。

5.以后如果还要new Dog类对象时(不是第一次使用了),重复3和4的步骤,不会再去初始化静态变量和静态代码     块了。

大家可以自己写程序实验一下。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值