﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Oo缘来是你oO-随笔分类-Java Pitfalls</title><link>http://www.blogjava.net/majianan/category/13673.html</link><description>&lt;br&gt;
&lt;div align=center &gt;
&lt;img width=200 height=50 src="http://www.blogjava.net/images/blogjava_net/majianan/14891/r_5858488902000cu2.gif" name="welcome"&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;script language="JavaScript"&gt;
&lt;!-- Begin
text = "人本是人，不必刻意去做人；世本是世，无须精心去处世；自然的才是快乐的。"; 
color1 = "blue"; 
color2 = "red"; fontsize = "2"; 
speed = 100; 
i = 0;
if (navigator.appName == "Netscape") {
document.write("&lt;layer id=a visibility=show&gt;&lt;/layer&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;");
}
else {
document.write("&lt;div id=a&gt;&lt;/div&gt;");
}
function changeCharColor() {
if (navigator.appName == "Netscape") {
document.a.document.write("&lt;center&gt;&lt;font face=arial size =" + fontsize + "&gt;&lt;font color=" + color1 + 
"&gt;");
for (var j = 0; j &lt; text.length; j++) {
if(j == i) {
document.a.document.write("&lt;font face=arial color=" + color2 + "&gt;" + Text.charAt(i) + "&lt;/font&gt;");
}
else {
document.a.document.write(text.charAt(j));
}
}
document.a.document.write('&lt;/font&gt;&lt;/font&gt;&lt;/center&gt;');
document.a.document.close();
}
if (navigator.appName == "Microsoft Internet Explorer") {
str = "&lt;center&gt;&lt;font face=arial size=" + fontsize + "&gt;&lt;font color=" + color1 + "&gt;";
for (var j = 0; j &lt; text.length; j++) {
if( j == i) {
str += "&lt;font face=arial color=" + color2 + "&gt;" + text.charAt(i) + "&lt;/font&gt;";
}
else {
str += text.charAt(j);
}
}
str += "&lt;/font&gt;&lt;/font&gt;&lt;/center&gt;";
a.innerHTML = str;
}
(i == text.length) ? i=0 : i++;
}
setInterval("changeCharColor()", speed);
// End --&gt;
&lt;/script&gt; 
</description><language>zh-cn</language><lastBuildDate>Wed, 28 Feb 2007 12:01:31 GMT</lastBuildDate><pubDate>Wed, 28 Feb 2007 12:01:31 GMT</pubDate><ttl>60</ttl><item><title>在java中使用循环定义会出现哪些问题？ </title><link>http://www.blogjava.net/majianan/archive/2006/10/19/76100.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Thu, 19 Oct 2006 02:58:00 GMT</pubDate><guid>http://www.blogjava.net/majianan/archive/2006/10/19/76100.html</guid><wfw:comment>http://www.blogjava.net/majianan/comments/76100.html</wfw:comment><comments>http://www.blogjava.net/majianan/archive/2006/10/19/76100.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/majianan/comments/commentRss/76100.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/majianan/services/trackbacks/76100.html</trackback:ping><description><![CDATA[
		<font face="Verdana">
				<font size="4">
						<font color="#0000ff">                              在Java中使用循环定义会出现哪些问题 <img height="20" src="http://www.blogjava.net/Emoticons/emquestion.gif" width="20" border="0" /></font> <br /><br /></font>
				<font size="2">                                              </font>
		</font>
		<a href="/majianan">
				<font face="Verdana" color="#0000ff" size="2">马嘉楠</font>
		</a>
		<font face="Verdana">
				<font size="2">
						<font color="#0000ff"> </font>       2006-10-19 </font>
		</font>
		<p>
				<br />
				<font face="Verdana" size="2">在上一篇文章《 </font>
				<a href="/majianan/archive/2006/10/18/75972.html?Pending=true#Post">
						<font face="Verdana" color="#0000ff" size="2">inconstant constants ( 变化无常的常量 )</font>
				</a>
				<font face="Verdana" size="2">  》的基础上,我们再来研究一下<font color="#000000">在 Java 中使用循环定义会出现哪些问题</font>。</font>
		</p>
		<p>
				<font face="Verdana" size="2">老规矩，代码伺候 ^+^</font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">例1：<br /><br /></span>
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">class</span>
						</font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">ClassX{<br /></span>
								<span style="COLOR: #0000ff">   public</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">final</span> <span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">X </span><span style="COLOR: #000000">=</span> <span style="COLOR: #000000">2</span><span style="COLOR: #000000">*</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">ClassY.Y;<br />}<br /><br /></span>
								<span style="COLOR: #0000ff">public</span> <span style="COLOR: #0000ff">class</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">ClassY{<br /></span>
								<span style="COLOR: #0000ff">   public</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">final</span> <span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">Y </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">ClassZ.Z</span><span style="COLOR: #000000">+</span> <span style="COLOR: #000000">1</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">;<br />}<br /><br /></span>
								<span style="COLOR: #0000ff">public</span>
								<span style="COLOR: #0000ff">class</span>
								<span style="COLOR: #000000"> ClassZ </span>
								<span style="COLOR: #0000ff">extends</span>
						</font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">ClassX{<br /></span>
								<span style="COLOR: #0000ff">   public</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">final</span> <span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> Z</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> X </span><span style="COLOR: #000000">+</span> <span style="COLOR: #000000">3</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">;<br />}<br /><br /></span>
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">class </span>
						</font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">ClassTest{<br /></span>
								<span style="COLOR: #0000ff">   public</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">void</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">main(String[] args){<br />      System.out.println(ClassX.X</span>
								<span style="COLOR: #000000">+</span>
								<span style="COLOR: #000000">ClassY.Y</span>
								<span style="COLOR: #000000">+</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<font face="Verdana" size="2">ClassZ.Z);<br />   }<br />} <br /></font>
				</span>
		</div>
		<p>
				<br />
				<font face="Verdana" size="2">代码中的static final变量X，Y，Z，循环定义。</font>
		</p>
		<p>
				<font face="Verdana" size="2">你可以先想一下，这个值会是多少？看看与实际结果是否一致。</font>
		</p>
		<p>
				<font face="Verdana" size="2">输出结果：</font>
				<br />
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img id="Code_Closed_Image_105656" onclick="this.style.display='none'; Code_Closed_Text_105656.style.display='none'; Code_Open_Image_105656.style.display='inline'; Code_Open_Text_105656.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" />
				<img id="Code_Open_Image_105656" style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_105656.style.display='none'; Code_Closed_Image_105656.style.display='inline'; Code_Closed_Text_105656.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" />
				<span id="Code_Closed_Text_105656" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
				</span>
				<span id="Code_Open_Text_105656" style="DISPLAY: none">
						<br />
						<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
						<span style="COLOR: #000000">15</span>
						<span style="COLOR: #000000">
								<br />
						</span>
				</span>
		</div>
		<p>
				<br />
		</p>
		<p>
				<font face="Verdana" size="2">现在对ClassTest.java进行一点修改，如下：<br /><br /></font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">例2：<br /><br /></span>
								<span style="COLOR: #0000ff">public</span> <span style="COLOR: #0000ff">class</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">ClassTest{<br /></span>
								<span style="COLOR: #0000ff">   public</span> <span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">void</span></font>
				</font>
				<font face="Verdana">
						<font size="2">
								<span style="COLOR: #000000">main(String[] args){<br />      System.out.println(ClassZ.Z</span>
								<span style="COLOR: #000000">+</span>
								<span style="COLOR: #000000">ClassY.Y</span>
								<span style="COLOR: #000000">+</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<font face="Verdana" size="2">ClassX.X);<br />   }<br />} </font>
				</span>
		</div>
		<p>
				<font face="Verdana" size="2">两次的输出结果会一样么？<br />我既然这么问了，你肯定会说不一样，那你知道原因么？你知道这次的输出结果么？<br />可以先思考一下。<br /><br />输出结果：</font>
				<br />
		</p>
		<p>
				<font face="Verdana" size="2">
				</font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img id="Code_Closed_Image_105721" onclick="this.style.display='none'; Code_Closed_Text_105721.style.display='none'; Code_Open_Image_105721.style.display='inline'; Code_Open_Text_105721.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" width="11" align="top" />
				<img id="Code_Open_Image_105721" style="DISPLAY: none" onclick="this.style.display='none'; Code_Open_Text_105721.style.display='none'; Code_Closed_Image_105721.style.display='inline'; Code_Closed_Text_105721.style.display='inline';" height="16" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" width="11" align="top" />
				<span id="Code_Closed_Text_105721" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
				</span>
				<span id="Code_Open_Text_105721" style="DISPLAY: none">
						<br />
						<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->
						<span style="COLOR: #000000">8</span>
						<span style="COLOR: #000000">
								<br />
						</span>
				</span>
		</div>
		<p>
				<br />让我来告诉你这是怎么回事。</p>
		<p>
				<font face="Verdana" size="2">我们可以看见，对于三个staitc final 变量 X，Y，Z，他们的初始化表达式是循环定义的。在编译期间不能确定它们的值，所以它们是运行期间常量( runtime constants )，编译器不会进行常量替换。<br />而且每个表达式的计算将会依赖于类装载的顺序。<br /><br />例如，为了计算出例1中的 ClassTest 结果，我们可以预见，ClassX 是第一个被装载的类，但是第一个完成初始化的类却是 ClassZ.<br /><br />让我们一步一步看看都发生了什么。<br /><br />1.   X = 2 * ClassY.Y;      计算X，需要知道ClassY.Y的值，下一步计算Y值<br />2.   Y = ClassZ.Z + 1;      计算Y，需要知道ClassZ.Z的值，下一步计算Z值<br />3.   Z = X + 3;                计算Z，需要知道X的值，而此时X的值还没有被计算出来(又转回来了，居然是个圈，呵呵^+^)，所以我们使用X的默认值0。<br /><br /></font>
				<font face="Verdana">
						<font size="2">
								<font color="#0000ff">因此：<br /></font>      Z = 3;<br />      Y = 4;<br />      X = 8;<br /><br />所以 ClassX.X + ClassY.Y + ClassZ.Z  =  15</font>
				</font>
		</p>
		<p>
				<font face="Verdana" size="2">例2当中，也是同一道理<br />不同的是，ClassZ是第一个被装载的类，ClassX是第一个完成初始化的类<br />1. Z = X + 3; <br />2. X = 2 * ClassY.Y; <br />3. Y = ClassZ.Z + 1;(此时使用Z的默认值0)<br /><br /><font color="#0000ff">因此：</font><br />      Y = 1;<br />      X = 2;<br />      Z = 5;<br /><br />所以 ClassZ.Z + ClassY.Y + ClassX.X = 8</font>
		</p>
		<p>
				<font face="Verdana" size="2">只是简单的改变的输出顺序，结果却截然不同。哪一个才是你想要得结果呢？</font>
		</p>
		<p>
				<font face="Verdana" size="2">我的例子看起来有点挖空心思钻牛角尖，但是在大型项目当中，也许就会出现与例子当中相同的循环定义，如果真的存在的话，那么在纷繁的代码当中想要发现循环定义可不是件容易的事情。<br /><br />如果独立看每一个定义的话，似乎都可以进行常量替换，看不出任何问题。但是这样的代码在不久的将来就会引发问题，而且不易被我们所察觉。<br /><br />在你的应用程序当中不经意的代码改变（例如示例代码中我们只是改变了输出顺序，却产生了截然不同的结果），就会导致不同的类装载顺序和计算顺序，或者在并发的线程调度中，可能也会导致致不同的类装载顺序和计算顺序。不幸的是，大多数编译器不认为这种代码是错误，也不会对编程人员给出任何警告。</font>
		</p>
		<p>
				<font face="Verdana" size="2">我只是讲了一下循环定义会引发的问题，我暂时也想不出什么好的解决办法，只能在编程的过程当中尽量注意啦。<br /><br /><br />注：有错误请告诉我，非常感谢！</font>
		</p>
