亚洲免费乱码视频,日韩 欧美 国产 动漫 一区,97在线观看免费视频播国产,中文字幕亚洲图片

      1. <legend id="ppnor"></legend>

      2. 
        
        <sup id="ppnor"><input id="ppnor"></input></sup>
        <s id="ppnor"></s>

        Java類謎題49:比生命更大

        字號:

        假如小報是可信的,那么搖滾“貓王”就會直到今天仍然在世。下面的程序用來估算貓王當(dāng)前的腰帶尺寸,方法是根據(jù)在公開演出中所觀察到的他的體態(tài)發(fā)展趨勢來進行投射。該程序中使用了Calendar.getInstance().get(Calendar.YEAR)這個慣用法,它返回當(dāng)前的日歷年份。那么,該程序會打印出什么呢?
            public class Elvis {
             public static final Elvis INSTANCE = new Elvis();
             private final int beltSize;
             private static final int CURRENT_YEAR =
             Calendar.getInstance().get(Calendar.YEAR);
             private Elvis() {
             beltSize = CURRENT_YEAR - 1930;
             }
             public int beltSize() {
             return beltSize;
             }
             public static void main(String[] args) {
             System.out.println("Elvis wears a size " +
             INSTANCE.beltSize() + " belt.");
             }
            }
            第一眼看去,這個程序是在計算當(dāng)前的年份減去1930的值。如果它是正確的,那么在2006年,該程序?qū)⒋蛴〕鯡lvis wears a size 76 belt。如果你嘗試著去運行該程序,你就會了解到小報是錯誤的,這證明你不能相信在報紙到讀到的任何東西。該程序?qū)⒋蛴〕鯡lvis wears a size -1930 belt。也許貓王已經(jīng)在反物質(zhì)的宇宙中定居了。
            該程序所遇到的問題是由類初始化順序中的循環(huán)而引起的[JLS 12.4]。讓我們來看看其細節(jié)。Elvis類的初始化是由虛擬機對其main方法的調(diào)用而觸發(fā)的。首先,其靜態(tài)域被設(shè)置為缺省值[JLS 4.12.5],其中INSTANCE域被設(shè)置為null,CURRENT_YEAR被設(shè)置為0。接下來,靜態(tài)域初始器按照其出現(xiàn)的順序執(zhí)行。第一個靜態(tài)域是INSTANCE,它的值是通過調(diào)用Elvis()構(gòu)造器而計算出來的。
            這個構(gòu)造器會用一個涉及靜態(tài)域CURRENT_YEAR的表達式來初始化beltSize。通常,讀取一個靜態(tài)域是會引起一個類被初始化的事件之一,但是我們已經(jīng)在初始化Elvis類了。遞歸的初始化嘗試會直接被忽略掉[JLS 12.4.2, 第3步]。因此,CURRENT_YEAR的值仍舊是其缺省值0。這就是為什么Elvis的腰帶尺寸變成了-1930的原因。
            最后,從構(gòu)造器返回以完成Elvis類的初始化,假設(shè)我們是在2006年運行該程序,那么我們就將靜態(tài)域CURRENT_YEAR初始化成了2006。遺憾的是,這個域現(xiàn)在所具有的正確值對于向Elvis.INSTANCE.beltSize的計算施加影響來說已經(jīng)太晚了,beltSize的值已經(jīng)是-1930了。這正是后續(xù)所有對Elvis.INSTANCE.beltSize()的調(diào)用將返回的值。
            該程序表明,在final類型的靜態(tài)域被初始化之前,存在著讀取它的值的可能,而此時該靜態(tài)域包含的還只是其所屬類型的缺省值。這是與直覺相違背的,因為我們通常會將final類型的域看作是常量。final類型的域只有在其初始化表達式是常量表達式時才是常量[JLS 15.28]。
            由類初始化中的循環(huán)所引發(fā)的問題是難以診斷的,但是一旦被診斷到,通常是很容易訂正的。要想訂正一個類初始化循環(huán),需要重新對靜態(tài)域的初始器進行排序,使得每一個初始器都出現(xiàn)在任何依賴于它的初始器之前。在這個程序中,CURRENT_YEAR的聲明屬于在INSTANCE聲明之前的情況,因為Elvis實例的創(chuàng)建需要CURRENT_YEAR被初始化。一旦CURRENT_YEAR的聲明被移走,Elvis就真的比生命更大了。
            某些通用的設(shè)計模式本質(zhì)上就是初始化循環(huán)的,特別是本謎題所展示的單例模式(Singleton)[Gamma95]和服務(wù)提供者框架(Service Provider Framework)[EJ Item 1]。類型安全的枚舉模式(Typesafe Enum pattern)[EJ Item 21]也會引起類初始化的循環(huán)。5.0版本添加了對這種使用枚舉類型的模式的語言級支持。為了減少問題發(fā)生的可能性,對枚舉類型的靜態(tài)初始器做了一些限制[JLS 16.5, 8.9]。
            總之,要當(dāng)心類初始化循環(huán)。最簡單的循環(huán)只涉及到一個單一的類,但是它們也可能涉及多個類。類初始化循環(huán)也并非總是壞事,但是它們可能會導(dǎo)致在靜態(tài)域被初始化之前就調(diào)用構(gòu)造器。靜態(tài)域,甚至是final類型的靜態(tài)域,可能會在它們被初始化之前,被讀走其缺省值。