我有一个泛型类,旨在保留不同类型属性的值。我想提供一种类型安全的方法来设置属性值,这样就不可能为属性分配错误类型的值。
我为所有属性类型定义了一个接口:
public interface Property<T> {
}
其中类型参数T用于指定属性值的类型。然后假设类OrderProperty
实现此接口属性可以定义为
OrderProperty property1 = new OrderProperty<String>();
OrderProperty property2 = new OrderProperty<Integer>();
最初我实现了类来保存属性值,如
public class Properties<K extends Property> {
private Map<K, Object> properties = new HashMap<K, Object>();
public <V> void set(K key, V value) {
properties.put(key, value);
}
}
问题是set()方法显然不是类型安全的,因为它不考虑属性与其值类型之间的连接,所以我可以轻松地编写类似
的内容Properties orderProperties = new Properties<OrderProperty>();
OrderProperty countProperty = new OrderProperty<Integer>();
orderProperties.set(countProperty, "1");
它会编译。
类型安全的实现将是
public <V> void set(Property<V> key, V value) {
properties.put(key, value);
}
但当然它不会编译,因为key不是泛型类型。
我需要像
这样的东西public <V> void set(K<V> key, V value) {
properties.put(key, value);
}
但是这个在语法上是不正确的。
我想知道是否有办法完成我需要的工作。
答案 0 :(得分:2)
您的Properties
课程只能支持一种类型的财产。这可能不是你想要的,即使这样可行:
public class Properties<V, T extends Property<? extends V>> {
public void set(T key, V value) {
//...
}
}
如果要支持不同类型的属性,则必须手动检查属性的有效性。原因是Java由于type erasure:
public interface Property<T> {
public Class<T> getPropertyType();
}
public class OrderProperty<T> extends Property<T> {
Class<T> type;
/** This constructor is required due to type erasure, otherwise the OrderType doesn't know the property type */
public OrderProperty(Class<T> type) {
this.type = type;
}
public Class<T> getPropertyType() {
return type;
}
}
public class Properties<K extends Property> {
private Map<K, Object> properties = new HashMap<K, Object>();
public <V> void set(K key, V value) {
properties.put(key, key.getPropertyType().cast(value));
}
}
答案 1 :(得分:1)
我的猜测是使用
public class Properties<V> {
public void set(Property<V> key, V value) {
properties.put(key, value);
}
}
编辑: 好的,根据你的评论,也许这样的事情应该这样做:
public class Properties<V, T extends Property<V>> {
public void set(T key, V value) {
}
}
编辑2: 要实现该课程,您可以执行类似
的操作Properties<Integer, OrderedProperty<Integer>> properties =
new Properties<Integer, OrderedProperty<Integer>>
答案 2 :(得分:0)
<强> EDITED 强>
好的,对不起,我没有完全理解你的要求。在你的情况下,我以前的答案可能是无用的。既然您希望能够在Properties
类中存储不同的属性,并且put(..)
方法仍然是类型安全的,那么您可以使用以下内容:
public static class Properties {
private Map<Property<?>, Object> properties = new HashMap<Property<?>, Object>();
public <V> void put(Property<V> key, V value) {
properties.put(key, value);
}
@SuppressWarnings("unchecked")
public <V> V get(Property<V> key) {
return (V) properties.get(key);
}
}
在这种情况下,您只能放置与该属性类型匹配的属性和值,如下所示:
OrderProperty<String> stringProperty = new OrderProperty<String>();
OrderProperty<Integer> countProperty = new OrderProperty<Integer>();
Properties orderProperties = new Properties();
orderProperties.put(countProperty, 3);
orderProperties.put(stringProperty, "");
orderProperties.put(stringProperty, 2);//This will not compile!