<img src ="http://www.blogjava.net/majianan/aggbug/76100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/majianan/" target="_blank">马嘉楠</a> 2006-10-19 10:58 <a href="http://www.blogjava.net/majianan/archive/2006/10/19/76100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>inconstant constants（变化无常的常量）</title><link>http://www.blogjava.net/majianan/archive/2006/10/18/75972.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Wed, 18 Oct 2006 08:27:00 GMT</pubDate><guid>http://www.blogjava.net/majianan/archive/2006/10/18/75972.html</guid><wfw:comment>http://www.blogjava.net/majianan/comments/75972.html</wfw:comment><comments>http://www.blogjava.net/majianan/archive/2006/10/18/75972.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/majianan/comments/commentRss/75972.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/majianan/services/trackbacks/75972.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Verdana">
						<font style="BACKGROUND-COLOR: #ffffff" color="#000000">
								<font color="#0000ff">                       <font size="4">         inconstant constants</font> ( 变化无常的常量 )</font> </font> <br />                                          <br />                                           </font>
				<a href="/majianan">
						<font face="Verdana">
								<font color="#0000ff">马嘉楠</font>
						</font>
				</a>
				<font face="Verdana">               2006-10-18 <br /><br /><br /></font>
				<font face="Verdana" size="2">看到这个题目也许你会感到奇怪，会想我在胡说八道什么，一定又是起个怪异的名字，骗取点击率。还请你耐心看完，如果你有所收获，那么我很高兴；如果你还是觉得上当了，那我继续努力写出点有用的东西，呵呵。<br /><br />其实我想了很久，也还是不知道起一个什么题目好，就套用了《 <font color="#0000ff">The Java Language Specification </font>》中的一个名词“ <font color="#0000ff">inconstant constants</font>”，我把他翻译成“<font color="#0000ff">变化无常的常量</font>” </font>
		</p>
		<p>
				<font face="Verdana" size="2">注：部分内容在《 </font>
				<a href="/majianan/archive/2006/10/14/75097.html">
						<font size="2">
								<font face="Verdana">
										<font color="#0000ff">使用Java中的final变量需要注意的地方</font>
								</font>
						</font>
				</a>
				<font face="Verdana" size="2">》有提到，不过我转载的原文不够详细深入，这才重新写一下。<br /></font>
		</p>
		<p>
				<font face="Verdana" size="2">我们还是来先看一段代码，由代码引出问题：<br /><br /></font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">class</span>
						</font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000"> ClassX {<br />   </span>
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">static </span>
								<span style="COLOR: #0000ff">final </span>
								<span style="COLOR: #0000ff">int</span>
								<span style="COLOR: #000000">  X  </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000">   </span>
								<span style="COLOR: #000000">2</span>
						</font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000"> ;<br />}<br /><br /></span>
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">class </span>
						</font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">ClassTest {<br />   </span>
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">static </span>
								<span style="COLOR: #0000ff">void </span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<font face="Verdana" size="2">main(String[] args){<br />      System.out.println(ClassX.X);<br />   }<br />}   </font>
				</span>
		</div>
		<p>
				<br />
				<font face="Verdana" size="2">输出结果：<br /><br />2 </font>
		</p>
		<p>
				<font face="Verdana" size="2">结果是显而易见的，这里需要说明的是：<br />根据Java语言规范，对于java中的static final变量，如果用一个在编译期间(complie time)可以计算出结果的表达式进行初始化，则用到此变量的地方会被该表达式的结果所替代。本例中，在编译期间，ClassTest.main() 函数中 ClassX.X 将被2所替代。<br /><br />此时，在类ClassTest main()中不再有指向ClassX的动态链接，告诉ClassTest在运行的时候从ClassX获得X的值，你可以通过使用javap反编译器帮助你理解。<br /><br />1. 先编译ClassTest.java文件<br />            javac ClassTest.java<br />2. 使用javap<br />            javap -c ClassTest<br /><br />屏幕输出： <br /><br /></font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">Complied from "ClassTest.java"<br />public class ClassTest extends java.lang.Object{<br />public ClassTest();<br />   Code:<br />      0: aload_0<br />      1: invokespecial     #1; //Method java/lang/Object."&lt;init&gt;</span>
						</font>
				</font>
				<font face="Verdana" size="2">
						<span style="COLOR: #000000">":()V<br />      4: return<br /><br />public static void main(java.lang.String[]);<br />   Code:<br />      0: getstatic         #2; //Field java/lang/System.out:Ljava/io/PrintStream;<br />      3: iconst_2 <br />      4: invokevirtua      #3; //Method java/io/PrintStream.println:(I)V<br />      7: return<br /><br />} </span>
				</font>
		</div>
		<p>
				<br />
				<font face="Verdana" size="2">可以看出，在调用System.out.println()之前，整数2已经被放在JVM的堆栈中，不再有指向ClassX.X的链接。如果此时，改变ClassX.X的值为1,并且重新编译ClassX.X文件，但是并不重新编译ClassTest.java文件，运行ClassTest，输出结果仍然是2.<br /><br />这么做(常量替换)的一个原因是为了在编译期间检查switch case语句。switch语句中的每一个case都需要一个常量值，而且每两个之间都不能相同，编译器在编译期间将会做检查。 <br /><br />如果用来给static final变量进行初始化的表达式，只能在运行时刻才可以计算出值，那么常量替换就不会发生.例如： </font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #0000ff">public </span>
								<span style="COLOR: #0000ff">class </span>
						</font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">ClassX {<br /></span>
								<span style="COLOR: #0000ff">   public </span>
								<span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">final</span> <span style="COLOR: #0000ff">int</span> X<span style="COLOR: #000000"> </span><span style="COLOR: #000000">=</span> <span style="COLOR: #0000ff">new</span>  </font>
				</font>
				<span style="COLOR: #000000">
						<font face="Verdana" size="2">java.util.Random().nextInt();<br />}   </font>
				</span>
		</div>
		<p>
				<br />
				<font face="Verdana" size="2">ClassX 改变了，我们再来看一下Main.main(): </font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">Complied from "ClassTest.java"<br />public class ClassTest extends java.lang.Object{<br />public ClassTest();<br />   Code:<br />      0: aload_0<br />      1: invokespecial      #1; //Method java/lang/Object."&lt;init&gt;</span>
						</font>
				</font>
				<font face="Verdana" size="2">
						<span style="COLOR: #000000">":()V<br />      4: return<br /><br />public static void main(java.lang.String[]);<br />   Code:<br />      0: getstatic          #2; //Field java/lang/System.out:Ljava/io/PrintStream;<br />      3: getstatic          #3; //Field ClassX.X:I <br />      6: invokevirtual      #4; //Method java/io/PrintStream.println:(I)V<br />      9: return<br /><br />} </span>
				</font>
		</div>
		<p>
				<br />
				<font face="Verdana" size="2">此时我们可以看见有个引用指向了Field X。<br />( 如果把类ClassX改成Interface，仍然会出现上面的结果 ) <br /><br />当然有方法可以使你避免出现<font color="#0000ff">"inconstant constants"</font>问题。<br /><br /></font>
				<font size="2">
						<font face="Verdana">
								<font color="#008000">
										<font color="#000080">第一种方法：</font>
										<br />
								</font>当你要声明一个编译期间常量的时候，一定要保证此变量不会或者不太可能改变，或者尽量少使用声明为static final的变量。当然这只能治标不能治本，所以我推荐使用第二种方法。<br /><br /><font color="#000080">第二种方法：</font><br />将变量声明为private，同时声明一个方法来获得此变量的值 <br /></font>
				</font>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000">ClassX.java修改如下： </span>
						</font>
				</font>
				<span style="COLOR: #008000">
						<br />
				</span>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #0000ff">public<font color="#000000"></font></span>
								<span style="COLOR: #0000ff">class</span>  </font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">ClassX {<br /></span>
								<span style="COLOR: #0000ff">   private</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">final</span> <span style="COLOR: #0000ff">int</span> <span style="COLOR: #000000">X </span><span style="COLOR: #000000">=</span> <span style="COLOR: #000000">2</span></font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #0000ff">   public  </span>
								<span style="COLOR: #0000ff">static </span>
								<span style="COLOR: #0000ff">int </span>
						</font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">getX(){<br /></span>
								<span style="COLOR: #0000ff">      return </span>
						</font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">X;<br />   }<br />}<br /><br /></span>
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000">ClassTest.java修改如下： </span>
						</font>
				</font>
				<span style="COLOR: #008000">
						<br />
				</span>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #0000ff">public</span> <span style="COLOR: #0000ff">class</span>  </font>
				</font>
				<font size="2">
						<font face="Verdana">
								<span style="COLOR: #000000">ClassTest{<br /></span>
								<span style="COLOR: #0000ff">   public</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #0000ff">void</span>  </font>
				</font>
				<font face="Verdana" size="2">
						<span style="COLOR: #000000">main(String[] args){<br />      System.out.println(ClassX.getX());<br />   }<br />} </span>
				</font>
		</div>
		<p>
				<br />
				<font face="Verdana" size="2">此时再改变ClassX.X的值为1，重新编译ClassX.java，而不编译ClassTest，结果就会显示1，而非2。这就避免了"<font color="#0000ff">inconstant constants</font>"的问题。 <br /><br />下一篇准备讲一下</font>
				<a href="/majianan/archive/2006/10/19/76100.html">
						<font face="Verdana" color="#0000ff" size="2">《在java中使用循环定义会出现哪些问题？》</font>
				</a>
				<font face="Verdana" color="#0000ff" size="2">
				</font>
		</p>
		<p>
				<br />
				<font face="Verdana">  </font>
		</p>
