java循环里面频繁定义string_在java中使用循环定义会出现哪些问题?

在Java中使用循环定义会出现哪些问题

1485c87a68aa31a1aa3d82858d59cb0b.gif

马嘉楠

2006-10-19

在上一篇文章《

inconstant constants ( 变化无常的常量 )

》的基础上,我们再来研究一下在 Java 中使用循环定义会出现哪些问题。

老规矩,代码伺候 ^+^

例1:

public

class

ClassX{

public static final intX= 2*

ClassY.Y;

}

public class

ClassY{

public static final intY=ClassZ.Z+ 1

;

}

public

class

ClassZ

extends

ClassX{

public static final intZ=X+ 3

;

}

public

class

ClassTest{

public static void

main(String[] args){

System.out.println(ClassX.X

+

ClassY.Y

+

ClassZ.Z);

}

}

代码中的static final变量X,Y,Z,循环定义。

你可以先想一下,这个值会是多少?看看与实际结果是否一致。

输出结果:

ca75c07623e1b494fee67e8f316fc310.gif

1fa987a29c6482f53d401256f96355eb.png

15

现在对ClassTest.java进行一点修改,如下:

例2:

public class

ClassTest{

public staticvoid

main(String[] args){

System.out.println(ClassZ.Z

+

ClassY.Y

+

ClassX.X);

}

}

两次的输出结果会一样么?

我既然这么问了,你肯定会说不一样,那你知道原因么?你知道这次的输出结果么?

可以先思考一下。

输出结果:

ca75c07623e1b494fee67e8f316fc310.gif

1fa987a29c6482f53d401256f96355eb.png

8

让我来告诉你这是怎么回事。

我们可以看见,对于三个staitc final 变量 X,Y,Z,他们的初始化表达式是循环定义的。在编译期间不能确定它们的值,所以它们是运行期间常量( runtime constants ),编译器不会进行常量替换。

而且每个表达式的计算将会依赖于类装载的顺序。

例如,为了计算出例1中的 ClassTest 结果,我们可以预见,ClassX 是第一个被装载的类,但是第一个完成初始化的类却是 ClassZ.

让我们一步一步看看都发生了什么。

1.   X = 2 * ClassY.Y;      计算X,需要知道ClassY.Y的值,下一步计算Y值

2.   Y = ClassZ.Z + 1;      计算Y,需要知道ClassZ.Z的值,下一步计算Z值

3.   Z = X + 3;                计算Z,需要知道X的值,而此时X的值还没有被计算出来(又转回来了,居然是个圈,呵呵^+^),所以我们使用X的默认值0。

因此:      Z = 3;

Y = 4;

X = 8;

所以 ClassX.X + ClassY.Y + ClassZ.Z  =  15

例2当中,也是同一道理

不同的是,ClassZ是第一个被装载的类,ClassX是第一个完成初始化的类

1. Z = X + 3;

2. X = 2 * ClassY.Y;

3. Y = ClassZ.Z + 1;(此时使用Z的默认值0)

因此:

Y = 1;

X = 2;

Z = 5;

所以 ClassZ.Z + ClassY.Y + ClassX.X = 8

只是简单的改变的输出顺序,结果却截然不同。哪一个才是你想要得结果呢?

我的例子看起来有点挖空心思钻牛角尖,但是在大型项目当中,也许就会出现与例子当中相同的循环定义,如果真的存在的话,那么在纷繁的代码当中想要发现循环定义可不是件容易的事情。

如果独立看每一个定义的话,似乎都可以进行常量替换,看不出任何问题。但是这样的代码在不久的将来就会引发问题,而且不易被我们所察觉。

在你的应用程序当中不经意的代码改变(例如示例代码中我们只是改变了输出顺序,却产生了截然不同的结果),就会导致不同的类装载顺序和计算顺序,或者在并发的线程调度中,可能也会导致致不同的类装载顺序和计算顺序。不幸的是,大多数编译器不认为这种代码是错误,也不会对编程人员给出任何警告。

我只是讲了一下循环定义会引发的问题,我暂时也想不出什么好的解决办法,只能在编程的过程当中尽量注意啦。

注:有错误请告诉我,非常感谢!

马嘉楠

jianan.ma@gmail.com

posted on 2006-10-19 10:58 马嘉楠 阅读(1872) 评论(4)  编辑  收藏 所属分类: Java

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值