2010-07-07 148 views
0

我有一个通用类,旨在保持不同类型属性的值。我想提供一个类型安全的方法来设置属性值,以便不可能为属性指定错误类型的值。通用方法中类类型参数的使用

我定义为所有属性种待实现的接口:

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

} 

属性值的问题是,所述一组()方法显然是不键入-safe因为它不把财产,其价值型之间的联系,所以我可以很容易地编写类似

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

但当然不会无法编译,因为关键是通用型的不行。

我需要这样的东西

public <V> void set(K<V> key, V value) { 
    properties.put(key, value); 
} 

但是这一个是语法不正确。

我想知道是否有任何方法来完成我所需要的。

+0

'私人地图 properties'这是为什么不'地图'?我以为你说'T'是值的类型。我很困惑。 – polygenelubricants 2010-07-07 11:48:15

+0

T用于在两个位置命名类型参数:在接口属性中,它引用值类型和类中的属性,其中T用于指示属性的类型(可能有许多类似OrderProperty,ItemProperty等等)。我想为它们实现通用容器。 – fnt 2010-07-07 12:45:58

+0

我编辑帖子以避免混淆 – fnt 2010-07-07 12:48:45

回答

1

我的猜测是使用一些如

public class Properties<V> { 
    public void set(Property<V> key, V value) { 
     properties.put(key, value); 
    } 
} 

编辑: 好,根据你的评论,也许这样的事情应该这样做:

​​

编辑2: 要实例化你可以做类似

Properties<Integer, OrderedProperty<Integer>> properties = 
    new Properties<Integer, OrderedProperty<Integer>> 
+0

问题是,Properties类要保存单一类型的属性,所以需要使用Property接口的实现来键入它。通过这种方式,我可以防止将一个ItemProperty放入OrderProperties的集合中。 – fnt 2010-07-07 12:54:53

+0

它看起来像一个不错的选择,但我如何实例化这个Properties类 - 我的意思是类型参数?我尝试使用<?扩展对象>但它没有做 - 我可能错过了一些东西。 – fnt 2010-07-07 14:11:35

+0

正如我在http://stackoverflow.com/questions/3194307/the-use-of-class-type-parameters-in-generic-method/3196582#3196582评论属性应该允许属性中包含的不同数据类型的值,即OrderedProperty ,OrderedProperty 等等。 – fnt 2010-07-08 09:26:28

2

您的Properties类将只能支持一种类型的属性。这可能不是您打算什么,即使这会工作:

public class Properties<V, T extends Property<? extends V>> { 
    public void set(T key, V value) { 
     //... 
    } 
} 

如果你想支持不同类型的属性,则必须手动检查你的财产的合法性。这样做的原因是Java由于type erasure

  1. 让你的房产< V>知道实际类型的它要支持
  2. 检查类型中的属性。设置方法

 

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

} 
+0

我看到,由于类型擦除运行时检查基于类型参数是不可能的。我想得到的是基于提供的类型参数的编译型检查。在set()方法中,K和V是“依赖类型”,所以我想知道是否可以定义这种依赖关系。 虽然 公共类属性> { 公共无效组(T键,V值){ // ... } } 定义了这样的使用类型的参数的依赖性,它看起来像是不可能实例化允许任意类型为V. – fnt 2010-07-08 09:20:42

+0

的属性,无论如何感谢您的答案,运行时检查更好,然后根本没有检查。 – fnt 2010-07-08 09:21:25

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! 
+0

是的,当然我可以按照你提到的方式创建属性的一个实例,但问题是它应该允许不同类型的属性。因此,例如OrderProperty countProperty = new OrderProperty (); orderProperties.put(countProperty,1);和OrderProperty nameProperty = new OrderProperty (); orderProperties.put(nameProperty,“1”);应该可以在同一时间。 – fnt 2010-07-08 09:06:41

+0

如果你看看整个讨论,你会看到我们正在走圆圈;) 属性类本身应接受类型参数,以限制映射键到特定的Property实现。 – fnt 2010-07-09 14:23:00

相关问题