2016-02-28 53 views
1

我想创建具有两个值的通用元组。例如一个具有两个字符串或两个整数的元组等(通用值)。但它不应该能够混合两个元素,例如一个字符串与一个整数(例如一个哈希映射)。创建具有相同类元素的通用元组

如何创建一个类型相同的元组?此刻,我为元组中的两个元素使用了通配符泛型参数,当然这不会强制开发人员为这两个元素使用相同的类类型。

import java.io.Serializable; 

public class Main { 
    class Element<T extends Comparable<?> & Serializable> { 
     private final T element; 

     public Element(T element) { 
      this.element = element; 
     } 

     public String raw() { 
      return element.toString(); 
     } 
    } 

    class Tuple<T extends Element<?>, U extends Element<?>> { 
     private final Element<?> element1; 
     private final Element<?> element2; 

     public Tuple(Element<?> element1, Element<?> element2) { 
      this.element1 = element1; 
      this.element2 = element2; 
     } 

     public Element<?> getElement1() { 
      return element1; 
     } 

     public Element<?> getElement2() { 
      return element2; 
     } 
    } 

    public static void main(String[] args) { 
     new Main(); 
    } 

    public Main() { 
     Element<String> element1 = new Element<String>(new String("First tuple element")); 
     Element<String> element2 = new Element<String>(new String("Second tuple element")); 
     Element<Integer> wrongelement = new Element<Integer>(42); // <-- Should not be possible, but it is... 
     Tuple<Element<String>, Element<String>> tuple = new Tuple<Element<String>, Element<String>>(element1, element2); 

     // First tuple element 
     System.out.println(tuple.getElement1().raw()); 

     // Second tuple element 
     System.out.println(tuple.getElement2().raw()); 
    } 
} 

回答

1

Tuple类简单地只用一个通用的类型,有你的元素中的字段是通用型的,而不是超类(即T element1而不是Element<?> element1):

class Tuple<T extends Element<?>> { 

    private final T element1; 
    private final T element2; 

    public Tuple(T element1, T element2) { 
     this.element1 = element1; 
     this.element2 = element2; 
    } 

    public T getElement1() { 
     return element1; 
    } 

    public T getElement2() { 
     return element2; 
    } 
} 

然后你可以简单地用一种类型的实例它是这样:

public static void main(String... args) { 

    Element<String> element1 = new Element<String>(new String("First tuple element")); 
    Element<String> element2 = new Element<String>(new String("Second tuple element")); 

    Tuple<Element<String>> tuple = new Tuple<Element<String>>(element1, element2); 

    // First tuple element 
    System.out.println(tuple.getElement1().raw()); 

    // Second tuple element 
    System.out.println(tuple.getElement2().raw()); 
} 

顺便说一句,你不必new String你的字符串,你可以简单地p rovide其视为常规字符串:

Element<String> element1 = new Element<String>("First tuple element"); 
Element<String> element2 = new Element<String>("Second tuple element"); 
+0

谢谢,我不知道为什么我没有想到这一点。 – swaechter

1

看来你只是想这样:

class Tuple<T extends Comparable<?> & Serializable> { 
    private final Element<T> element1; 
    private final Element<T> element2; 

    public Tuple(Element<T> element1, Element<T> element2) { 
     this.element1 = element1; 
     this.element2 = element2; 
    } 

    public Element<T> getElement1() { 
     return element1; 
    } 

    public Element<T> getElement2() { 
     return element2; 
    } 
} 

public Main() { 
    Element<String> element1 = new Element<>("First tuple element"); 
    Element<String> element2 = new Element<>("Second tuple element"); 
    Element<Integer> wrongelement = new Element<>(42); 

    // compiles fine 
    Tuple<String> tuple = new Tuple<>(element1, element2); 

    // doesn't compile 
    Tuple<String> tuple = new Tuple<>(element1, wrongelement); 
} 
+0

谢谢,我接受了另一个解答,因为它是第一个。我也猜测返回T是更通用的,并简化了代码的重构(如果你想用AnotherElement替换Element)。另一方面,IDE支持可能会更好,因为写出返回元素。 – swaechter

+1

另一个答案看起来不对我。它允许这样做,例如:'元组>元组=新元组>(element1,wrongelement);'。您似乎不想使用Element的子类参数化Tuple。你似乎想要一个包含相同泛型类型的两个元素的元组。 –

0

在不重新发明轮子的利益,你可以考虑使用是已经存在的元组或对执行。 Apache的commons-lang库,例如,包括Pair<R, L>实现,你可以通过它只是绑两个泛型类型参数是相同的空类扩展...

import org.apache.commons.lang3.tuple.Pair 

public class MyPair<T> extends Pair<T, T> { } 

如果你真的想保持你的API,您可以非常简单地使用Pair方法left()right()来实现这些方法。

相关问题