2017-04-21 82 views
1

我是新來的Java,我想知道如何做到這一點在Java或更簡單,更清潔更好,更方便,就像有多個泛型類型的東西Java的多泛型類

public class Item<T1, T2, T3, T4, T5, T6, T7, T8, T9>{ 
    private T1 t1; 
    private T2 t2; 
    private T3 t3; 
    private T4 t4; 
    private T5 t5; 
    private T6 t6; 
    private T7 t7; 
    private T8 t8; 
    private T9 t9; 

    public Item(T1 t1){ 
     this(t1, null, null, null, null, null, null, null, null); 
    } 
    public Item(T1 t1, T2 t2){ 
     this(t1, t2, null, null, null, null, null, null, null); 
    } 

    public Item(T1 t1, T2 t2, T3 t3){ 
     this(t1, t2, t3, null, null, null, null, null, null); 
    } 

    public Item(T1 t1, T2 t2, T3 t3, T4 t4){ 
     this(t1, t2, t3, t4, null, null, null, null, null); 
    } 
    ... 
+1

如果你真的需要9種不同gerenic類型的容器,那麼這實際上可能是最簡單的設計:d – f1sh

+0

'公有get(INT索引){'這不是很好形成。我想你想要'public Object get(int index){' – ControlAltDel

+0

你不需要明確地將其他字段初始化爲'null'。只需做'public Item(T1 t1){this.t1 = t1; }'等 –

回答

0

免責聲明:(停止downvotes ;-))

這只是一個簡單的解決方案,以保持其在檢索用實際類型在,又不同類型的對象,簡單的方式任意數量的無類型安全的保障。謹慎使用!

提出的解決方案:

你可以只使用一個簡單的List<Object>。當你不想搞清楚自己的實際需求是什麼,這可能已經足夠了,你......這裏有一個例子:

public class Item { 
    List<Object> items = new ArrayList<>(); 

    public <T> Item(T... items) { // well... could also just be Object 
    Collections.addAll(this.items, items); 
    } 

    public <T> T get(int index) { 
    return (T) items.get(index); // unsafe of course... but no requirement said something about type safety ;-) 
    } 

    public static void main(String[] args) { 
    Item item = new Item("sum", 123L, 234L, true); 

    if (item.get(3)) { 
     long sum = item.<Long>get(1) + item.<Long>get(2); 
     System.out.println(item.get(0) + " is " + sum); 
    } 
    } 
} 

它打印:

sum is 357 

關於類型安全你可以提高這一點通過提供檢索期間類型和慘遭失敗如果檢索對象是預期的類型不:

public class Item { 
    List<Object> items = new ArrayList<>(); 

    public <T> Item(T... items) { 
    Collections.addAll(this.items, items); 
    } 

    public <T> T get(int index, Class<T> type) { 
    Object item = items.get(index); 
    if (type.isInstance(item)) { 
     return type.cast(item); 
    } 
    throw new RuntimeException("failing miserably as index " + index + " isn't of type " + type); 
    } 

    public static void main(String[] args) { 
    Item item = new Item("sum", 123L, 234L, true); 

    if (item.get(3, Boolean.class)) { 
     long sum = item.get(1, Long.class) + item.get(2, Long.class); 
     System.out.println(item.get(0, String.class) + " is " + sum); 
    } 
    } 
} 

正如其他建議:建設者模式可能也有幫助,但只要你添加更多的類型或者想刪除一些你需要修改代碼的東西。如果你想聲明一個變量來保存你的item,那麼對於構建器模式,你仍然必須編寫所有這些泛型類型信息。這個解決方案沒有必要。當然這個解決方案也有一些問題:第一個變體是不安全的,可能導致ClassCastException。如果你想檢索一個沒有給定類型的對象,第二個變種可能會導致RuntimeException,但至少它是類型安全的,否則;-)所以這取決於你想完成什麼。

如果您不喜歡第二個變體中的RuntimeException,您也可以改用Optional。我故意忽略了這個變體,因爲它使得代碼更加冗長。這裏是get - 實施它:

