泛型邊界處的動(dòng)作

邊界處的動(dòng)作

正因?yàn)榉盒偷牟脸嚼海盒蛶砹艘粋€(gè)事實(shí),可以表示沒有任何意義的事物巾表,即可以表示沒有任何意義的事物。

public class ArrayMaker<T> {
    private Class<T> kind;

    public ArrayMaker(Class<T> kind) {
        this.kind = kind;
    }

    @SuppressWarnings("unchecked")
    T[] create(int size) {
        return (T[]) Array.newInstance(kind, size);
    }

    public static void main(String[] args) {
        ArrayMaker<String> stringMaker = new ArrayMaker<>(String.class);
        String[] stringArray = stringMaker.create(9);
        System.out.println(Arrays.toString(stringArray));
    }
}

盡管在上面的例子中,kind被存儲(chǔ)為Class<T>吃既,但是擦除也意味著它實(shí)際將被存儲(chǔ)為Class,沒有任何的參數(shù)申鱼。因此當(dāng)我們將它作為參數(shù)傳入Array.newInstance時(shí),實(shí)際上并沒擁有kind的類型信息匣砖,因此不會(huì)產(chǎn)生具體的結(jié)果,所以必須進(jìn)行轉(zhuǎn)型拂共,并產(chǎn)生一條警告蛇捌。


但是如果創(chuàng)建的是一個(gè)容器而不是數(shù)組俭驮,情況又會(huì)變得不一樣混萝。例子代碼如下。

public class ListMaker<T> {
    List<T> create() {
        return new ArrayList<T>();
    }

    public static void main(String[] args) {
        ListMaker<String> stringMaker = new ListMaker<>();
        List<String> list = stringMaker.create();
    }
}

上面的代碼中屯蹦,編譯器不會(huì)提出任何警告脑蠕,盡管在create()內(nèi)部的new ArrayList<T>中的<T>
被移除了——在運(yùn)行時(shí),這個(gè)類的內(nèi)部沒有任何的<T>晃跺,因此看起來毫無意義。但是將代碼改為返回new ArrayList(),編譯器就會(huì)給出警告二打。
如果在返回list之前,將某些對(duì)象放入其中鸳慈,那么情況就會(huì)像下面一樣潘鲫。

public class FilledListMaker<T> {
    List<T> create(T t, int n) {
        List<T> result = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            result.add(t);
        }
        return result;
    }

    public static void main(String[] args) {
        FilledListMaker<String> stringMaker = new FilledListMaker<>();
        List<String> list = stringMaker.create("Hello", 4);
        System.out.println(list);
    }
}
// Outputs
[Hello, Hello, Hello, Hello]

即是上面代碼中状植,編譯器無法知道create()中的T的任何信息振定,但是它仍舊可以在編譯器確保代碼中放置到result中的對(duì)象具有T類型卑惜,使其適合ArrayList<T>芋浮。因此,即使擦除在方法內(nèi)部或者類內(nèi)部移除了有關(guān)實(shí)際類型的信息,編譯器仍可以依舊確保在方法或者類中使用的類型的內(nèi)部一致性。
因?yàn)椴脸诜椒w中移除了類型信息,所以在運(yùn)行時(shí)的問題就是邊界:即對(duì)象進(jìn)入和離開方法的地點(diǎn)。這正是編譯器在編譯器執(zhí)行類型檢查并插入轉(zhuǎn)型代碼的地點(diǎn)。

字節(jié)碼解析

public class SimpleHolder {
    private Object obj;

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

    public static void main(String[] args) {
        SimpleHolder holder = new SimpleHolder();
        holder.setObj("Item");
        String s = (String) holder.getObj();
    }
}

在解析生成的字節(jié)碼中巢块,可以發(fā)現(xiàn)歹鱼。set()get()方法將直接存儲(chǔ)值和產(chǎn)生值庭敦,而轉(zhuǎn)型調(diào)用是在get的時(shí)候執(zhí)行檢查的疼电。

public class GenericHolder<T> {
    private T obj;

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

