Java 泛型方法中类类型参数的使用

Java 泛型方法中类类型参数的使用,java,generics,types,Java,Generics,Types,我有一个泛型类,用于保存不同类型属性的值。我想提供一种类型安全的方法来设置属性值,这样就不可能为属性指定错误类型的值 我为所有属性类型定义了一个要实现的接口: public interface Property<T> { } 最初我实现这个类来保存属性值,比如 public class Properties<K extends Property> { private Map<K, Object> properties = new HashMap

我有一个泛型类,用于保存不同类型属性的值。我想提供一种类型安全的方法来设置属性值,这样就不可能为属性指定错误类型的值

我为所有属性类型定义了一个要实现的接口:

public interface Property<T> {

} 
最初我实现这个类来保存属性值,比如

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

}
公共类属性{
私有映射属性=新HashMap();
公共无效集(K键,V值){
属性。put(键、值);
}
}
问题是set()方法显然不是类型安全的,因为它不考虑属性与其值类型之间的连接,所以我可以很容易地编写类似的代码

Properties orderProperties = new Properties<OrderProperty>();
OrderProperty countProperty = new OrderProperty<Integer>();
orderProperties.set(countProperty, "1");
public <V> void set(K<V> key, V value) {
    properties.put(key, value);
}
Properties<Integer, OrderedProperty<Integer>> properties = 
    new Properties<Integer, OrderedProperty<Integer>>
Properties orderProperties=新属性();
OrderProperty countProperty=新的OrderProperty();
orderProperties.set(countProperty,“1”);
它会编译

类型安全实现将是

public <V> void set(Property<V> key, V value) {
    properties.put(key, value);
}
公共无效集(属性键,V值){
属性。put(键、值);
}
但它当然不会编译,因为键不是泛型类型

我需要像这样的东西

Properties orderProperties = new Properties<OrderProperty>();
OrderProperty countProperty = new OrderProperty<Integer>();
orderProperties.set(countProperty, "1");
public <V> void set(K<V> key, V value) {
    properties.put(key, value);
}
Properties<Integer, OrderedProperty<Integer>> properties = 
    new Properties<Integer, OrderedProperty<Integer>>
公共无效集(K键,V值){
属性。put(键、值);
}
但这一条在语法上是不正确的


我想知道是否有什么方法可以满足我的需要。

我想应该用一些东西作为

public class Properties<V> {
    public void set(Property<V> key, V value) {
        properties.put(key, value);
    }
}
公共类属性{
公共无效集(属性键,V值){
属性。put(键、值);
}
}
编辑: 好的,根据你的评论,也许像这样的事情可以做到:

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

    }
}
公共类属性{
公共无效集(T键,V值){
}
}
编辑2: 要实例化该类,可以执行以下操作

Properties orderProperties = new Properties<OrderProperty>();
OrderProperty countProperty = new OrderProperty<Integer>();
orderProperties.set(countProperty, "1");
public <V> void set(K<V> key, V value) {
    properties.put(key, value);
}
Properties<Integer, OrderedProperty<Integer>> properties = 
    new Properties<Integer, OrderedProperty<Integer>>
属性=
新特性

我想应该用一些东西作为

public class Properties<V> {
    public void set(Property<V> key, V value) {
        properties.put(key, value);
    }
}
公共类属性{
公共无效集(属性键,V值){
属性。put(键、值);
}
}
编辑: 好的,根据你的评论,也许像这样的事情可以做到:

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

    }
}
公共类属性{
公共无效集(T键,V值){
}
}
编辑2: 要实例化该类,可以执行以下操作

Properties orderProperties = new Properties<OrderProperty>();
OrderProperty countProperty = new OrderProperty<Integer>();
orderProperties.set(countProperty, "1");
public <V> void set(K<V> key, V value) {
    properties.put(key, value);
}
Properties<Integer, OrderedProperty<Integer>> properties = 
    new Properties<Integer, OrderedProperty<Integer>>
属性=
新特性

您的
属性
类只能支持一种类型的属性。这可能不是您想要的,即使这会起作用:

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

公共类属性您的
属性
类将只能支持一种类型的属性。这可能不是您想要的,即使这会起作用:

public class Properties<V, T extends Property<? extends V>> {
    public void set(T key, V value) {
      //...
    }
}
公共类属性已编辑
好的,很抱歉,我没有完全理解你的要求。在你的情况下,我以前的回答可能是毫无用处的。由于您希望能够在
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);
    }

}
公共静态类属性{
私有映射,对象>();
公共作废put(属性键,V值){
属性。put(键、值);
}
@抑制警告(“未选中”)
公共V get(属性密钥){
返回(V)属性。获取(键);
}
}
在这种情况下,只能放置与该属性类型匹配的属性和值,如下所示:

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!
OrderProperty stringProperty=新的OrderProperty();
OrderProperty countProperty=新的OrderProperty();
Properties orderProperties=新属性();
put(countProperty,3);
orderProperties.put(stringProperty,“”);
放置(stringProperty,2)//这不会编译!
已编辑 好的,很抱歉,我没有完全理解你的要求。在你的情况下,我以前的回答可能是毫无用处的。由于您希望能够在
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);
    }

}
公共静态类属性{
私有映射,对象>();
公共作废put(属性键,V值){
属性。put(键、值);
}
@抑制警告(“未选中”)
公共V get(属性密钥){
返回(V)属性。获取(键);
}
}
在这种情况下,只能放置与该属性类型匹配的属性和值,如下所示:

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!
OrderProperty stringProperty=新的OrderProperty();
OrderProperty countProperty=新的OrderProperty();
Properties orderProperties=新属性();
put(countProperty,3);
orderProperties.put(stringProperty,“”);
放置(stringProperty,2)//这不会编译!

私有地图属性
为什么这不是
地图
?我记得你说过,
T
是值的类型。我很困惑。T用于在两个位置命名类型参数:在接口属性中,它引用值类型;在类属性中,T用于指示属性的类型(可能有许多这样的属性,如OrderProperty、ItemProperty等等)。我想为它们实现通用容器。我编辑了帖子以避免混淆
私有映射属性
为什么这不是
映射
?我记得你说过,
T
是值的类型。我很困惑。T用于在两个位置命名类型参数:在接口属性中,它引用值类型;在类属性中,T用于指示属性的类型(可能有许多这样的属性,如OrderProperty、ItemProperty等等)。我想为它们实现通用容器。我编辑了这篇文章以避免混淆问题是Properties类要保存单一类型的属性,因此需要使用Property接口的实现来键入它。通过这种方式,我可以防止将ItemProperty放入OrderProperty的集合中