本發(fā)明一般而言涉及軟件開發(fā)并且更具體而言涉及在各種編程語言中任何一種語言當中的語言開發(fā)的各方面,作為一個例子,所述編程語言為諸如獨立于平臺的、面向對象的編程語言。
背景技術:
在各種編程語言中,參數(shù)多態(tài)性(例如,泛型)可被認為是使語言更具表達性同時仍保持完全靜態(tài)類型安全性的方式。參數(shù)多態(tài)性可以允許以泛型方式編寫函數(shù)或數(shù)據(jù)類型,使得其可以以相同方式處理各種數(shù)據(jù)類型,而不管它們的類型不同。這樣的函數(shù)和數(shù)據(jù)類型可被稱為泛型函數(shù)和泛型數(shù)據(jù)類型。例如,泛型列表類可被寫為List<T>,這意味著它可以是任何類型T的元素的列表,其中T與List分開指定。
當使用不提供可以是用于所有其它類型的超類型的單個類型的面向對象語言時,經常不能在不使用特定轉換操作的情況下在某些類型上進行泛化,其中所述特定轉換操作為諸如裝箱(例如,自動將基本類型(像int)的值轉換成對應包裝類(像Integer)的對象)。例如,傳統(tǒng)上JavaTM語言不允許對象和基本類型上的泛型。
參數(shù)多態(tài)性(泛型)還可以涉及代碼規(guī)模、生成成本和類型特殊性之間的權衡。例如,編程語言可以支持基本類型特化的泛型,但是可以靜態(tài)地生成特化類,從而潛在增加了代碼占用空間成本和編譯成本。另一種編程語言可以為程序使用的每個實例化生成模板的特化實例化,這可能導致大的靜態(tài)占用空間。還有第三種語言可以使用模板化的字節(jié)碼格式,僅執(zhí)行對運行時的特化,這可能在使用泛型類文件之前需要附加的步驟,從而潛在地損害了運行時性能。
技術實現(xiàn)要素:
雖然運行時特化器可能總是能夠生成泛型類的自動特化版本,但是在某些情況下,可以利用用戶對特化的控制的替代形式。例如,可以使用自動特化,同時還允許使用特定于特化的方法實現(xiàn)。一般地,當將泛型類特化時,泛型類的成員集合可能不變。換句話說,與泛型版本中相同的成員可以存在于自動特化的版本中。但是,特化類的手動精煉可以允許開發(fā)人員將特化類的一個或多個方法的特定(有可能更好)表示和/或實現(xiàn)手動特化。
特化類的手動精煉可以包括利用方法的不同版本來重寫方法的已有或自動特換版本。此外,手動精煉還可以包括在特化類中包括僅用于特定(而不是其他)類型參數(shù)化的另外的方法。因此,可以僅當對特定類型參數(shù)化特化對應的泛型類時,才在特化類中包括精煉方法。
例如,泛型類List可以對任何T是泛型的,并且List的自動特化版本可以包括泛型版本的所有字段和方法,但是如果Lsit對T=int被特化,則特定的一個類方法的新版本還可以被包括在特化類中。因此,根據(jù)一些實施例,如果Lsit對T=int被特化,則可以使用該方法的手動特化版本替代自動特化版本。
附圖說明
圖1是示出根據(jù)一個實施例的、實現(xiàn)特化類的依賴性驅動的共同特化的系統(tǒng)的部件的邏輯框圖。
圖2是示出根據(jù)一個實施例的依賴性驅動的共同特化的邏輯框圖。
圖3是示出如本文所述的用于依賴性驅動的共同特化的方法的一個實施例的流程圖。
圖4是示出根據(jù)一個實施例的、涉及依賴性鏈當中多個依賴性的依賴性驅動的共同特化的邏輯框圖。
圖5是示出根據(jù)一個示例實施例的、包括多個依賴性的依賴性驅動的共同特化的邏輯框圖。
圖6是示出根據(jù)一個實施例的泛型類的部分特化的邏輯框圖。
圖7是示出如本文所述的、用于泛型類的部分特化的方法的一個實施例的流程圖。
圖8是示出根據(jù)一個實施例的、具有依賴性驅動的共同特化的部分特化的邏輯框圖。
圖9是示出根據(jù)一個實施例的特化類的手動精煉的邏輯框圖。
圖10是示出如本文所述的、用于特化類的手動精煉的方法的一個實施例的流程圖。
圖11是示出根據(jù)一個實施例的、用于將新方法添加到特化類的手動精煉的框圖。
圖12是示出如本文所述的、用于經由特化類的手動精練來添加新方法的方法的一個實施例的流程圖。
圖13是示出根據(jù)一個實施例的、用于泛型類的批量替換的手動精煉的邏輯框圖。
圖14是示出如本文所述的、用于經由手動精煉對類進行批量替換的方法的一個實施例的流程圖。
圖15是示出根據(jù)一個實施例的、用于泛型方法的手動精煉的邏輯框圖。
圖16是示出如本文所述的、用于泛型方法的手動精煉的方法的一個實施例的流程圖。
圖17是示出根據(jù)一個實施例的、適于實現(xiàn)特化類的依賴性驅動的共同特化的示例計算機系統(tǒng)的邏輯框圖。
具體實施方式
本文描述了對利用獨立于平臺的、面向對象的語言(諸如JavaTM編程語言)進行軟件開發(fā)的增強的各種實施例,以支持與泛型類型、類和方法的特化相關的各種特征。
例如,特化類的加載或操作可以觸發(fā)其它類的特化。例如,如果第一類擴展特定的超類,則第一類的特化可以觸發(fā)該超類的特化。此外,將類特化可以觸發(fā)作為該類的實現(xiàn)的一部分在內部使用的各個類的特化。根據(jù)一個實施例,編譯器可被配置為識別泛型類之間的依賴性關系,并且依據(jù)基于第一類的特化觸發(fā)其它類的特化的觸發(fā)類型(例如,類型和/或類型參數(shù)化)的類型變量來描述類。
編譯器可以包括在生成類文件時指示類之間的依賴性關系的引用(例如,結構引用)。例如,在一個實施例中,編譯器可被配置為依據(jù)泛型子類型的類型變量將泛型超類型的描述寫出(例如,寫到類文件)。因此,在一些實施例中,類文件可以包括指示一個類和另一個類之間的依賴性關系的信息(例如,元數(shù)據(jù)和/或描述)。加載第一類可以基于依賴性關系而觸發(fā)第二類的加載。此外,根據(jù)各種實施例,可以存在多級依賴性,并且一個類的特化可以觸發(fā)多個其它類的特化,多個其它類的特化又可以觸發(fā)另外一些類的特化。
此外,泛型類可以具有多于一個可特化的類型形參并且可以期望特化其中一個或多個類型變量而不特化其它類型變量(例如,使其它類型變量是泛型)。在一些實施例中,部分特化的結果可以是對剩余類型形參進一步可特化的一個或多個另外的泛型類。根據(jù)一些實施例,在運行時期間執(zhí)行的特化器可被配置為部分地特化泛型類(例如,以產生部分特化類),并且隨后進一步特化該部分特化類以生成完全特化類。因此,不是一次全部執(zhí)行泛型類的特化(諸如將Map<K,V>特化成Map<int,int>或Map<long,int>),而是一個類型形參可被部分地特化(諸如產生Map<K,int>),然后在某個稍后時間,剩余的(一個或多個)類型形參可被特化,諸如生成Map<int,int>或Map<long,int>。
雖然運行時特化器可以總是能夠生成泛型類的自動特化版本,但是在一些情況下,用戶對特化的控制的替代形式可以允許使用自動特化,同時還添加(或重寫)特定于特化的方法實現(xiàn)。一般而言,當類被特化時,泛型類的成員集合可能不改變。換句話說,與泛型版本中相同的成員可以存在于自動特化的版本中。但是,特化類的手動精煉可以允許開發(fā)人員將特化類的特定(有可能更好)表示和/或實現(xiàn)手動特化。根據(jù)各種實施例,替代的以及另外的方法、數(shù)據(jù)布局、字段等可以在原始泛型類(以及泛型類的自動特化版本)與替換類之間變化。因此,在一些實施例中,可以為泛型類提供類、方法、字段等的替換版本,同時維持相同的接口和表示,而在其它實施例中,可以為泛型類的特定特化提供完全不同的表示(例如,不同的和/或另外的方法、數(shù)據(jù)布局、字段等)。
例如,泛型類List可以對任何T是泛型并且List的自動特化版本可以包括泛型版本的所有字段和方法,但是如果List對T=int被特化,則特定的一個類方法的新版本也可以包括在特化類中。因此,根據(jù)一些實施例,如果List對T=int被特化,則該方法的手動特化版本可以代替自動特化版本被使用。特化類的手動精煉可以包括利用方法的不同版本來重寫方法的已有或自動特化版本。此外,手動精煉還可以包括在僅用于特定(并且沒有其它)類型參數(shù)化的特化類中包括另外的方法。因此,可以在僅當對應的泛型類對特定類型形參被特化時,將精煉方法包括在特化類中。
此外,特化可以包括為泛型類提供替換類。特化類的批量替換可以涉及用替換類替換泛型類的自動特化的能力。根據(jù)一些實施例,當類對特定的類型形參被特化時,類的自動特化版本可以完全不被使用并且,代替地,完全不同的手寫類可以被使用。在一些實施例中,可以在編譯泛型類時使用(和/或需要)類的替代的、手寫的特化。但是,在其它實施例中,可以在類被編譯之后(例如,在泛型類被特化之前或當時)使用泛型類的替代(例如,替換或精煉)特化。
此外,替換類可以與泛型或自動特化版本具有相同的接口,但是它可以具有完全不同的表示和/或實現(xiàn)。但是,在一些實施例中,替換類必須具有(例如,可以被要求具有)與泛型或自動特化版本相同的接口。例如,根據(jù)一些實施例,不具有基類的(以及因此類的自動特化版本的)所有方法(例如,所有非私有方法)的替換類可能導致錯誤。
在一些實施例中,替換類可以被要求具有(至少)類的泛型或自動特化版本將具有的所有相同方法(例如,使得類的替代版本遵守Liskov代換原理)。每當特定的特化被實例化時,運行時環(huán)境可以加載類的替代版本。類的泛型或自動特化版本可以包括識別類的替代版本并指示哪些類型參數(shù)化可以觸發(fā)替代版本的使用的信息。
作為替代,識別類的替代版本并指示哪些類型參數(shù)化可以觸發(fā)替代版本的使用的信息可以存儲在除類的泛型或自動特化版本以外的其它地方,諸如在類文件中或信息注冊表中,并且因此當使用類的替代版本時運行時可以不必加載類的泛型或自動特化版本。
在以下詳細描述中,闡述了眾多具體細節(jié),以提供對要求保護的主題的透徹理解。但是,本領域技術人員將理解,要求保護的主題可以在沒有這些具體細節(jié)的情況下實踐。在其它情況下,為了不模糊要求保護的主題,沒有在下面詳細描述方法、裝置或系統(tǒng),因為它們是本領域普通技術人員已知的。
雖然本文通過對若干實施例和說明性附圖的例子描述了各種實施例,但本領域技術人員將認識到,實施例不限于所描述的實施例或附圖。應當理解,附圖及對其的詳細描述不意在將實施例限定到所公開的特定形式,相反,其意在覆蓋屬于本公開內容的精神和范圍內的所有修改、等同物和替代方案。本文中使用的任何標題僅僅是為了組織的目的而不意味著被用來限制描述的范圍。如貫穿本申請所使用的,詞“可以”是在允許的意義上(即,意味著有可能)而不是在強制的意義上(即,意味著必須)使用的。類似地,詞“包括”和“包含”意味著包括但不限于。
以下詳細描述的一些部分是依據(jù)對存儲在特殊裝置或專用計算設備或平臺的存儲器中的二進制數(shù)字信號進行操作的算法或符號表示來給出的。在本特定說明書的上下文中,術語特殊裝置等包括通用計算機,一旦其被編程為根據(jù)來自程序軟件的指令執(zhí)行特定功能。算法描述或符號表示是信號處理或相關領域的普通技術人員用來將他們的工作的實質傳達給本領域其他技術人員的技術的例子。算法在這里,并且一般被認為是導致期望結果的操作或相似信號處理的自一致序列。在這種上下文中,操作或處理涉及物理量的物理操縱。通常,但不是必須,這種量可以采取能夠被存儲、傳送、組合、比較或以其它方式被操縱的電或磁信號的形式。有時候,主要是出于共同使用的原因,將這種信號稱為位、數(shù)據(jù)、值、元素、符號、字符、項、數(shù)字、數(shù)值等被證明是方便的。但是,應當理解,所有這些或相似的術語應當與適當?shù)奈锢砹肯嚓P聯(lián)并且僅僅是方便的標簽。除非另有具體說明,如從下面的討論中顯而易見的,否則應當明白,貫穿本說明書,利用諸如“處理”、“計算”、“確定”等術語的討論是指特殊裝置,諸如專用計算機或類似的專用電子計算設備,的動作或過程。因此,在本說明書的上下文中,專用計算機或類似的專用電子計算設備能夠操縱或變換通常表示為存儲器、寄存器或其它信息存儲設備、傳輸設備或專用計算機或類似專用電子計算設備的顯示設備中的物理電子或磁量的信號。
現(xiàn)在轉到圖1,圖1示出了根據(jù)各種實施例的、用于編譯和執(zhí)行在高級、獨立于平臺的面向對象語言中指定的計算機程序的工作流,其中所述語言支持基本和引用數(shù)據(jù)類型以及如本文所述關于泛型類和/或方法的特化的各種方法、特征和增強。為了說明的目的,以下描述主要在使用JavaTM編程語言的上下文中提供。但是,應當指出的是,所描述的技術可以與在適當?shù)纳舷挛闹兄С侄喾N類型(諸如基本類型、引用類型、記錄類型、聯(lián)合類型等)及其特化的幾乎任何面向對象的編程語言一起使用。
根據(jù)所示實施例,當諸如編譯器120之類的編譯器可以在一個或多個計算設備上實現(xiàn)并且可以接收用于計算機程序的源代碼(諸如源代碼110)時,工作流可以開始。在各種實施例中,源代碼110可以在各種高級和/或獨立于平臺的、面向對象的編程語言(諸如JavaTM和/或其它語言)中指定。例如,在使用JavaTM的實施例中,源代碼可以被提供為一組.java文件。在一些實施例中,源代碼110可以利用可以包括一種或多種低級和/或中間語言(例如,匯編)的語言的組合來指定。在一些實施例中,源代碼中的至少一些可以最初以諸如Python或Ruby之類的動態(tài)類型的高級語言來編寫,而在其它實施例中,所有源代碼可以以諸如JavaTM之類的靜態(tài)類型的語言來編寫。
一般而言,類可以被認為是用戶定義的類型或數(shù)據(jù)結構,其可以包括作為成員的數(shù)據(jù)、變量、函數(shù)、方法和/或其它屬性,并且表示用于創(chuàng)建特定類型的編程對象程序的定義、藍圖或模板。類可以為數(shù)據(jù)成員提供初始值并且為成員函數(shù)和方法提供實現(xiàn)。類經常包括在庫中。庫可以被認為是由軟件程序或應用使用的資源的集合。根據(jù)一些實施例,庫可以包括各種類型的資源中任何一種,包括但不限于數(shù)據(jù)、文檔、類、子例程和/或類型規(guī)范。庫可以被組織成以便由多于一個應用(有可能在相同的時間)使用,并且可以通過提供資源來促進可重用性,使得應用可以不必實現(xiàn)(或重新實現(xiàn))相同的行為。
編譯器120可以分析源代碼110,以產生程序的可執(zhí)行版本或者字節(jié)碼文件,諸如所描繪的實施例中的加注釋的(一個或多個)類文件130(例如,在JavaTM的情況下是.class文件或.jar文件)。在各種實施例中可以使用不同類型的可執(zhí)行代碼格式;例如,可以使用二進制機器語言代替字節(jié)碼。在一些場景中,可執(zhí)行代碼(例如,加注釋的類文件130)的部分可以是字節(jié)碼,而其它部分是原生二進制機器語言。
根據(jù)一些實施例,作為將程序源代碼110編譯成可執(zhí)行代碼(例如,加注釋的類文件130)的一部分,編譯器120可以在生成可執(zhí)行版本之前執(zhí)行一系列分析操作并生成各種中間數(shù)據(jù)結構,諸如應用或實現(xiàn)特化。例如,編譯器可以利用泛型類中程序元素的編碼(加注釋或修飾)形式來應用類型擦除操作,從而創(chuàng)建加注釋的類文件130。如上面所指出的,程序元素的編碼形式可以包括指示類(或方法)聲明的哪些類型變量已被擦除以及哪些類型是類型變量的擦除物的元數(shù)據(jù)。
在一些實施例中,諸如編譯器120之類的編譯器可以保留傳統(tǒng)上在編譯過程期間可能不被保留的某些類型的信息。例如,在一個實施例中,編譯器120可以保留作為執(zhí)行擦除的一部分被使用的信息。編譯器可以在加注釋的類文件130中包括這種信息(的至少部分)作為關于特化的元數(shù)據(jù)。
例如,類型擦除操作可以利用泛型類中程序元素的編碼(或加注釋)形式來應用。程序元素可以表示類簽名或聲明、方法簽名或聲明、指令、指令的實參,以及表示、移動或操縱數(shù)據(jù)的幾乎任何程序元素。
程序元素的編碼形式可以包括指示類(或方法)聲明的哪些類型變量已被擦除以及哪些類型是類型變量的擦除物的元數(shù)據(jù)。此外,元數(shù)據(jù)可以包括各種類型的與特化相關的信息。例如,元數(shù)據(jù)可以指示對類(或方法聲明)的類型變量的值進行操作的指令。類似地,元數(shù)據(jù)可以指示實參指示作為類或方法聲明的類型變量的擦除物的類型。
根據(jù)一些實施例,加注釋的類文件中的元數(shù)據(jù)可以包括指示哪些類型變量已被擦除以及哪些類型是類型變量的擦除物的特化信息。類型擦除涉及泛型在編程語言(例如,Java語言)中的使用。當執(zhí)行類型擦除操作時,編譯器可被配置為用它們的界限或者如果類型形參無界限的話利用Object類型替換泛型類型中的所有類型形參。所生成的字節(jié)碼因此可以僅包含普通的類、接口和方法。
此外,結構描述可被用來擴展在運行時環(huán)境中描述類的方式。代替僅通過名稱來描述類并且使用該名稱來定位這個類(例如,在盤上的類文件中),類可以被稱為代碼生成器函數(shù)以及有可能一些實參的組合。換句話說,在一些實施例中,類可以通過指定生成器函數(shù)的結構描述以及可能的用于該生成器函數(shù)的一個或多個形參來描述。在一些實施例中,結構描述可以被認為是用于其中類名稱可被使用的幾乎任何情況(例如,實參類型、返回類型、字段類型、超類型、instanceof或cast運算符的操作數(shù)等)的類名稱(例如,可以代替類名稱被使用)。
因此,在一些實施例中,編譯器和/或虛擬化的運行時環(huán)境可被配置為允許利用結構描述來描述類。例如,可以利用結構描述來描述類之間的依賴性關系(例如,超類/子類關系)。根據(jù)一些實施例,類的結構標識可以利用結構描述來使用,諸如以擴展類在運行時環(huán)境中被描述的方式。根據(jù)一些實施例,類的結構描述可以出現(xiàn)在任何地方,而類名稱可以出現(xiàn)在純粹名義上的VM(例如,未被配置為支持結構描述作為類名稱的VM)中。例如,類的結構描述可以作為或代替實參類型、返回類型、字段類型、超類型、instanceof或cast運算符的操作數(shù)出現(xiàn),并且一般而言在類名稱可被使用的任何地方。
如圖1中所示,加注釋的類文件130可以被傳遞到在執(zhí)行平臺100上執(zhí)行代碼的執(zhí)行環(huán)境,諸如虛擬化的運行時環(huán)境140,由此創(chuàng)建各種輸出數(shù)據(jù)和/或行為。根據(jù)各種實施例,虛擬化的運行時環(huán)境140又可以包括多個不同的部件,諸如存儲器管理器160、特化器170、類加載器175、字節(jié)碼驗證器180(例如,以檢查可執(zhí)行代碼的有效性),和/或解釋器和/或即時(JIT)編譯器185。在一些實施例中,JIT編譯器可以負責將一些或全部字節(jié)碼(例如,字節(jié)碼的被頻繁使用的部分)翻譯成特定于平臺的機器碼,以提高程序執(zhí)行的性能。在一些實施例中,虛擬化的運行時環(huán)境140還可以包括實現(xiàn)多個應用編程接口(API)庫190的代碼。在一些實施例中,虛擬化的運行時環(huán)境140可以在諸如操作系統(tǒng)195的較低層軟件之上運行。
在不同的實施例中,作為經編譯的代碼的執(zhí)行的結果而產生的輸出或行為可以包括存儲在各級系統(tǒng)存儲器中的數(shù)據(jù)(例如,內存對象和/或數(shù)據(jù)結構)、存儲在持久存儲裝置上的數(shù)據(jù)(例如,文件系統(tǒng)上的文件)等。行為還可以包括各種程序功能,諸如在屏幕上顯示輸出、經網絡發(fā)送消息,和/或以其它方式與各種用戶和/或部件交互。
在一些實施例中,虛擬化的運行時環(huán)境140可以使用由編譯器120生成的加注釋的(一個或多個)類文件130。根據(jù)一些實施例,在加載要利用特定參數(shù)化特化的類時,虛擬化的運行時環(huán)境140可以使用加注釋的類文件130作為模板(連同要用于進行特化的形參一起)并且可以產生作為被特化的類的特定特化的新類。例如,當特化類時,一組類型形參可以是用于特化的輸入的一部分(例如,List<any T>可以利用T=int作為形參被特化,以獲得List<int>)。一般而言,加注釋的類文件130可被認為是利用特化相關的元數(shù)據(jù)標記的類文件。此外,根據(jù)各種實施例,加注釋的類文件130可以變成作為加注釋的類的特化的新類。
特化類的依賴性驅動的共同特化
根據(jù)一些實施例,特化類的加載或操作可以觸發(fā)其它類的特化。例如,如果“class ArrayList<T>extends AbstractList<T>”,則ArrayList<int>的實例化可以要求AbstractList<int>的解析。類似地,給定作為其實現(xiàn)的一部分在內部包括表示映射的節(jié)點的類的類Map<keyType,ValueType>,該類的keyType和valueType也將是泛型。利用依賴性驅動的共同特化,根據(jù)一些實施例,當泛型類Map<keyType,valueType>被實例化為從int到long的映射(例如,Map<int,long>)時,Map<int,long>的特化實現(xiàn)可以然后觸發(fā)(一個或多個)依賴類型(諸如上面提到的內部節(jié)點類)的特化。
因此,根據(jù)一些實施例,諸如編譯器120之類的編譯器可以識別泛型類之間的依賴性關系并且可以依據(jù)觸發(fā)類型(例如,觸發(fā)依賴類型的特化的類型)的類型變量來描述依賴類型。例如,當編譯器寫出類文件而不是名義上寫/做一切時,諸如當ArrayList<T>被擦除成只有ArrayList以使得ArrayList擴展List時(如在遺留編譯器中所做的那樣),被配置為實現(xiàn)依賴性驅動的共同特化的編譯器可以包括指示類文件中的依賴性關系的結構引用。
例如,如果ArrayList extends List,而不是僅使用名稱List,則編譯器可以利用引用例如“通過利用類型形參T對List應用特化變換而產生的類”的結構描述。換句話說,編譯器120可被配置為依據(jù)泛型子類型的類型變量將泛型超類型的描述寫出(例如,寫到類文件)。因此,類文件可以包括指示類ArrayList<T>擴展通過對實參(例如,T)應于特化代碼生成器而產生的類的描述。加載ArrayList可以觸發(fā)List的加載并且List可以由結構描述來描述,使得特化器(和/或類加載器)可以應用結構描述來生成用于T的特定參數(shù)化的類List并將其加載到運行時高速緩存中。其后,List可以能夠用于諸如通過ArrayList來擴展。
根據(jù)一個實施例,在超類的結構描述中(例如,在ArrayList<T>extends List<T>的例子中),來自ArrayList的類型變量T出現(xiàn)在超類型的結構描述中,使得,當ArrayList<T>對T=int被特化時,超類型的結構描述中T的出現(xiàn)被int替換。因此,如在ArrayList中聲明的T的類型形參給出了“T”在“extends”子句和ArrayList主體中出現(xiàn)的含義。當類被生成時,類ArrayList<int>可以擴展通過應用List對int的特化變換而產生并且可以觸發(fā)List<int>的加載的類,從而讓ArrayList<int>擴展List<int>。
根據(jù)一些實施例,當在“<>”之間被聲明時,類型形參T引入類型變量T,類似于在方法的“()”之間聲明的形式參數(shù)引入變量的方式。類型變量T可以在泛型類的簽名中(例如,如在“extends”子句中)以及在泛型類的主體中(例如,如在字段的類型中)使用。根據(jù)一些實施例,在泛型類的簽名中,類型變量T可以出現(xiàn)在類型實參位置(例如“extends AbstractList<T>”),但是不能出現(xiàn)在頂層位置(例如,“extends T”)。但是,在泛型類的主體中,類型變量T可以出現(xiàn)在類型實參位置(例如,作為字段聲明,諸如“List<T>f;”)以及在頂層位置(例如,作為字段聲明,諸如“T f;”)。根據(jù)一些實施例,每當類型變量T在類型實參位置被使用時,共同特化可以被觸發(fā)。
在運行時,一個類型(或類)的特化可以觸發(fā)其它類型的特化。例如,根據(jù)一些實施例,如果Foo<T>的實現(xiàn)引用Bar<T>,則Foo的特化可以觸發(fā)Bar的特化(例如,因為可能需要Bar完成用于Foo的代碼的特化)。運行時環(huán)境,諸如虛擬化的運行時環(huán)境140,可以利用各種類型的信息中的任何一種來識別依賴性關系,諸如通過由編譯器使用關于類文件中所包括的依賴類型的信息。
現(xiàn)在轉到圖2,圖2是示出如本文所述的特化類的依賴性驅動的共同特化的一個示例實施例的邏輯框圖。如圖2中所示,類文件200可以包括具有依賴性關系230的泛型類A 210和泛型類B 220。例如,在一個實施例中,類A可以依賴于類B。根據(jù)一些實施例,當依賴性特化器250將類A特化以生成類A 260時,諸如在對特定的類型參數(shù)化的類A的實例化時,依賴性特化器250可以確定(例如,識別)類A和類B之間的依賴性關系并且因此還可以將類B特化以生成類B 270。因此,泛型類A 210和泛型類B 220之間的依賴性關系230可以在類A被特化的任何時候觸發(fā)類B的特化。
從開發(fā)人員的角度來看,共同特化簡單地基于不同類型(或類)之間的依賴性關系自動發(fā)生(例如,無需開發(fā)人員的任何特定命令)。
圖3是示出如本文所述的用于特化類的依賴性驅動的共同特化的方法的一個實施例的流程圖。如方框300中所示,用于實現(xiàn)依賴性驅動的共同特化的方法可以包括在獨立于平臺的面向對象的運行時環(huán)境中特化利用面向對象的編程語言定義的第一泛型類。第一泛型類可以包括一個或多個可特化的類型變量并且這一個或多個類型變量中的每一個可以是經一個或多個類型參數(shù)化可特化的。此外,第一泛型類可以對特定的一個類型參數(shù)化被特化。
例如,如上所述,在類文件200中定義的泛型類A 210可以對特定的類型參數(shù)化被實例化。因此,該泛型類可以對于該特定的類型參數(shù)化在虛擬運行時環(huán)境140中(例如,在獨立于平臺的面向對象的運行時環(huán)境中)被特化。
根據(jù)一個示例實施例,基于Java的類ArrayList<T>可以對類型int被特化。因此,根據(jù)示例實施例,泛型類ArrayList可以對T=int在基于Java的虛擬機中被特化。
如方框310中所示,根據(jù)一些實施例,可以在第一泛型類和第二泛型類之間確定依賴性關系。例如,運行時環(huán)境的特化器(諸如虛擬化的運行時環(huán)境140的特化器170和/或依賴性特化器250)可被配置為確定兩個類之間的依賴性關系,諸如圖2中所示的泛型類A 210和泛型類B 220之間的依賴性關系230。
根據(jù)各種實施例,兩個類之間的依賴性可以涉及類型或類B在類A中幾乎任何類型使用(例如,通過其被創(chuàng)建或觸發(fā))。例如,依賴性關系可以涉及超類型、字段描述符、方法描述符的使用,或者另一泛型類型或類在方法主體中的使用(或者通過其被定義/創(chuàng)建)。作為一個例子,類ArrayList<T>可以擴展AbstractList<T>,由此創(chuàng)建(例如,定義)類ArrayList<T>和類AbstractList<T>之間的依賴性關系。
每當泛型類型形參(例如,在上面的例子中由<T>表征的)出現(xiàn)時,依賴性驅動的共同特化可以被觸發(fā)。因此,根據(jù)一些實施例,在泛型類型形參作為超類型、作為轉換(cast)的目標、作為方法形參的類型或返回類型出現(xiàn)的任何時候,或者類型形參可以出現(xiàn)的幾乎任何地方,依賴性驅動的共同特化可以被觸發(fā)(例如,特化可以發(fā)生)。因此,根據(jù)一些實施例,如果特定的泛型類幾乎出現(xiàn)在任何地方(例如,在依賴類的API或實現(xiàn)中),則為了能夠生成/特化依賴類,特定的泛型類也可以被生成/特化(例如,在依賴類的生成/特化之前、期間或之后)。
如方框320中所示,根據(jù)一個實施例,響應于確定依賴性關系,第二泛型類可以基于所確定的依賴性關系對特定的類型參數(shù)化被特化。繼續(xù)上面的例子,ArrayList<T>對特定的類型參數(shù)化的特化可以觸發(fā)AbstractList<T>對相同參數(shù)化的特化。根據(jù)一些實施例,如果類ArrayList<T>被實例化,并且因此對T=int被特化,則類AbstractList<T>也可以對T=int被特化。
此外,類(或其它類型)之間的相同依賴性關系也可被用來觸發(fā)對不同參數(shù)化的特化。例如,對int特化ArrayList<T>可以觸發(fā)AbstractList<T>對int的特化。隨后,ArrayList<T>可以對long被特化,這可以觸發(fā)AbstractList<T>對long的特化。換句話說,根據(jù)一些實施例,一旦定義了兩個泛型類之間的依賴性關系,則每當?shù)谝活惐惶鼗瘯r,該依賴性關系可以觸發(fā)依賴類的特化(并且不管多少次)。
雖然上面利用基于超類關系的依賴性進行了描述,但是在其它實施例中,依賴性可以基于類之間的其它關系。例如,如果助手類LinkedListNode<T>嵌套在類LinkedList<T>的主體中,則LinkedList<T>的實例化可以觸發(fā)LinkedListNode的共同特化。
雖然在上面被描述為按特定次序執(zhí)行的兩個單獨且不同的特化,但是根據(jù)各種實施例,第一和第二泛型類的特化可以按任何次序發(fā)生和/或可以重疊。例如,在一個實施例中,特化器250可以確定第一泛型類和第二泛型類之間的依賴性關系并且,作為響應,可以在特化第一泛型類之前特化第二泛型類。在另一實施例中,特化器250可以開始特化第一泛型類、確定依賴性關系、特化第二泛型類,然后完成第一泛型類的特化。
雖然以上關于圖2和圖3的例子示出了兩個類之間的單個依賴性關系,但是依賴性驅動的共同特化可以涉及多層(甚至許多層)依賴性(或依賴性鏈)。在一些實施例中,在深度和廣度兩方面都可以存在許多級的依賴性。例如,圖4是示出根據(jù)一個實施例的、涉及依賴性鏈中多個依賴性的依賴性驅動的共同特化的邏輯框圖。如圖4中所示,類文件可以包括多個泛型類,諸如泛型類A 410、泛型類B 420、泛型類C 440和泛型類D 430。此外,類文件可以定義泛型類之間的依賴性關系。例如,泛型類A 410可以依賴于泛型類B 420和泛型類C 440,如由依賴性關系425和435所示。此外,泛型類B 420本身可以依賴于泛型類D 430,如由依賴性關系435所指示的。
因此,當被配置為實現(xiàn)依賴性驅動的共同特化的運行時環(huán)境的特化器(諸如虛擬化的運行時環(huán)境140的依賴性特化器450)特化泛型類A 410以生成類A 460時,它可以確定(或識別)泛型類A 410與泛型類B 420和泛型類C 440之間的依賴性關系。響應于確定依賴性關系(例如,當特化泛型類A 410時),依賴特化器450可以特化泛型類B 420和泛型類C 440,以分別生成類B 470和類C 480。
此外,當特化泛型類B 420時,無論是獨立地(例如,由于類B的獨立實例化)還是響應于泛型類A 410的特化,依賴性特化器450都可以特化泛型類D 430,以生成類D 490。
如上面所指出的,兩個類之間的依賴性關系可以基于類之間的各種關系來定義。例如,根據(jù)各種實施例,兩個類之間的依賴可以存在,因為一個類擴展另一個類、或者因為其實現(xiàn)引用另一個類,或者因為其API將另一個類命名為它的其中一個實參或返回類型。
當?shù)谝环盒皖惐惶鼗瘯r,在一些實施例中,特化器可以基于第一泛型類和任何其它泛型類之間的依賴性關系“跟蹤”任何依賴性鏈并相應地特化其它類。
圖5是示出根據(jù)一個示例實施例的、包括多個依賴性的依賴性驅動的共同特化的邏輯框圖。如圖5中所示,類文件可以包括多個類定義,諸如類510、512、514、516和518。類文件中的一個(或多個)類可以依賴于其它類。例如,類510可以依賴于類512、514、516和518。例如,以下示例代碼示出了依賴于其它類的類510的可能定義:
因此,類SortedList依賴于多個其它類,諸如List、Comparator、Collection和Set。具體而言,List是SortedList的超類,Comparator在字段簽名中作為SortedList的形參被命名,Collection在方法簽名中被命名,并且類Set在方法的主體內被使用。因此,SortedList基于不同類型的依賴性關系依賴于每個其它類。
當將類510特化以生成類530時,根據(jù)一個示例實施例,依賴性特化器520可以確定類SortedList依賴于其它類并且,作為響應,可以將類512、514、516和518分別特化以生成類532、534、536和538。具體而言,根據(jù)一個實施例,特化SortedList<int>可以觸發(fā)List<int>(超類)、Comparator<int>(字段簽名)、Collection<int>(方法簽名)、Set<int>(方法主體)的特化。
此外,特化的定時可以從實施例到實施例有所變化,諸如依賴于不同運行時環(huán)境之間的差異。例如,在一個實施例中,可以直到方法countUnique在程序執(zhí)行期間真正被調用,Set<int>才被特化。
雖然上面的例子使用公有類型,但是依賴性驅動的共同特化不限于公有類型。例如,以下樣本代碼示出了具有非公有類型的依賴性驅動的共同特化:
根據(jù)一些實施例,在上面的例子中,雖然類Node對于LinkedList是私有的,但是每當LinkedList被特化時,它可以被特化。
此外,作為特化單個依賴類的一部分,相同的泛型類可以對不同的類型形參被特化多次。作為一個非常簡單的例子,接口Map<K,V>可以利用兩個不同的ArrayList來實現(xiàn),一個用于鍵,一個用于值,如以下示例代碼中所示:
在上面的例子中,ArrayList基于K和V的各個類型形參被共同特化。
特化類的部分特化
泛型類可以具有多于一個可特化的類型形參,諸如在例子中是Map<K,V>??赡芷谕鼗渲幸粋€或多個類型變量,而不特化其它類型變量(例如,保留其它類型變量是泛型)。圖6是示出根據(jù)一個實施例的泛型類的部分特化的邏輯框圖。根據(jù)一些實施例(特化器,諸如虛擬化的運行時環(huán)境140的部分特化器620)可被配置為部分地特化泛型類610,以產生部分特化的類630,并且還可被配置為隨后進一步特化部分特化類630,以生成完全特化類640。
例如,泛型類610可以表示泛型類Map<K,V>并且部分特化器620可被配置為將泛型類610特化成具有泛型鍵但對于值具有int值的映射,諸如Map<K,int>。作為替代,泛型類Map<K,V>可被特化成對于鍵具有int值但具有泛型值的映射,諸如在Map<int,V>中。這在本文中可以被稱為“部分特化”。
在一些實施例中,部分特化的結果可以是對剩余的類型形參進一步可特化的一個或多個另外的泛型類。例如,部分特化類630可以表示Map<K,int>并且可以進一步特化以生成完全特化類640,完全特化類640可以表示對鍵具有特定類型的一個或多個映射,諸如Map<int,int>或Map<long,int>。換句話說,對于具有多于一個類型變量的泛型類型(例如,Map<K,V>),其中一個類型變量可被特化(例如,Map<int,V>),而不特化其它(一個或多個)類型變量。結果所得的類可以被認為是可進一步被特化的部分特化類。
因此,不是一次全部執(zhí)行泛型類的特化(諸如通過將Map<K,V>特化成Map<int,int>或Map<long,int>),而是一個類型形參可被部分特化,諸如產生Map<K,int>,然后在某個稍后時間,剩余的(一個或多個)類型形參可被特化,諸如生成Map<int,int>或Map<long,int>。
雖然在圖6中被示為將部分特化類630存儲回類文件200,但是在一些實施例中,部分特化類630可以存儲在不同位置,諸如在單獨的類文件中或者在虛擬化的運行時環(huán)境140中的存儲器中等。
圖7是示出如本文所述的用于泛型類的部分特化的方法的一個實施例的流程圖。如方框700中所示,泛型類可以被部分特化。根據(jù)一個實施例,泛型類可以包括多個可特化的類型變量,其中每個類型變量可以經多個類型參數(shù)化是可特化的。
如方框710和720中所示,將泛型類部分特化可以涉及經多個類型參數(shù)化中特定的一個類型參數(shù)化對多個類型變量中特定的一個類型變量將泛型類特化,如方框710中所示,并且不對另一個可特化類型變量將泛型類特化,如方框720中所示,使得部分特化類可對多個類型參數(shù)化中每一個對多個可特化類型變量中至少另一個可特化類型變量進一步可特化。例如,
interface Map<any K,any V>{...}
可以對一個類型變量(諸如K)被部分特化,而不特化另一個類型變量。例如,在以下例子中,
class IntBasedMap<any V>implements Map<int,V>{...}
IntBasedMap可以是Map的部分特化。僅Map的一個類型變量(例如,K)被特化,因此允許IntBasedMap(例如,部分特化的Map<int,V>)經Map可特化的任何或全部類型參數(shù)化對V被進一步特化。在一些實施例中,部分特化類可以經該類可特化的多個可能的類型參數(shù)化當中每一個類型參數(shù)化進一步可特化。因此,根據(jù)各種實施例,在如上面的例子中那樣對K=int被部分特化之后,部分特化的Map(例如,作為IntBasedMap)可以經其它類型參數(shù)化針對V進一步特化,諸如對V=long、V=boolean、V=String等。此外,如上面的例子中所示,部分特化類(諸如Map<int,V>)可以看起來像參數(shù)化的類型(例如,在“extends”子句中)。在一些實施例中,參數(shù)化的類型(例如,Map<int,V>)可被識別為泛型類(例如,Map<K,V>)的部分參數(shù)化,并且泛型類可被部分特化以形成另一泛型類(例如,Map<int,V>),從而允許形成參數(shù)化的類型。形成參數(shù)化的類型常常可以意味著通過將類型實參綁定到類型形參K和V來“實例化”泛型類Map<K,V>,但是在一些實施例中,恒等函數(shù)可被應用到部分特化的泛型類Map<K,V>,以形成參數(shù)化的類型,類似于類型String是應用到非泛型類String的恒等函數(shù)的方式。
如方框730中所示,根據(jù)一些實施例,然后,部分特化類可以隨后對另一個可特化的類型變量被進一步特化,使得部分特化類變得完全特化。繼續(xù)上面的例子,部分特化的Map<int,V>(例如,作為IntBasedMap)可以對剩余的類型變量(例如,V)進一步被特化,如在下面的示例代碼中:
class IntToIntMap extends IntBasedMap<int>{...}
因此,根據(jù)一個示例實施例,Map<int,V>可以對V=int(作為一個例子)被進一步特化,得到Map<int,int>(例如,經由IntBasedMap和IntToIntMap)。此外,經一個類型參數(shù)化被進一步特化之后,相同的部分特化類可以經其它的類型參數(shù)化被進一步特化。例如,相同的部分特化的Map類可以對V=long被進一步特化,如在以下的示例代碼中:
class IntToLongMap extends IntBasedMap<long>{...}
在一些實施例中,類的部分特化可以通過以下來實現(xiàn):部分特化注入到類中的元數(shù)據(jù)(例如,為了使類可特化),然后將部分特化的元數(shù)據(jù)傳播到新的、部分特化的類文件中,使得部分特化的結果可重新特化。因此,根據(jù)一些實施例,部分特化可以通過將特化元數(shù)據(jù)的投影從原始類正向傳播到部分特化的結果中來實現(xiàn)。
這可以通過開發(fā)人員編寫他的代碼的方式——他想要具有不同級別的部分特化的方式——來實現(xiàn)。如本文所述,將泛型類特化可以有兩個不同的原因。首先,將泛型類特化會導致更好的性能(例如,對int的操作比對對象的操作更快),其次,泛型類可以被特化,以利用關于實參的特定信息(例如,諸如添加僅適用于某些類型形參的新功能)。
因此,即使你不知道關于值的任何內容(例如,Map<int,V>),具有其中鍵是int的Map也是有益的。然后,這個部分特化的Map類可被特化,以使用特定的映射值,而不必特化整個類(例如,因為Map<K,V>已被部分特化成Map<int,V>)。
因此,根據(jù)一些實施例,類的部分特化可以涉及類的特化,以產生進一步可特化的類。例如,下面是HashMap的部分特化:
class IntMap<K>extends HashMap<K,int>
HashMap的部分特化需要將元數(shù)據(jù)(如上所述)傳播到所生成的類中,使得類型變量K可被進一步特化,并且允許將該進一步特化的結果識別為HashMap<K',int>的子類型。
在一些實施例中,部分特化類可被顯式地聲明,諸如在以下示例代碼中:
class HashMap<int,V>implements Map<int,V>
作為替代,可以自動生成(例如,由運行時環(huán)境)多個不同的部分特化(例如,Map<int,V>、Map<long,V>等),每當特定類型的使用發(fā)生時,其本身根據(jù)需要是可特化的。因此,可以存在多個不同的部分特化并且它們可以出現(xiàn)在類文件中基于可特化的泛型類的參數(shù)化的類型可能出現(xiàn)的任何地方(例如,超類型、局部變量、字段類型、方法形參的類型、類型轉換等)。
此外,部分特化可以與上述依賴性驅動的共同特化相結合。圖8是示出根據(jù)一個實施例的、具有依賴性驅動的共同特化的部分特化的邏輯框圖。泛型類810可以包括多個泛型類型變量并且可以由虛擬化的運行時環(huán)境140的特化器850部分特化,以生成部分特化類820。此外,泛型類810可以依賴于泛型類840,如由依賴性關系830所指示的。如上面所指出的,依賴性關系可以涉及超類型、字段描述符、方法描述符、或者另一泛型類型或類在方法主體中的使用(或者通過其定義/創(chuàng)建)。例如,泛型類810可以表示泛型類Map<K,V>,它可以利用被表示為泛型類840的泛型MapNode類作為其實現(xiàn)的一部分,如在以下的示例代碼中:
當特化器870部分地特化泛型類810以生成部分特化類820時,特化器870可以確定或識別泛型類810和泛型類840之間的依賴性關系,并且因此可以(部分地)特化泛型類840,從而生成部分特化類860。例如,對K=int部分特化Map<K,V>可以觸發(fā)MapNode<K,V>對K=int的部分特化,如以下示例代碼中所示:
隨后,根據(jù)一個實施例,部分特化類820可被進一步特化,以生成完全特化類880,這還可以觸發(fā)部分特化類860的進一步特化,以生成完全特化類890。例如,部分特化的Map<int,V>可以對V=int被進一步特化,從而觸發(fā)MapNode(int,V)對V=int的進一步特化,如以下示例代碼中所示:
作為另一個例子,泛型類HashMap<K,V>可以擴展Map<K,V>。根據(jù)一些實施例,諸如對K=int部分特化HashMap,可以觸發(fā)Map對K=int的(部分)特化。
作為又一個例子,Map<K,V>的方法可以采用從V到U的映射函數(shù),并返回Map<K,U>(其映射可以對原始映射中的所有(k,v)都是(k,mapper(v)))。當Map被部分特化時,映射器函數(shù)的特化可以基于映射類和映射器函數(shù)之間的依賴性關系被觸發(fā),如下面的示例代碼中所示:
特化類的手動精煉
雖然運行時特化器可以總是能夠生成泛型類的自動特化版本,但是在一些實施例中,對特化的用戶控制的替代形式可以涉及使用自動特化同時還添加(或重寫)特定于特化的方法實現(xiàn)。一般而言,根據(jù)一些實施例,泛型類的成員集合在其被特化時不改變——在自動特化版本中存在與泛型版本中相同的成員。但是,特化類的手動精煉可以允許開發(fā)人員手動特化特化類的一個或多個方法的更好表示和/或實現(xiàn)。
換句話說,泛型類List對任何T可以是泛型,并且List的自動特化版本可以包括泛型版本的所有字段和方法,但是如果List對T=int被特化,則特定方法的新版本可以被包括。因此,根據(jù)一些實施例,List對T=int被特化,該方法的手動特化版本可以代替自動特化版本被使用。
作為另一個例子,用于特定類型參數(shù)化的方法可以被添加到ArrayList,如下所示:
在一些實施例中,某些方法對泛型類的一些實例化可能是有意義的,但對于其它實例化沒有意義。例如,如果T是int或long,但不是Shoe或某個其它對象,則List<T>上的sum()方法可能有意義。一些實施例可以包括關于給定實例化的條件成員的聲明-地點機制。這也可以包括如果它們都出現(xiàn)則可能彼此不一致的成員,諸如對于List<int>的int承載sum()方法和對于List<double>的double承載sum()方法。此外,一些實施例可以包括類文件表示,當類被實例化為已擦除類時,即,沒有任何類型參數(shù)化,該類文件表示允許忽略某些成員。
特化類的手動精煉,以重寫功能
根據(jù)一些實施例,特化類的手動精煉替換(重寫)否則將由特化器生成的功能。以類似于如上所述的自動特化類的批量替換的方式,方法也可以被(手動地)添加以替換功能,諸如重寫自動特化的成員。
對于泛型類的一些實例化,替換自動特化的版本會是優(yōu)選的。一些實施例可以包括以下機制(諸如語言機制):通過該機制,單個類文件可以既描述類成員的泛型版本,又在一個或多個特定于實例化的層中“重寫”該泛型版本。于是,類既可以包括方法的泛型版本,又可以包括用于特定類型特化的方法的替代版本。
圖9是示出根據(jù)一個實施例的特化類的手動精煉的邏輯框圖。如圖9中所示,類文件200可以包括類A 900,類A 900包括當類A900被特化時可被自動特化的已有方法910。此外,類A 900還可以包括當類A 900對特定類型形參被特化時代替已有方法920被使用的精煉方法920。當類A 900被特化時,精煉特化器930可被配置為確定該類正在對其被特化的特定的類型參數(shù)化是否是應當使用該精煉方法的類型參數(shù)化。換句話說,特化器可以確定精煉方法與類正在對其被特化的特定的類型參數(shù)化對應。如果精煉特化器930確定應應當使用精煉方法920,則精煉特化器930可以加載并特化包括該精煉方法的類,如由類A 940和精煉方法950所示。作為替代,如果類正在對該精煉方法不應當被使用的不同類型參數(shù)化被特化,則精煉特化器930可以利用已有方法910的自動特化版本來加載和特化該類,如由類A 960和自動特化方法970所示。
因此,根據(jù)一些實施例,通過對特定類型參數(shù)化重寫特定方法(或添加新方法),用戶控制的替代形式可被用來增強特化。因此,開發(fā)人員可以能夠對一些類型利用最佳可能的實現(xiàn),同時對其它類型依賴于通用(例如,自動特化的)版本。例如,List<int>可以具有sum()方法,或者已有方法的優(yōu)化版本可以對特定類型參數(shù)化被手動編寫。泛型類的用戶不必知道關于手動精煉的任何內容。例如,泛型類的用戶不必為了利用手動精煉或重寫版本而請求或指定使用手動精煉或重寫版本。相反,根據(jù)一些實施例,僅僅對特定類型形參實例化類就可以觸發(fā)手動精煉的使用(例如,如由泛型類的開發(fā)者提供的),而無需用戶對泛型類的任何特定知識或請求。
在一個實施例中,泛型類的開發(fā)者可以寫(例如,重寫的方法的)多個版本并且編譯器可被配置為將該代碼編譯成類文件中的多個版本。類文件還可以包括指示對哪些類型特化使用哪些版本的信息。此外,運行時環(huán)境可被配置為使用類文件中的信息來確定在加載特定特化時要使用哪個版本。
作為另一個例子,類Box可以保存值,如以下示例代碼中所示:
在上面的例子中,方法toString可以對所有類型T起作用,但是可能是為了給出更好的答案,或者是由于更快的實現(xiàn),toString()的更特化的版本可以提供T=int的Box的實例化。此外,在一些實施例中,附加的類型約束(T=int)可以在toString()的特化版本的主體中使用,以便對主體進行類型檢查,諸如以便確保編譯器知道“t”的類型實際上是“int”而不是泛型“T”。
根據(jù)一些實施例,當重寫特化的泛型類的特定方法時,該方法的替代版本可以被包括在類文件中并且可以被指示為應用到特化的特定集合(例如,對于某些類型形參)。在一些實施例中,當泛型類的方法在運行時被特化時,如果使用與方法的替代版本對應的其中一個特定的特化,則可以使用該方法的替代版本(例如,拷貝到特化類)而不是自動特化版本。
在一些實施例中,精煉方法可被用于多個類型參數(shù)化。例如,精煉方法可以特定于short和char,如以下例子中所示:
<where T extends Serializable>void writeObject(){...}
//僅對于short和char
<where T has 16bits>void swapBytes(){...}
圖10是示出如本文所述的、用于特化類的手動精煉的方法的一個實施例的流程圖。如方框1000中所示,泛型類可以對特定的類型參數(shù)化被特化。例如,在運行時,可以加載包括對于經多個類型參數(shù)化可特化的泛型類的類聲明的類文件。類聲明可以包括特定于多個類型參數(shù)化中特定的一個的精煉方法,并且,當類對該特定的類型參數(shù)化被特化時,可以為泛型類的方法提供替代實現(xiàn)。
例如,特化器可被配置為加載Box類并對T=int特化Box類。如方框1010中所示,特化器可以確定對泛型類匹配已有方法并且與特定的類型參數(shù)化對應的精煉方法。例如,特化器可以確定精煉toString方法對于重寫泛型toString方法并與類型參數(shù)化T=int對應的Box類存在。
如方框1020中所示,根據(jù)一個實施例,響應于確定精煉方法與特定的類型參數(shù)化對應,特化器可以在泛型類的特化版本中包括精煉方法,而不是包括已有方法的自動特化版本。換句話說,當對特定的類型參數(shù)化特化泛型類時,特化器可被配置為在基于特定的類型參數(shù)化的特化類中包括精煉方法。例如,特化器可以在Box類的特化版本中包括精煉toString方法,而不是包括toString方法的泛型或自動特化版本。因此,當該類對特定的類型參數(shù)化被特化時,精煉方法可以為泛型類的方法提供替代實現(xiàn)。
此外,如方框1030中所示,泛型類可以對不同的類型參數(shù)化被特化,并且,如方框1040中所示,特化器可以確定精煉方法不與該不同的類型參數(shù)化對應。例如,來自以上例子的Box類可以對除T=int之外的類型參數(shù)化被特化,并且因此特化器可以確定精煉toString方法不與該類型參數(shù)化對應。作為響應,特化器可以不在對于其它類型參數(shù)化的特化中包括該精煉方法,如方框1050中所示。例如,當對除T=int之外的另一類型參數(shù)化特化Box類時,特化器可以不在該類的特化版本中包括精煉toString方法(例如,與T=int對應的toString方法),而是可以包括toString方法的自動特化版本。作為替代,根據(jù)一個實施例,對于其它類型參數(shù)化可以存在另一精煉stostring方法(例如,在類聲明中),并且因此,當該類對其它類型參數(shù)化被特化時,可以包括在特化類中。
當開發(fā)人員具有關于類型的特定知識時,可以存在比自動版本更好的(例如,更小、更快、更高效的)實現(xiàn)。例如,如果程序使用參數(shù)化的類型ArrayList<boolean>,則ArrayList<T>類的自動特化版本可以利用大于存儲布爾值所需的最小值的缺省元素規(guī)模。例如,在Java編程語言中,缺省地,布爾可以利用8位(或更大)位置存儲。因此,在一些實施例中,當ArrayList<T>對T=Boolean被特化時,開發(fā)人員能夠提供其自己的使用不同存儲機制的實現(xiàn)(例如,使用long的內部數(shù)組并執(zhí)行逐位計算)。
因此,可以存在泛型ArrayList<T>,但是,如果其對T=Boolean被實例化,則可以使用不同的手寫類來代替自動特化版本。在一些實施例中,自動特化版本和手寫版本可以被要求具有相同的簽名,但是可以具有完全不同的表示和/或完全不同的成員,等等。
此外,泛型類的自動特化版本可以僅被用不同特化的不同方法來部分地重寫。因此,不是替換整個類和/或實現(xiàn),而是僅存在于特定實例化中的個體方法可以被替換(例如,以使用更好的實現(xiàn))或者個體方法可以被添加(如上面所指出的)。因此,根據(jù)一些實施例,開發(fā)人員可以提供手寫的精煉,其提供類、個體替換(例如,重寫)方法和/或另外的方法的全新表示。
例如,雖然List<int>可以具有add和get的自動特化實現(xiàn),但是對于某些類型參數(shù)化(例如,T=int)包括sum方法會是有益的,該sum方法可以不是List的所有特化版本的成員(例如,對于T的所有類型參數(shù)化)。
例如:
手動精煉,以提供新的方法
在一些實施例中,編譯器和/或運行時可以允許的方法對于類的某些(例如,一個,一些或全部)特化版本被手動添加到類,諸如向特化類添加不在自動特化版本中存在的新功能。
圖11是示出根據(jù)一個實施例的、用于將新方法添加到特化類的手動精煉的框圖。如圖11中所示,類文件可以包括類A 1100,其既包括(一個或多個)已有方法1110又包括僅與特定的類型參數(shù)化對應的新方法1120。當類A 1100對新方法1120對應的類型參數(shù)化被特化時,精煉特化器1130可以包括新方法,以及類的特化版本中(一個或多個)已有方法的特化版本,如由類A 1140中的新方法1150和(一個或多個)已有方法1160所示。
但是,當類對新方法不對應的類型參數(shù)化被特化時,特化器可以不在特化類中包括該新方法,而是代替地可以僅包括(一個或多個)已有方法的特化版本,如由包括(一個或多個)已有方法1180但不包括新方法的特化版本的類A 1170所示。
因此,不是簡單地基于類型變量的實例化替換方法的主體,而是可以添加新方法。根據(jù)一些實施例,新方法可以被稱為“有條件”方法,因為它可以只被包括在某些類型特化中。
作為另一個例子:
在上面的例子中,兩個有條件sum()方法被添加到List。其中一個Sum()方法是實例化List<int>的成員,而另一個是實例化List<long>的成員,同時任何一個都不是List<?>或泛型List<T>的成員。
圖12是示出如本文所述、用于經由特化類的手動精煉來添加新方法的方法的一個實施例的流程圖。如方框1200中所示,泛型類可以對特定的類型參數(shù)化被特化。例如,特化器可被配置為加載類并對特定的類型參數(shù)化將類特化。利用上面的例子,特化器可被配置為加載List類并對T=int特化List類。如方框1210中所示,特化器可以確定用于泛型類的、與特定的類型參數(shù)化對應的新方法。例如,特化器可以確定,對于Box類,存在與類型參數(shù)化T=int對應的新sum()方法。
如方框1220中所示,根據(jù)一個實施例,響應于確定新方法與特定的類型參數(shù)化對應,特化器可以在泛型類的特化版本中包括該新方法,以及包括任何已有方法的自動特化版本。例如,特化器可以在List類的特化版本中包括sum()方法,以及包括add()和get()方法的泛型或自動特化版本。
此外,如方框1230中所示,泛型類可以對另一類型參數(shù)化被特化,并且,如方框1240中所示,特化器可以確定新方法不與該另一類型參數(shù)化對應。例如,來自上面的例子的List類可以對除T=int之外的類型參數(shù)化被特化,并且因此特化器可以確定新的sum()方法不與該類型參數(shù)化對應。作為響應,特化器可以不在用于該另一類型參數(shù)化的特化中包括該新方法,如方框1250中所示。例如,當對除T=int之外的類型參數(shù)化特化List類時,特化器可以不在該類的特化版本中包括sum()方法(例如,與T=int對應的方法),但可以僅包括add()和get()方法的自動特化版本。
在一些實施例中,精煉方法可被用于多于一個類型參數(shù)化。例如,泛型類可以包括用于T=Object的精煉方法。在一些實施例中,如果泛型類對T=String(即,String是對象)被特化,則用于T=Object的精煉方法可被包括在泛型類的特化版本中。但是,在其它實施例中,如果相同的泛型類對T=String被特化,則精煉方法(例如,對于T=Object)不能包括在特化版本中。因此,在一些實施例中,只有當泛型類對為其指定特定精煉方法的確切類型參數(shù)化被特化時,才可以使用該特定精煉方法,而在其它實施例中,精煉方法可以用于多個類型參數(shù)化。
特化類的批量替換
此外,在一些實施例中,可以既不使用泛型類的自動特化也不使用該類的手動精煉,而是代替地可以使用全新的、手寫的類。一般而言,替換類可以具有與泛型或自動特化版本相同的接口,但是它可以具有完全不同的表示和/或實現(xiàn)。因此,根據(jù)一些實施例,替換類可以被要求具有(至少)類的泛型或自動特化版本將具有的所有相同的方法(例如,使得類的替代版本遵守Liskov代換原理)。在運行時,每當特定特化被實例化時,運行時環(huán)境可以加載類的替代版本。
圖13是示出根據(jù)一個實施例的、用于泛型類的批量替換的手動精煉的邏輯框圖。如圖13中所示,類文件200可以包括泛型類1300以及替換類1310。替換類1310可以與特定的類型參數(shù)化對應并且可以預期在泛型類1300對這些特定的類型參數(shù)化被特化時替換泛型類1300。例如,當泛型類1300對替換類1310對應的類型參數(shù)化A1350被特化時,精煉特化器1320可以加載特化的替換類1330而不是泛型類1300的自動特化版本。作為替代,當泛型類1300對替換類1310不對應的不同類型參數(shù)化(諸如類型參數(shù)化B 1360)被特化時,特化器可以加載并特化泛型類1300,如由自動特化類1340所表示的。
在一個實施例中,類的泛型或自動特化版本可以包括識別類的替代版本并指示哪些類型參數(shù)化可以觸發(fā)替代版本的使用的信息。但是,在其它實施例中,識別類的替代版本并指示哪些類型參數(shù)化可以觸發(fā)替代版本的使用的信息可以存儲在除類的泛型或自動特化版本以外的其它地方(例如,在類文件中或信息注冊表中),并且因此運行時可以不必在使用類的替代版本時加載類的泛型或自動特化版本。
例如,可以提供用于泛型類的給定實例化的替換定制表示,如在以下例子中:
類似地,我們可能具有其鍵和值為int的散列表的特化表示:
根據(jù)一些實施例,當實現(xiàn)類的批量替換時,運行時類加載器和/或特化器可被配置為確定替換類應當被使用(例如,基于被實例化的特定類型形參)并定位和加載替換類來代替泛型類的自動特化和/或手動精煉版本。
圖14是示出如本文所述的、用于經由手動精煉來批量替換類的方法的一個實施例的流程圖。如方框1400中所示,泛型類可以對特定的類型參數(shù)化被特化。例如,利用上面的示例,特化器可被配置為加載ArrayList類并對T=Boolean特化ArrayList類。根據(jù)一些實施例,ArrayList類可以是基于泛型類聲明并且可以經多個類型參數(shù)化可特化的泛型類。如方框1410中所示,特化器可以確定與特定的類型參數(shù)化對應的泛型類的替換(例如,精煉)類。例如,特化器可以確定ArrayList類的精煉版本存在并且與類型參數(shù)化T=boolean對應。在一個實施例中,用于ArrayList的類文件可以包括用于ArrayList的精煉類聲明,其為泛型ArrayList提供(例如包括)當泛型類對特定的類型參數(shù)化(例如,T=boolean)被特化時使用的替代實現(xiàn)。
如方框1420中所示,根據(jù)一個實施例,響應于確定替換類與特定的類型參數(shù)化對應,特化器可以加載替換類而不是加載泛型類的自動特化版本。例如,特化器可以加載ArrayList的ArrayList<boolean>版本,而不是ArrayList的自動特化版本。
因此,在一個實施例中,將泛型類特化可以包括加載與泛型類的精煉類聲明對應(例如,基于泛型類的精煉類聲明)的類,該精煉類聲明特定于特定的類型參數(shù)化并且當泛型類對特定的類型參數(shù)化被特化時為泛型類提供替代實現(xiàn)。此外,泛型類可以對其它類型參數(shù)化可特化,而無需加載與精煉類聲明對應的類。
例如,如方框1430中所示,泛型類可以對另一類型參數(shù)化被特化,并且,如方框1440中所示,特化器可以確定替換類不與該另一類型參數(shù)化對應。例如,來自上面例子的ArrayList類可以對除T=boolean以外的類型參數(shù)化被特化,并且因此特化器可以確定替換類(例如,ArrayList<boolean>)不與該另一類型參數(shù)化對應。作為響應,根據(jù)一個實施例,特化器可以不加載ArrayList的ArrayList<boolean>版本,而是可以加載ArrayList的自動特化版本,如方框1450中所示。
如上面關于方法的手動精煉所描述的,在一些實施例中,精煉類聲明可被用于多于一個類型參數(shù)化。例如,泛型類可以具有用于T=Object的精煉泛型類聲明。在一些實施例中,如果泛型類對T=String(即,String是對象)被特化,則用于T=Object的精煉類聲明可被用于泛型類的特化版本。但是,在其它實施例中,如果相同的泛型類對T=String被特化,則精煉類聲明(例如,對于T=Object)可以不被用于該類的特化版本。因此,在一些實施例中,只有當泛型類對為其指定特定精煉類聲明的確切類型參數(shù)化被特化時,特定精煉類聲明才可被使用,而在其它實施例中,精煉方法可用于多個類型參數(shù)化。
在一些實施例中,特化的泛型類的手動精煉也可以與泛型類的部分特化和依賴性驅動的共同特化相結合,如上所述。例如,部分特化類可被手動精煉,以包括用于一個或多個特化的一些附加功能,并且部分特化還可以觸發(fā)一個或多個其它泛型類的(完全或部分)特化。
泛型方法的手動精煉
除了基于類類型形參的特定實例化來使用手動精煉,如上所述,手動精煉也可以基于泛型方法的方法類型形參來提供。在一些實施例中,當類中的泛型方法(例如,類自身不必是泛型)對特定類型被特化時,該方法的替代版本可被使用。
例如,假設我們有:
class IntList extends List<int>{...}
并且我們有泛型方法:
我們可以特化T=int實例化:
在這里,我們說這是已有泛型方法對類型形參的特定組合的特化。當開發(fā)人員寫該方法的不同版本時,不同的版本可以由編譯器傳播到類文件中,并且,在運行時,該方法的特定版本基于被特化的特定類型形參被加載。
圖15是示出根據(jù)一個實施例的、用于泛型方法的手動精煉的邏輯框圖。如圖15中所示,類文件200可以包括泛型方法1500以及替換方法1510。替換方法1510可以與特定的類型參數(shù)化對應并且可以預期在泛型方法1500對這些特定的類型參數(shù)化被特化時替換泛型方法1500。例如,當泛型方法1500對替換方法1510對應的類型參數(shù)化A 1550被特化時,精煉特化器1520可以加載特化的替換方法1530而不是泛型方法1500的自動特化版本。作為替代,當泛型方法1500對替換方法1310不對應的不同類型參數(shù)化(諸如類型參數(shù)化B1560)被特化時,特化器可以加載并特化泛型方法1500,如由自動特化方法1540所表示的。
圖16是示出如本文所述的、用于泛型方法的手動精煉的方法的一個實施例的流程圖。如方框1600中所示,泛型方法可以對特定的類型參數(shù)化被特化。例如,特化器可被配置為加載并對特定的類型參數(shù)化將方法特化。利用上面的例子,特化器可被配置為加載singletonList方法并對T=int特化singletonList方法。如方框1610中所示,特化器可以為泛型方法確定與特定的類型參數(shù)化對應的替換方法。例如,特化器可以確定singletonList方法的替換版本存在并且與類型參數(shù)化T=int對應。
如方框1620中所示,根據(jù)一個實施例,響應于確定替換方法與特定的類型參數(shù)化對應,特化器可以加載替換方法,而不是加載泛型方法的自動特化版本。例如,特化器可以加載singletonList方法的specialization<T=int>版本,而不是singletonList的自動特化版本。
此外,如方框1630中所示,泛型方法可以對另一類型參數(shù)化被特化,并且,如方框1640中所示,特化器可以確定替換方法不與該另一類型參數(shù)化對應。例如,來自上面的例子的singletonList方法可以對除T=int之外的類型參數(shù)化被特化,并且因此特化器可以確定替換方法(例如,specialization<T=int>版本)不與該另一類型參數(shù)化對應。作為響應,根據(jù)一個實施例,特化器可以不加載singletonList方法的specialization<T=int>版本,而是可以加載singletonList方法的自動特化版本,如方框1650中所示。
在至少一些實施例中,實現(xiàn)本文描述的一種或多種技術的一部分或全部的計算機系統(tǒng)可以包括通用計算機系統(tǒng),該通用計算機系統(tǒng)包括或被配置為訪問一個或多個計算機可讀介質。圖17示出了適于實現(xiàn)本文所述的方法、特征和增強的此類通用計算設備3000。在所示實施例中,計算設備3000包括經由輸入/輸出(I/O)接口3030耦合到系統(tǒng)存儲器3020的一個或多個處理器3010。計算設備3000還包括耦合到I/O接口3030的網絡接口3040。
在各種實施例中,計算設備3000可以是包括一個處理器3010的單處理器系統(tǒng)或包括若干處理器3010(例如,兩個、四個、八個或另一合適數(shù)目)的多處理器系統(tǒng)。處理器3010可以包括能夠執(zhí)行指令的任何合適的處理器。例如,在各種實施例中,處理器3010可以是實現(xiàn)各種指令集體系架構(ISA),諸如x86、PowerPC、SPARC或MIPS ISA或任何其它合適的ISA,當中任何一個的通用或嵌入式處理器。在多處理器系統(tǒng)中,每個處理器3010通??梢裕槐?,實現(xiàn)相同的ISA。
系統(tǒng)存儲器3020可被配置為存儲可由(一個或多個)處理器3010訪問的程序指令和數(shù)據(jù)。在各種實施例中,系統(tǒng)存儲器3020可以利用任何合適的存儲器技術來實現(xiàn),諸如靜態(tài)隨機存取存儲器(SRAM)、同步動態(tài)RAM(SDRAM)、非易失性/閃存型存儲器或任何其它類型的存儲器。在所示實施例中,實現(xiàn)一個或多個期望功能的程序指令和數(shù)據(jù),諸如上述那些方法、技術和數(shù)據(jù),被示為作為代碼(即,程序指令)3025和數(shù)據(jù)3026存儲在系統(tǒng)存儲器3020中。例如,在一個實施例中,存儲器3020以及代碼3025和數(shù)據(jù)3026可以存儲用于實現(xiàn)上述編譯器120和/或虛擬化運行時環(huán)境140的程序指令和數(shù)據(jù)。
在各種實施例中,編譯器120和/或虛擬化的運行時環(huán)境140(和/或其任何個別的子模塊)可以各自以各種編程語言或方法中任何一種來實現(xiàn)。例如,在一個實施例中,編譯器120和/或虛擬化的運行時環(huán)境140可以用C、C++、匯編,JAVA或其它通用編程語言中任何一種來編寫,而在另一實施例中,它們當中一個或多個可以用不同的、更專門的編程語言來編寫。而且,在一些實施例中,編譯器120和/或虛擬化的運行時環(huán)境140(和/或其各個子模塊)不能用相同的編程語言來實現(xiàn)。
在一個實施例中,I/O接口3030可被配置為協(xié)調設備中處理器3010、系統(tǒng)存儲器3020和任何外圍設備,包括網絡接口3040或其它外圍接口,之間的I/O流量。在一些實施例中,I/O接口3030可以執(zhí)行任何必要的協(xié)議、定時或其它數(shù)據(jù)變換,以便將來自一個部件(例如,系統(tǒng)存儲器3020)的數(shù)據(jù)信號轉換成適于被另一部件(例如,處理器3010)使用的格式。在一些實施例中,I/O接口3030可以包括對通過各種類型的外圍總線,諸如像外圍組件互連(PCI)總線標準或通用串行總線(USB)標準的變型,附連的設備的支持。而且,在一些實施例中,I/O接口3030,諸如到系統(tǒng)存儲器3020的接口,的一些或全部功能可以直接被結合到處理器3010中。
網絡接口3040可被配置為允許在計算設備3000和附連到一個或多個網絡3050的其它設備3060之間交換數(shù)據(jù)。在各種實施例中,網絡接口3040可以支持經由任何合適的有線或無線通用數(shù)據(jù)網絡的通信,諸如像以太網類型。
在一些實施例中,系統(tǒng)存儲器3020可以是被配置為如上文關于圖1-6所述存儲用于實現(xiàn)對應方法和裝置的實施例的程序指令和數(shù)據(jù)的計算機可讀(例如,計算機可訪問)介質的一個實施例。但是,在其它實施例中,程序指令和/或數(shù)據(jù)可以在不同類型的計算機可讀介質上被接收、發(fā)送或存儲。一般而言,計算機可讀介質可以包括非暫態(tài)存儲介質或存儲器介質,諸如磁性或光學介質,例如,經由I/O接口3030耦合到計算設備3000的盤或DVD/CD。非暫態(tài)計算機可讀存儲介質還可以包括可作為系統(tǒng)存儲器3020或另一類型存儲器包括在計算設備3000的一些實施例中的任何易失性或非易失性介質,諸如RAM(例如,SDRAM、DDR SDRAM、RDRAM、SRAM等)、ROM等。
另外,計算機可讀介質可以包括傳輸介質或信號,諸如經由諸如網絡和/或無線鏈路的通信介質傳送的電、電磁或數(shù)字信號,其中通信介質諸如可以經由網絡接口3040實現(xiàn)。諸如圖17中所示的多個計算設備的部分或全部可被用來實現(xiàn)在各種實施例中所描述的功能;例如,在各種不同的設備和服務器上運行的軟件部件可以協(xié)作,以提供功能。在一些實施例中,除了或代替利用通用計算機系統(tǒng)實現(xiàn),所描述的功能的一部分還可以利用存儲設備、網絡設備或專用計算機系統(tǒng)來實現(xiàn)。如本文所使用的,術語“計算設備”是指至少所有這些類型的設備,并且不限于這些類型的設備。
各種實施例還可以包括在計算機可讀介質上接收、發(fā)送或存儲根據(jù)前面的描述實現(xiàn)的指令和/或數(shù)據(jù)。一般而言,計算機可讀介質可以包括存儲介質或存儲器介質,諸如磁性或光學介質,例如盤或DVD/CD-ROM,易失性或非易失性介質,諸如RAM(例如,SDRAM、DDR、RDRAM、SRAM等等)、ROM等。在一些實施例中,計算機可讀介質還可以包括經由諸如網絡和/或無線鏈路的通信介質傳送的傳輸介質或信號,例如電、電磁或數(shù)字信號。
如圖中所示和在本文描述的各種方法表示方法的示例性實施例。方法可以在軟件、硬件或其組合中實現(xiàn)。在各種方法中,步驟的次序可以改變,并且各種元素可被添加、重新排序、組合、省略、修改等。各種步驟可以自動地(例如,沒有被用戶輸入直接提示)和/或以編程方式(例如,根據(jù)程序指令)執(zhí)行。
雖然本文已經參照具體實施例并在其上下文中描述了各種系統(tǒng)和方法,但是應當理解,這些實施例是說明性的并且本公開內容的范圍不限于這些具體實施例。許多變化、修改、添加和改進是可能的。例如,在描述中識別出的方框和邏輯單元是用于理解所描述的實施例,而不意味著限制本公開內容。例如,在一些實施例中,被描述為由編譯器120執(zhí)行的動作、過程、方法、任務或功能可以由虛擬化的運行時環(huán)境140執(zhí)行,反之亦然。此外,功能可以在本文所述的或利用不同術語描述的系統(tǒng)和方法的各種實現(xiàn)中以不同方式在方框中分離或組合。
這些實施例意在是說明性的而非限制性的。因而,可以為在本文中被描述為單個實例的部件提供多個實例。各種部件、操作和數(shù)據(jù)存儲之間的邊界在某種程度上是任意的,并且特定操作是在具體說明性配置的上下文中示出的。功能的其它分配是可以想到的并可以落入隨后的例子的范圍內。最后,在示例性配置中作為離散部件給出的結構和功能可被實現(xiàn)為組合結構或部件。
雖然上面已經詳細描述了實施例,但是,一旦完全明白了以上公開內容,眾多的變化和修改將變得顯而易見。意在將以下權利要求解釋為涵蓋所有此類變化和修改。