日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

How to Map Distinct Value Types Using Java Generics--reference

發(fā)布時間:2025/4/5 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 How to Map Distinct Value Types Using Java Generics--reference 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文:http://www.codeaffine.com/2015/03/04/map-distinct-value-types-using-java-generics/

Occasionally the average developer runs into a situation where he has to map values of arbitrary types within a particular container. However the Java collection API provides container related parameterization only. Which limits the type safe usage of?HashMap?for example to a?single?value type. But what if you want to mix apples and pears?

Luckily there is an easy design pattern that allows to map distinct value types using Java generics, which?Joshua Bloch?has described as?typesafe hetereogeneous container?in his book?Effective Java(second edition, Item 29).

Stumbling across some not altogether congenial solutions regarding this topic recently, gave me the idea to explain the problem domain and elaborate on some implementation aspects in this post.

Map Distinct Value Types Using Java Generics

Consider for the sake of example that you have to provide some kind of application context that allows to bind values of arbitrary types to certain keys. A simple non type safe implementation usingString?keys backed by a?HashMap?might look like this:

public class Context {private final Map<String,Object> values = new HashMap<>();public void put( String key, Object value ) {values.put( key, value );}public Object get( String key ) {return values.get( key );}[...] }

The following snippet shows how this?Context?can be used in a program:

Context context = new Context(); Runnable runnable = ... context.put( "key", runnable );// several computation cycles later... Runnable value = ( Runnable )context.get( "key" );

The drawback of this approach can be seen at line six where a down cast is needed. Obviously this can lead to a?ClassCastException?in case the key-value pair has been replaced by a different value type:

Context context = new Context(); Runnable runnable = ... context.put( "key", runnable );// several computation cycles later... Executor executor = ... context.put( "key", executor );// even more computation cycles later... Runnable value = ( Runnable )context.get( "key" ); // runtime problem

The cause of such problems can be difficult to trace as the related implementation steps might be spread wide apart in your application. To improve the situation it seems reasonable to bind the value not only to its key but also to its type.

Common mistakes I saw in several solutions following this approach boil down more or less to the following?Context?variant:

public class Context {private final <String, Object> values = new HashMap<>();public <T> void put( String key, T value, Class<T> valueType ) {values.put( key, value );}public <T> T get( String key, Class<T> valueType ) {return ( T )values.get( key );}[...] }

Again basic usage might look like this:

Context context = new Context(); Runnable runnable = ... context.put( "key", runnable, Runnable.class );// several computation cycles later... Runnable value = context.get( "key", Runnable.class );

One first glance this code might give the illusion of being more type save as it avoids the down cast in line six. But running the following snippet gets us down to earth as we still run into theClassCastException?scenario during the assignment in line ten:

Context context = new Context(); Runnable runnable = ... context.put( "key", runnable, Runnable.class );// several computation cycles later... Executor executor = ... context.put( "key", executor, Executor.class );// even more computation cycles later... Runnable value = context.get( "key", Runnable.class ); // runtime problem

So what went wrong?

First of all the down cast in?Context#get?of type?T?is ineffective as?type erasure?replaces unbounded parameters with a static cast to?Object. But more important the implementation does not use the type information provided by?Context#put?as key. At most it serves as superfluous cosmetic effect.

Typesafe Hetereogeneous Container

Although the last?Context?variant did not work out very well it points into the right direction. The question is how to properly parameterize the key? To answer this take a look at a stripped-down implementation according to the typesafe hetereogenous container pattern described by Bloch.

The idea is to use the?class?type as key itself. Since?Class?is a parameterized type it enables us to make the methods of?Context?type safe without resorting to an unchecked cast to?T. A?Class?object used in this fashion is called a type token.

public class Context {private final Map<Class<?>, Object> values = new HashMap<>();public <T> void put( Class<T> key, T value ) {values.put( key, value );}public <T> T get( Class<T> key ) {return key.cast( values.get( key ) );}[...] }

Note how the down cast within the?Context#get?implementation has been replaced with an effective dynamic variant. And this is how the context can be used by clients:

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 );

This time the client code will work without class cast problems, as it is impossible to exchange a certain key-value pair by one with a different value type.

Where there is light, there must be shadow, where there is shadow there must be light. There is no shadow without light and no light without shadow….Haruki Murakami

Bloch mentions two limitations to this pattern. ‘First, a malicious client could easily corrupt the type safety [...] by using a class object in its raw form.’ To ensure the type invariant at runtime a dynamic cast can be used within?Context#put.

public <T> void put( Class<T> key, T value ) {values.put( key, key.cast( value ) ); }

The second limitation is that the pattern cannot be used on?non-reifiable?types (see Item 25, Effective Java). Which means you can store value types like?Runnable?or?Runnable[]?but not?List<Runnable>?in a type safe manner.

This is because there is no particular class object for?List<Runnable>. All parameterized types refer to the same?List.class?object. Hence Bloch points out that there is no satisfactory workaround for this kind of limitation.

But what if you need to store two entries of the same value type? While creating new type extensions just for storage purpose into the type safe container might be imaginable, it does not sound as the best design decision. Using a custom key implementation might be a better approach.

Multiple Container Entries of the Same Type

To be able to store multiple container entries of the same type we could change the?Context?class to use a custom key. Such a key has to provide the type information we need for the type safe behaviour and an identifier for distinction of the actual value objects.

