对于我前一段时间写过的PropretyHolder来说,这是一个完美的用例.你可以在
my blog阅读它的长度.我开发它时考虑到了不变性,随时可以根据你的需要进行调整.
一般来说,如果你想从Java中的类型安全中获利,你需要知道你的密钥.我的意思是 – 几乎不可能开发出来自外部源的密钥类型安全解决方案.
这是一个特殊的密钥,它知道它的值的类型(它不完整,完整版请完成download the source):
public class PropertyKey {
private final Class clazz;
private final String name;
public PropertyKey(Class valueType, String name) {
this.clazz = valueType;
this.name = name;
}
public boolean checkType(Object value) {
if (null == value) {
return true;
}
return this.clazz.isAssignableFrom(value.getClass());
}
... rest of the class
}
然后你开发一个利用它的数据结构:
public class PropertyHolder {
private final ImmutableMap, ?> storage;
/**
* Returns value for the key of the type extending-the-one-declared-in-the {@link PropertyKey}.
*
* @param key {@link PropertyKey} instance.
* @return Value of the type declared in the key.
*/
@SuppressWarnings("unchecked")
public T get(PropertyKey key) {
return (T) storage.get(key);
}
/**
* Adds key/value pair to the state and returns new
* {@link PropertyHolder} with this state.
*
* @param key {@link PropertyKey} instance.
* @param value Value of type specified in {@link PropertyKey}.
* @return New {@link PropertyHolder} with updated state.
*/
public PropertyHolder put(PropertyKey key, T value) {
Preconditions.checkNotNull(key, "PropertyKey cannot be null");
Preconditions.checkNotNull(value, "Value for key %s is null",
key);
Preconditions.checkArgument(key.checkType(value),
"Property \"%s\" was given "
+ "value of a wrong type \"%s\"", key, value);
// Creates ImmutableMap.Builder with new key/value pair.
return new PropertyHolder(filterOutKey(key)
.put(key, value).build());
}
/**
* Returns {@link Builder} with all the elements from the state except for the given ket.
*
* @param key The key to remove.
* @return {@link Builder} for further processing.
*/
private Builder, Serializable> filterOutKey(PropertyKey key) {
Builder, Serializable> builder = ImmutableMap
., Serializable> builder();
for (Entry, Serializable> entry : this.storage.entrySet()) {
if (!entry.getKey().equals(key)) {
builder.put(entry);
}
}
return builder;
}
... rest of the class
}
我在这里省略了很多不必要的细节,如果不清楚,请告诉我.