我想创建一个具有两个值的通用元组。例如,具有两个字符串或两个整数等的元组(泛型值)。但是它不应该能够混合这两个元素,例如字符串和整数(例如哈希映射)。
如何创建类型相同的元组?目前,我对元组中的两个元素都使用通配符泛型参数,当然这不会强制开发人员对两个元素使用相同的类类型。
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());
}
}
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
字符串,您可以简单地将它们作为常规字符串提供:
Element<String> element1 = new Element<String>("First tuple element");
Element<String> element2 = new Element<String>("Second tuple element");
似乎你只是想要这个:
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);
}
为了不重新发明轮子,您可以考虑使用现有的元组或对实现。例如,Apache 的 commons-lang 库包含一个Pair<R, L>
实现,您可以通过一个空类来扩展它,该空类只是将两个泛型类型参数绑定为相同......
import org.apache.commons.lang3.tuple.Pair
public class MyPair<T> extends Pair<T, T> { }
如果你真的想保留你的API,你可以非常简单地根据配对方法left()
和right()
来实现这些方法。