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

Seb*_*rth 6 java generics

如何通过一List<T>组我未向方法声明的某些允许类型传递.

例如,将类型限制为Integer,Boolean和String:

// Pseudo code
public void method(List<Integer OR Boolean OR String> myList);
Run Code Online (Sandbox Code Playgroud)

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

public void method(List<Object> myList);
Run Code Online (Sandbox Code Playgroud)

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

public void method(List<Parent> myList);
Run Code Online (Sandbox Code Playgroud)

如果我是声明那些子类(AllowedTypeA extends Parent)的那个就足够了.但是,当我不是我想要使用的类的所有者时,我能做什么(我无法进行Integer扩展Parent)?

lau*_*une 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 ); }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Com*_*ass 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

并测试它:

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
}
Run Code Online (Sandbox Code Playgroud)