使ç¨Javaæ³åæ å°ä¸åçå¼ç±»å
èèä¸ä¸ªä¾åï¼ä½ éè¦æä¾æç§åºç¨ç¨åºçä¸ä¸æï¼å®å¯ä»¥å°ç¹å®çé®ç»å®å°ä»»æç±»åçå¼ãå©ç¨Stringä½ä¸ºé®çHashMapï¼ä¸ä¸ªç®åçãéç±»åå®å
¨ï¼type safeï¼çå®ç°å¯è½æ¯è¿æ ·çï¼
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 );
}
[...]
}
æ¥ä¸æ¥ç代ç ç段å±ç¤ºäºææ ·å¨ç¨åºä¸ä½¿ç¨Context ï¼
Context context = new Context();
Runnable runnable = ...
context.put( "key", runnable );
// several computation cycles later...
Runnable value = ( Runnable )context.get( "key" );
å¯ä»¥çåºï¼è¿ç§æ¹æ³ç缺ç¹æ¯å¨ç¬¬6è¡éè¦è¿è¡åä¸è½¬åï¼down castï¼ãå¦ææ¿æ¢é®å¼å¯¹ä¸å¼çç±»åï¼æ¾ç¶ä¼æåºä¸ä¸ªClassCastExceptionå¼å¸¸:
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
产çè¿ç§é®é¢çåå æ¯å¾é¾è¢«è·è¸ªå°çï¼å 为ç¸å
³çå®ç°æ¥éª¤å¯è½å·²ç»å¹¿æ³åå¸å¨ä½ çç¨åºå个é¨åä¸ã
为äºæ¹åè¿ç§æ
åµï¼è²ä¼¼å°valueåå®çkeyãå®çvalueé½è¿è¡ç»å®æ¯åççã
å¨æçå°çãæç
§è¿ç§æ¹æ³çå¤ç§è§£å³æ¹æ¡ä¸ï¼å¸¸è§çé误æå¤æå°å½ç»äºä¸é¢Contextçåç§ï¼
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 );
}
[...]
}
åæ ·çåºæ¬ç¨æ³å¯è½æ¯è¿æ ·çï¼
Context context = new Context();
Runnable runnable = ...
context.put( "key", runnable, Runnable.class );
// several computation cycles later...
Runnable value = context.get( "key", Runnable.class );
ä¹ä¸çï¼è¿æ®µä»£ç å¯è½ä¼ç»ä½ æ´ç±»åå®å
¨çéè§ï¼å 为å
¶å¨ç¬¬6è¡é¿å
äºåä¸è½¬åï¼down castï¼ãä½æ¯è¿è¡ä¸é¢ç代ç å°ä½¿æ们éè¿ç°å®ï¼å 为æ们ä»å°å¨ç¬¬10è¡èµå¼è¯å¥å¤è·å
¥ClassCastException çææ±ï¼
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
åªéåºé®é¢äºå¢ï¼
é¦å
ï¼Context#getä¸çåä¸è½¬åæ¯æ æçï¼å 为类åæ¦é¤ä¼ä½¿ç¨éæ转åçObjectæ¥ä»£æ¿æ çåæ°ï¼unbonded parametersï¼ãæ¤å¤æ´éè¦çæ¯ï¼è¿ä¸ªå®ç°æ ¹æ¬å°±æ²¡æç¨å°ç±Context#put æä¾çç±»åä¿¡æ¯ãè¿å
å
¶éæ¯å¤æ¤ä¸ä¸¾çç¾å®¹ç½¢äºã
ç±»åå®å
¨çå¼æ容å¨
è½ç¶ä¸é¢Context çåç§ä¸èµ·ä½ç¨ï¼ä½å´ææäºæ¹åãæ¥ä¸æ¥çé®é¢æ¯ï¼ææ ·åçå°åæ°åè¿ä¸ªkeyï¼ ä¸ºäºåçè¿ä¸ªé®é¢ï¼è®©æ们å
ççä¸ä¸ªæ ¹æ®Blochææè¿°çç±»åå®å
¨å¼æ容å¨æ¨¡å¼ï¼typesafe heterogenous container patternï¼çç®è£
å®ç°å§ã
æ们çæ³æ³æ¯ç¨keyèªèº«çclass ç±»åä½ä¸ºkeyãå 为Class æ¯åæ°åçç±»åï¼å®å¯ä»¥ç¡®ä¿æ们使Contextæ¹æ³æ¯ç±»åå®å
¨çï¼èæ éè¯è¯¸äºä¸ä¸ªæªç»æ£æ¥ç强å¶è½¬æ¢ä¸ºTãè¿ç§å½¢å¼çä¸ä¸ªClass 对象称ä¹ä¸ºç±»å令çï¼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 ) );
}
[...]
}
请注æå¨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 <T> void put( Class<T> key, T value ) {
values.put( key, key.cast( value ) );
}
第äºä¸ªå±éå¨äºå®ä¸è½ç¨å¨ä¸å¯å
·ä½åï¼non-reifiable ï¼çç±»åä¸ï¼è§ãEffective Javaã第25项ï¼ãæ¢å¥è¯è¯´ï¼ä½ å¯ä»¥ä¿åRunnable æRunnable[]ï¼ä½æ¯ä¸è½ä¿åList<Runnable>ã
è¿æ¯å 为List<Runnable>没æç¹å®class对象ï¼ææçåæ°åç±»åæçæ¯ç¸åçList.class 对象ãå æ¤ï¼Blochæåºå¯¹äºè¿ç§å±éæ§æ²¡æ满æç解å³æ¹æ¡ã
ä½æ¯ï¼åå¦ä½ éè¦åå¨ä¸¤ä¸ªå
·æç¸åå¼ç±»åçæ¡ç®è¯¥æä¹åå¢ï¼å¦æä»
为äºåå
¥ç±»åå®å
¨ç容å¨ï¼å¯ä»¥èèå建æ°çç±»åæ©å±ï¼ä½è¿æ¾ç¶ä¸æ¯æ好ç设计ã使ç¨å®å¶çKeyä¹è®¸æ¯æ´å¥½çæ¹æ¡ã
å¤æ¡åç±»å容å¨æ¡ç®
为äºè½å¤åå¨å¤æ¡åç±»å容å¨æ¡ç®ï¼æ们å¯ä»¥ç¨èªå®ä¹keyæ¹åContext ç±»ãè¿ç§keyå¿
é¡»æä¾æ们类åå®å
¨æéçç±»åä¿¡æ¯ï¼ä»¥ååºåä¸åçå¼å¯¹è±¡ï¼value objectsï¼çæ è¯ãä¸ä¸ªä»¥String å®ä¾ä¸ºæ è¯çãå¹¼ç¨çkeyå®ç°å¯è½æ¯è¿æ ·çï¼
public class Key<T> {
final String identifier;
final Class<T> type;
public Key( String identifier, Class<T> type ) {
this.identifier = identifier;
this.type = type;
}
}
æ们å次使ç¨åæ°åçClassä½ä¸ºç±»åä¿¡æ¯çé©åï¼è°æ´åçContextå°ä½¿ç¨åæ°åçKeyèä¸æ¯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 ) );
}
[...]
}
客æ·ç«¯å°è¿æ ·ä½¿ç¨è¿ä¸ªçæ¬çContextï¼
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 );
è½ç¶è¿ä¸ªä»£ç ç段å¯ç¨ï¼ä½ä»æ缺é·ãå¨Context#getä¸ï¼Key被ç¨ä½æ¥è¯¢åæ°ãç¨ç¸åçidentifieråclassåå§å两个ä¸åçKeyçå®ä¾ï¼ä¸ä¸ªç¨äºputï¼å¦ä¸ä¸ªç¨äºgetï¼æågetæä½å°è¿ånull ãè¿ä¸æ¯æ们æ³è¦çâ¦â¦
//è¯è
é代ç ç段
Context context = new Context();
Runnable runnable1 = ...
Key<Runnable> key1 = new Key<>( "same-id", Runnable.class );
Key<Runnable> key2 = new Key<>( "same-id", Runnable.class );
context.put( key1, runnable1 );//ä¸ä¸ªç¨äºput
context.get(key2); //å¦ä¸ä¸ªç¨äºget --> return null;
幸è¿çæ¯ï¼ä¸ºKey设计åéçequals åhashCode å¯ä»¥è½»æ¾è§£å³è¿ä¸ªé®é¢ï¼è¿è使HashMap æ¥æ¾æé¢æå·¥ä½ãæåï¼ä½ å¯ä»¥ä¸ºå建keyæä¾ä¸ä¸ªå·¥åæ¹æ³ä»¥ç®åå
¶å建è¿ç¨ï¼ä¸static importä¸èµ·ä½¿ç¨æ¶æç¨ï¼ï¼
public static Key key( String identifier, Class type ) {
return new Key( identifier, type );
}
温馨提示:答案为网友推荐,仅供参考