A naive key implementation using a?String?instance as identifier might look like this:

public class Key<T> {final String identifier;final Class<T> type;public Key( String identifier, Class<T> type ) {this.identifier = identifier;this.type = type;} }

Again we use the parameterized?Class?as hook to the type information. And the adjusted?Context?now uses the parameterized?Key?instead of?Class:

public class Context {private final Map<Key<?>, Object> values = new HashMap<>();public <T> void put( Key<T> key, T value ) {values.put( key, value );}public <T> T get( Key<T> key ) {return key.type.cast( values.get( key ) );}[...] }

A client would use this version of?Context?like this:

Context context = new Context();Runnable runnable1 = ... Key<Runnable> key1 = new Key<>( "id1", Runnable.class ); context.put( key1, runnable1 );Runnable runnable2 = ... Key<Runnable> key2 = new Key<>( "id2", Runnable.class ); context.put( key2, runnable2 );// several computation cycles later... Runnable actual = context.get( key1 );assertThat( actual ).isSameAs( runnable1 );

Although this snippet works, the implementation is still flawed. The?Key?implementation is used as lookup parameter in?Context#get. Using two?distinct?instances of?Key?initialized with the?same?identifier and class – one instance used with put and the other used with get – would return?null?on?get. Which is not what we want.

Luckily this can be solved easily with an appropriate?equals?and?hashCode?implementation of?Key. That allows the?HashMap?lookup to work as expected. Finally one might provide a factory method for key creation to minimize boilerplate (useful in combination with static imports):

public static Key key( String identifier, Class type ) {return new Key( identifier, type ); }

Conclusion

‘The normal use of generics, exemplified by the collection APIs, restricts you to a fixed number of type parameters per container. You can get around this restriction by placing the type parameter on the key rather than the container. You can use?Class?objects as keys for such typesafe heterogeneous containers’ (Joshua Bloch, Item 29, Effective Java).

Given these closing remarks, there is nothing left to be added except for wishing you good luck mixing apples and pears successfully…

轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/4329860.html

總結(jié)

以上是生活随笔為你收集整理的How to Map Distinct Value Types Using Java Generics--reference的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 浓精喷进老师黑色丝袜在线观看 | 亚洲日本激情 | 国产乱淫av公 | 亚洲福利电影网 | 男男黄网站 | 国产传媒一区二区 | 爱爱免费网址 | 国产亚洲欧美一区二区三区 | 日韩一区二区在线播放 | 国产日产欧美 | 色欲av无码一区二区三区 | 亚洲一区二区av | 中文字幕一区二区免费 | 好屌妞视频这里有精品 | 香蕉成视频人app下载安装 | 色呦呦在线 | 天天看夜夜爽 | 欧美一级做 | 久久88| 日本aa在线观看 | 五月天伊人网 | 国产精品亚洲五月天丁香 | 懂色一区二区二区av免费观看 | 成人福利免费视频 | 欧美丰满熟妇bbbbbb | 欧美在线观看成人 | 波多野结衣视频观看 | 欧美性猛交一区二区三区精品 | 一区二区三区视频网站 | 日本黄色xxxxx| 国产精品第1页 | 国产成人在线观看免费网站 | 国产精品高潮呻吟久久av野狼 | 精品成人一区二区 | 色77777| 都市激情校园春色 | 亚洲一级大片 | 51精产品一区一区三区 | 国产精品资源网站 | 国产三级直播 | av电影一区二区三区 | 精品视频免费播放 | 久久久久久国产精品三级玉女聊斋 | 人与禽性7777777 | 涩涩精品 | 免费午夜人成电影 | 久久综合久久鬼色 | 精品一区电影国产 | 向日葵视频在线 | 日韩欧美国产成人精品免费 | 欧洲一二三区 | 国产欧美精品一区二区色综合 | www.日韩欧美 | 久艹在线观看 | 韩国伦理片观看 | 好妞色妞国产在线视频 | 日韩视频免费看 | 91爱爱网站| 欧美精品免费播放 | av女优天堂在线观看 | 四虎永久在线精品免费一区二区 | 成人h视频在线观看 | 亚洲精品久久一区二区三区777 | 久草五月| 原来神马电影免费高清完整版动漫 | 久久一区二区精品 | 日韩精品免费在线观看 | 精品人妻无码专区视频 | www.youjizz.com国产 | 亚洲成av人影院 | 日韩黄| 99免费| 黄色综合网站 | 国内自拍偷拍网 | 中文字幕免费高清在线观看 | 国产女主播在线一区二区 | 麻豆视频在线观看免费 | 女女调教被c哭捆绑喷水百合 | 国产另类ts人妖一区二区 | 精彩视频一区二区三区 | 国产又粗又黄又爽视频 | 99久久久国产精品无码性 | 在线观看黄色片 | 欧美乱妇视频 | 久久一区二区三区四区五区 | 婷婷另类小说 | 3d动漫啪啪精品一区二区中文字幕 | 黄色网址链接 | 五个女闺蜜把我玩到尿失禁 | av在线视屏| 免费看一级片 | 国产高清视频一区 | 一级片黄色 | 1024日韩| 国产a国产片国产 | 激情综合av | 一级性爱视频 | 亚洲日日日 | 久久亚洲成人 |