2010-07-07 149 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

相關問題