public <T> Optional<T> get(int index, Class<T> type) { 
    Object item = items.get(index); 
    if (type.isInstance(item)) { 
    return Optional.of(type.cast(item)); 
    } 
    return Optional.empty(); 
} 

最後,我可能不會,因爲它是相當騰出一些代碼的解決方法在生產中使用此代碼。在生產代碼中,我比較喜歡類型安全性。

+0

哦,大屎我喜歡這是 – Ckkn

+1

這是完全不安全的代碼,歡迎'ClassCastException's或'RuntimeException's –

+0

@FedericoPeraltaSchaffner我已經提到它不是類型安全的。 OP尋求一種簡單/乾淨的方式來解決通用災難。建議的解決方案很簡單。關於「乾淨」取決於。該解決方案可以保存不同類型的對象,並檢索實際類型而不是「對象」。第二個變種故意拋出'RuntimeException',因此比第一個更安全。仍然是一個簡單的解決方案,但如果檢索到的對象不是預期類型,則會失敗。這個代碼當然可以改進,但是:它是完整的,不需要任何庫。 – Roland

1

一對夫婦的建議可能對您有用:

  1. 你有「伸縮構造反模式」的情況。 builder design pattern是通常的補救措施。至於你提到你正在尋找一個簡單的解決方案,我會建議使用Lombok的註釋實施類建設者:

    @Getter 
    @Builder 
    class Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> { 
        private T1 t1; 
        private T2 t2; 
        private T3 t3; 
        private T4 t4; 
        private T5 t5; 
        private T6 t6; 
        private T7 t7; 
        private T8 t8; 
        private T9 t9; 
    } 
    

    你必須初始化一個Item這樣的:

    Item<String, Integer, Double, String, Long, Long, Long, Long, Long> item = 
        Item.<String, Integer, Double, String, Long, Long, Long, Long, Long>builder() 
          .t4("text").t2(42).t3(3.14159).build(); 
    

    不幸類型信息是重複的。請注意,您可以跳過字段並按任意順序進行初始化。這將是很多與多個構造函數的工作。其他領域例如t1t5將被留空。

  2. 考慮從jOOL library採用Tuple9。如果你看看source code of Tuple9這並不比你的代碼簡單。這種方法的簡單性在於別人已經完成了實現而不是你。庫最多可支持Tuple16

1

您可以使用庫,代碼預處理器或生成器模式,或者如果你喜歡讓事情變得簡單,你可能只是創建可鏈接的方法,將允許您設置只是屬性你希望,可以以任意順序你想要的:

public class Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> { 
    private T1 t1; 
    private T2 t2; 
    private T3 t3; 
    private T4 t4; 
    private T5 t5; 
    private T6 t6; 
    private T7 t7; 
    private T8 t8; 
    private T9 t9; 

    public Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> t1(T1 t1) { 
     this.t1 = t1; 
     return this; 
    } 

    public Item<T1, T2, T3, T4, T5, T6, T7, T8, T9> t2(T2 t2) { 
     this.t2 = t2; 
     return this; 
    } 

    // TODO: rest of methods 
} 

用法:

Item<String, Double, Integer, Long, Long, Long, Long, Long, String> item = new Item() 
    .t1("hello") 
    .t2(0.123) 
    .t3(123) 
    .t4(123L) 
    .t5(123_456L) 
    .t6(123_456_789L) 
    .t7(654_321L) 
    .t8(321L) 
    .t9("goodbye"); 

或以任何其它順序:

Item<String, Double, Integer, Long, Long, Long, Long, Long, String> item = new Item() 
    .t6(123_456_789L) 
    .t2(0.123) 
    .t3(123) 
    .t5(123_456L) 
    .t7(654_321L) 
    .t8(321L) 
    .t4(123L) 
    .t1("hello") 
    .t9("goodbye"); 

,或只與幾個屬性:(!)

Item<String, Double, Integer, Long, Long, Long, Long, Long, String> item = new Item() 
    .t6(123_456_789L) 
    .t2(0.123) 
    .t3(123);