考虑以下代码:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* @author Colby
*/
public class Entity {
//test code
public static void main(String[] args) {
Entity e = new Entity();
e.put("username", "colby");
e.put("level", 99);
e.put("hours played", Long.MAX_VALUE - 1);
e.put("banned", true);
String username = e.get("username");
int level = e.get("level");
long played = e.get("hours played");
boolean banned = e.get("banned");
System.out.println(username);
System.out.println(level);
System.out.println(played);
System.out.println(banned);
}
public Entity() {
map = new ConcurrentHashMap<>();
}
private final Map<String, Object> map;
public <T> void put(String key, T value) {
map.put(key, value);
}
public <T> T get(String key) {
return (T) map.get(key);
}
public boolean has(String key) {
return get(key) != null;
}
}
一个非常有用的属性系统。现在,当我做这样的事情时,我的问题来了:
int i = e.get("non existent key");
map get将返回null,因此将在开箱时抛出一个NPE。
我尝试的解决方案是:
public <T> T get(String key) {
Object o = map.get(key);
if(o == null) {
if(T instanceof Integer) {
return (T) new Integer(-1);
}
}
return (T) o;
}
然而,我得到一个错误,无法在instanceof线上找到符号T。如何改进此代码?
您可以将默认值作为参数传递给方法。
public <T> T get(String key, T defaultValue) {
Object o = map.get(key);
if(o == null) {
return defaultValue;
} else {
return (T) o;
}
}
您可以使用包含类型信息和标签的密钥来完成此操作:
abstract class Key<T> {
private final String label;
private final T defaultValue;
Key(String label, T defaultValue) {
// Assign to fields.
}
T defaultValue() { return defaultValue; }
@Override public boolean equals(Object obj) {
// Implement to check both label and getClass().
}
@Override public int hashCode() {
// Implement to check both label and getClass().
}
}
然后使用这个而不是普通的String
:
public <T> void put(Key<T> key, T value) {
map.put(key, value);
}
public <T> T get(Key<T> key) {
if (!map.containsKey(key)) {
return key.defaultValue();
} else {
return (T) map.get(key);
}
}
然后实例化Key
实例,如:
Key<String> fooKey = new Key<String>("Foo", "someDefaultValue") {};
Key<Integer> barKey = new Key<Integer>("Bar", -1) {};
Key<List<String>> listKey = new Key<List<String>>("List", new ArrayList<String>()) {};
这允许您将客户端对与密钥相关联的类型的知识进行编码。get
中的强制转换是安全的,因为您知道只有正确类型的条目才被放入映射中。