使用相同的类元素创建通用元组

时间:2016-02-28 15:35:35

标签: java generics tuples containers

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

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

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

3 个答案:

答案 0 :(得分: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你的字符串,你可以简单地将它们作为常规字符串提供:

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

答案 1 :(得分: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); 
}

答案 2 :(得分:0)

为了不重新发明轮子,您可以考虑使用现有的Tuple或Pair实现。例如,Apache的commons-lang库包含一个Pair<R, L>实现,您可以通过一个空类扩展它,它只是将两个泛型类型参数绑定为相同...

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

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

如果你真的想保留你的API,你可以根据配对方法left()right()非常简单地实现这些方法。

相关问题