Java 型別安全的異構容器

2021-07-02 19:50:27 字數 2902 閱讀 3043

我們的想法是用key自身的class型別作為key。因為class是引數化的型別,它可以確保我們使context方法是型別安全的,而無需訴諸於乙個未經檢查的強制轉換為t。這種形式的乙個class物件稱之為型別令牌(type token)。

public class context 

public t get( classkey )

[...]

}

請注意在context#get的實現中是如何用乙個有效的動態變數替換向下轉型的。客戶端可以這樣使用這個context:

context context = new context();

runnable runnable ...

context.put( runnable.class, runnable );

// several computation cycles later...

executor executor = ...

context.put( executor.class, executor );

// even more computation cycles later...

runnable value = context.get( runnable.class );

這次客戶端的**將可以正常工作,不再有類轉換的問題,因為不可能通過乙個不同的值型別來交換某個鍵值對。

bloch指出這種模式有兩個侷限性。「首先,惡意的客戶端可以通過以原生態形式(raw form)使用class物件輕鬆地破壞型別安全。」為了確保在執行時型別安全可以在context#put中使用動態轉換(dynamic cast)。

public void put( classkey, t value )

第二個侷限在於它不能用在不可具體化(

non-reifiable )的型別中

換句話說,你可以儲存runnablerunnable,但是不能儲存list

這是因為list沒有特定class物件,所有的引數化型別指的是相同的list.class物件。因此,bloch指出對於這種侷限性沒有滿意的解決方案。

為了能夠儲存多條同型別容器條目,我們可以用自定義key改變context類。這種key必須提供我們型別安全所需的型別資訊,以及區分不同的值物件(value objects)的標識。乙個以string例項為標識的、幼稚的key實現可能是這樣的:

public class key

}

我們再次使用引數化的class作為型別資訊的鉤子,調整後的context將使用引數化的key而不是class

public class context 

public t get( keykey )

[...]

}

客戶端將這樣使用這個版本的context

context context = new context();

runnable runnable1 = ...

keykey1 = new key<>( "id1", runnable.class );

context.put( key1, runnable1 );

runnable runnable2 = ...

keykey2 = new key<>( "id2", runnable.class );

context.put( key2, runnable2 );

// several computation cycles later...

runnable actual = context.get( key1 );

assertthat( actual ).issameas( runnable1 );

雖然這個**片段可用,但仍有缺陷。在context#get中,key被用作查詢引數。用相同的identifier和class初始化兩個不同的key的例項,乙個用於put,另乙個用於get,最後get操作將返回null。這不是我們想要的……
context context = new context();

runnable runnable1 = ...

keykey1 = new key<>( "same-id", runnable.class );

keykey2 = new key<>( "same-id", runnable.class );

context.put( key1, runnable1 );//乙個用於put

context.get(key2); //另乙個用於get --> return null;

幸運的是,為key設計合適的equalshashcode可以輕鬆解決這個問題,進而使hashmap查詢按預期工作。最後,你可以為建立key提供乙個工廠方法以簡化其建立過程(與static import一起使用時有用):

public static  key key( string identifier, class type )

STL容器的執行緒安全?

執行緒安全的情況 執行緒不安全的情況 看到風險了吧?在工程中多執行緒操作stl的場景應該還是比較常見的,乙個典型的例子就是用其來做生產者 消費者模型的佇列或者其他共享佇列,這樣為了應對執行緒安全問題我們必須自己對容器操作進行封裝。這是我自己實現的的封裝類threadsafe container.h,...

docker容器的安全加固

社群中常用的做法是利用lxcfs來提供容器中的資源可見性。lxcfs是乙個開源的fuse 使用者態檔案系統 實現來支援lxc容器。lxcfs通過使用者態檔案系統,在容器中提供下列 procfs 的檔案 proc cpuinfo proc diskstats proc meminfo proc sta...

docker容器的安全加固

社群中常用的做法是利用lxcfs來提供容器中的資源可見性。lxcfs是乙個開源的fuse 使用者態檔案系統 實現來支援lxc容器。lxcfs通過使用者態檔案系統,在容器中提供下列 procfs 的檔案 proc cpuinfo proc diskstats proc meminfo proc sta...