如何返回多个类型的对象

Hap*_*ppy 6 java collections list random-access

让我们举个例子来简化它.我构建了一个构造函数采用的列表integer和a List<Integer>.我的列表将包含给定列表的所有元素乘以integer.我的列表不存储新元素,而是动态计算它们:

class MyList extends AbstractList<Integer> implements RandomAccess {
    private final int multiplier;
    private final List<Integer> list;

    public MyList(int multiplier, List<Integer> list) {
        this.multiplier = multiplier;
        this.list = list;
    }

    @Override
    public Integer get(int index) {
        return list.get(index) * multiplier;
    }

    @Override
    public int size() {
        return list.size();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,我们可以调用new MyList(3, list)list = [0, 1, 2, 3]获得[0, 3, 6, 9].

我想限制开发人员给MyList构造函数一个列表,这也是RandomAccess为了确保他不会破坏性能.

我尝试用以下方法更改构造函数:

public <E extends List<Integer> & RandomAccess> MyList(int multiplier, E list)
Run Code Online (Sandbox Code Playgroud)

MyList不是问题,但现在我们不能在不使用两者List<Integer>RandomAccess类似的实现的情况下调用构造函数ArrayList<Integer>.所以有这个列表的人:List<Integer> list = new ArrayList<>();不能这样做new MyList(3, list);(因为它是用声明List<Integer>而不是ArrayList<Integer>).

我的另一个解决方案就是这个:

public MyList(int multiplier, List<Integer> list) {
        if(!(list instanceof RandomAccess)) {
            // Do something like log or throw exception
        }
        this.multiplier = multiplier;
        this.list = list;
    }
Run Code Online (Sandbox Code Playgroud)

但是现在我无法在编译时检查列表是否实现RandomAccess,我需要使用instanceof而且我讨厌这样做.

我很确定有更好的方法,但它是什么?

Pau*_*ton 1

您可以采用 所使用的解决方案Collections.unmodifiableList。使用一个静态方法来代替公共构造函数,该方法返回两个实现之一,一个实现RandomAccess,另一个不实现。

这是 的代码Collections.unmodifiableList

public static <T> List<T> unmodifiableList(List<? extends T> list) {
    return (list instanceof RandomAccess ?
            new UnmodifiableRandomAccessList<>(list) :
            new UnmodifiableList<>(list));
}
Run Code Online (Sandbox Code Playgroud)

我知道你说过你不喜欢使用instanceof. 我也不知道,但有时这是最好的做法。

请注意,使用构造函数的解决方案

public <E extends List<Integer> & RandomAccess> MyList(int multiplier, E list)
Run Code Online (Sandbox Code Playgroud)

不仅丑陋,因为它迫使程序员强制转换(例如转换为ArrayList),但它实际上不起作用。例如,如果list是 的实例Collections$UnmodifiableRandomAccessList,则甚至无法将其转换为同时实现List和 的类型RandomAccess,因为Collections$UnmodifiableRandomAccessList它是私有的。