    public static void main(String[] args) {
        GenericHolder<String> holder = new GenericHolder<>();
        holder.setObj("Item");
        String s = holder.getObj();
    }
}

字節(jié)碼中沧侥,從get()返回的轉(zhuǎn)型消失了拾因,但是在傳遞給set()的值在編譯器會(huì)接受檢查。
這與之前所產(chǎn)生的字節(jié)碼是相同的,而對(duì)set()的類型進(jìn)行檢查是不需要的,因?yàn)檫@將由編譯器執(zhí)行,而對(duì)get()返回的值進(jìn)行轉(zhuǎn)型仍然是需要的,但這個(gè)與不加泛型執(zhí)行的操作是一樣的。但這將由編譯器自動(dòng)插入,減少了讀取與寫入的代碼噪聲。
由于所產(chǎn)生的get()set()是相同的,所以在泛型中所有的動(dòng)作都是在邊界處發(fā)生的贾节,對(duì)傳入的值做額外的編譯期檢查,并插入對(duì)傳遞出去的值的轉(zhuǎn)型。要記住的是,邊界就是發(fā)生動(dòng)作的地方。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颁虐,一起剝皮案震驚了整個(gè)濱河市板熊,隨后出現(xiàn)的幾起案子容劳,更是在濱河造成了極大的恐慌留量,老刑警劉巖可岂,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亚享,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了修然?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵臼朗,是天一觀的道長(zhǎng)挡毅。 經(jīng)常有香客問我耗绿,道長(zhǎng)堕绩,這世上最難降的妖魔是什么黍氮? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任本股,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好城瞎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布强窖。 她就那樣靜靜地躺著咙崎,像睡著了一般伊滋。 火紅的嫁衣襯著肌膚如雪燥撞。 梳的紋絲不亂的頭發(fā)上冠胯,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音脚翘,去河邊找鬼灿巧。 笑死盾似,一個(gè)胖子當(dāng)著我的面吹牛撰茎,可吹牛的內(nèi)容都是我干的炫惩。 我是一名探鬼主播筋蓖,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼赂毯!你這毒婦竟也來了手趣?” 一聲冷哼從身側(cè)響起中符,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤胀瞪,失蹤者是張志新(化名)和其女友劉穎帆谍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谱煤。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刘离,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出踪旷,到底是詐尸還是另有隱情气破,我是刑警寧澤碳锈,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站父晶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏弄跌。R本人自食惡果不足惜甲喝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铛只。 院中可真熱鬧埠胖,春花似錦、人聲如沸淳玩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜕着。三九已至谋竖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間侮东,已是汗流浹背圈盔。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悄雅,地道東北人驱敲。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宽闲,于是被迫代替她去往敵國(guó)和親众眨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 2.簡(jiǎn)單泛型 -********Java泛型的核心概念:告訴編譯器想使用什么類型, 然后編譯器幫你處理一切細(xì)節(jié) 2...
    CodingHou閱讀 391評(píng)論 0 0
  • 本文大量參考Thinking in java(解析容诬,填充)娩梨。 定義:多態(tài)算是一種泛化機(jī)制,解決了一部分可以應(yīng)用于多...
    谷歌清潔工閱讀 462評(píng)論 0 2
  • 附上思維導(dǎo)圖览徒。這篇博客主要講了如下知識(shí)點(diǎn)狈定。 看完了《Thinking in Java》的第十五章泛型,著實(shí)被震了一...
    Happioo閱讀 730評(píng)論 0 1
  • 柳州這邊下雨了习蓬,天氣忽然變的很冷纽什。我聽說老家的雪已經(jīng)積的很厚。學(xué)校的石泥路是不是又 結(jié)冰了躲叼?老同學(xué)芦缰,你們都還好嗎?...
    抹捻閱讀 461評(píng)論 0 0
  • 1.只讓輸入的字母變大寫 方法一 方法二 2.限制只能輸入字母 + 輸入后自動(dòng)變大寫 + 限制輸入字母?jìng)€(gè)數(shù)
    itonny閱讀 521評(píng)論 0 1