限制Java中的类型以在List中使用

时间:2014-12-31 15:50:41

标签: java generics

如何传递一个List<T>,其中包含一些我未向方法声明的特定允许类型。

E.g。将类型限制为Integer,Boolean和String

// Pseudo code
public void method(List<Integer OR Boolean OR String> myList);

如果我使用List<Object>,我可以将所有内容放入该列表中:

public void method(List<Object> myList);

如果我使用List,我可以将Parent及其子类的所有实例放入该列表中:

public void method(List<Parent> myList);

如果我是声明那些子类(AllowedTypeA extends Parent)的人就足够了。但是,当我不是我想要使用的类的所有者时,我该怎么办(我无法使Integer扩展Parent)?

2 个答案:

答案 0 :(得分:7)

最好的办法是将这个混合列表包装成一个类,并提供方法来添加你想要允许的内容:

class WrappedMix {
    private List<Object> oddsAndEnds = ...

    public void add( Integer el ){ oddsAndEnds.add( el ); }
    public void add( Boolean el ){ oddsAndEnds.add( el ); }
    public void add( String el ){ oddsAndEnds.add( el ); }
}

或者使用合适的覆盖(和重载)扩展ArrayList,

虽然我很好奇你为什么要这样一个列表 - 它的处理并不方便。

答案 1 :(得分:2)

从概念上讲,我更喜欢@ laune的解决方案。我更喜欢类型安全和编译错误,而不是将一堆东西扔进列表并忘记添加允许的类型。

话虽这么说,它仍然可以做,虽然你必须做一些额外的东西来使这个实用,即如果你删除对象类型,你也应该删除所有与之关联的对象它需要覆盖其他方法,例如addAll以确保正常运行。

这种方法与laune相比更加灵活,因为您可以随时添加allowedTypes。对于你的情况,可能不是最好的,但一般的问题仍然有趣,我拍了一下。也许你想要一些你的列表来存储整数,而不是其他的。您可以使用addPermittedObject方法执行此操作。

public class SelectiveList extends ArrayList<Object> {
    //the (types of) objects that we can store
    private ArrayList<Object> permittedObjects = new ArrayList<Object>();

    // put an Object type into the list
    public boolean addPermittedObject(Object o) {
        for (Object type : permittedObjects) {
            if (type.getClass() == o.getClass()) {
                return false; // if we already have it, do not add it again
            }
        }
        return permittedObjects.add(o); // else let's add it
    }

    // remove the Object type
    public boolean removePermittedObject(Object o) {
        for (Object type : permittedObjects) {
            if (type.getClass() == o.getClass()) {
                return permittedObjects.remove(type);
            }
        }
        return false;
    }

    @Override
    public boolean add(Object o) {
        for (Object type : permittedObjects) {
            if (type.getClass() == o.getClass()) {
                return super.add(o); // go ahead and add the item since it
                                        // matches our list
            }
        }
        return false;
    }
}

并测试它:

public static void main(String[] args) {
    SelectiveList selectiveList = new SelectiveList();
    selectiveList.add("Potato");
    selectiveList.add(1);
    selectiveList.add(true);
    System.out.println(selectiveList.size()); // prints 0
    // these objects need to be initialized, but their contents do not
    // matter
    selectiveList.addPermittedObject(new String());
    selectiveList.addPermittedObject(new Boolean(false));
    selectiveList.addPermittedObject(new Integer(1));
    selectiveList.add("Potato");
    selectiveList.add(1);
    selectiveList.add(true);
    System.out.println(selectiveList.size()); // prints 3
}