<img src ="http://www.blogjava.net/majianan/aggbug/75972.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/majianan/" target="_blank">马嘉楠</a> 2006-10-18 16:27 <a href="http://www.blogjava.net/majianan/archive/2006/10/18/75972.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>请问：谁有电子版的《java pitfalls》啊？给我一份</title><link>http://www.blogjava.net/majianan/archive/2006/08/15/63591.html</link><dc:creator>马嘉楠</dc:creator><author>马嘉楠</author><pubDate>Tue, 15 Aug 2006 01:20:00 GMT</pubDate><guid>http://www.blogjava.net/majianan/archive/2006/08/15/63591.html</guid><wfw:comment>http://www.blogjava.net/majianan/comments/63591.html</wfw:comment><comments>http://www.blogjava.net/majianan/archive/2006/08/15/63591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/majianan/comments/commentRss/63591.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/majianan/services/trackbacks/63591.html</trackback:ping><description><![CDATA[谁有电子版的《java pitfalls》啊？<br /><br />请发给我一份，非常感谢！<br /><br />Email:jianan.ma@gmail.com<img src ="http://www.blogjava.net/majianan/aggbug/63591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/majianan/" target="_blank">马嘉楠</a> 2006-08-15 09:20 <a href="http://www.blogjava.net/majianan/archive/2006/08/15/63591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>