Java泛型中是否有联盟?

时间:2009-11-08 19:08:28

标签: java generics

我可以在集合中包含两种不同的类型吗?例如,我可以使用List<字符串U整数> ?

6 个答案:

答案 0 :(得分:5)

简短回答?不可以。您当然可以List Objects,但是您可以将任何放入其中,而不只是String或{{1}对象。

您可以创建容器对象列表,该容器对象将包含IntegerInteger(可能通过泛型)。更麻烦一点。

String

并实施public class Contained<T> { T getContained(); } Contained<Integer>

当然,真正的问题是你想要这样做的原因吗?我希望集合包含相同类型的对象,然后我可以迭代并对这些对象执行操作,而不必担心它们是什么。也许您的对象层次结构需要进一步思考?

答案 1 :(得分:2)

不。不过,您有几种选择:

  • 您可以使用List&lt;对象&gt;并藏起你喜欢的任何东西;或

  • 您可以使用List&lt; 2级成员&gt;并将您的数据放在其中一个班级成员中。

编辑:示例。

class UnionHolder {
  public String stringValue;
  public int intValue;
}

List < UnionHolder > myList 
...

当然,您需要一些额外的代码来确定从列表中获取的UnionHolder对象中提取哪种数据。一种可能性是让第三个成员具有不同的值,具体取决于它是什么,或者你可以说,有一个成员函数,如

public boolean isItAString() { return (this.stringValue != null }

答案 2 :(得分:1)

除了已经提供的好答案......


您的算法中可能有两种数据类型。但您可能不必将它们放在同一个列表中......

创建两个类型列表可能会使您的算法更清晰,您仍然可以保持“类型安全”并携带所有数据。接下来是两个代码示例,第二个是MyData对象中的两个列表。

public class Algorithm1 {

  public void process(List<String> strings, List<Integer> integers) {
    ...
  }

}

--------------------------------------

public class DataPair {

  public List<String> strings;
  public List<Integer> integers;

}

public class Algorithm2 {

 public void process(DataPair dataPair) {
   ...
 }

}

答案 3 :(得分:0)

没有。以这种方式思考:使用泛型,整个想法是提供类型安全。如果您可以将不同类型的对象放入其中,那将是不可能的。

您可以将非通用java.util.List用于您的目的。

如果您想确保只有StringInteger个对象进入列表,您可以像这样创建自己的List实现:

public class MySpecialList {
   private List list= new LinkedList();
   ...
   public void add(final String string) {
       list.add(string);
   }

   public void add(final Integer integer) {
       list.add(integer);
   }
   ...
   // add rest of List style methods
}

缺点:您失去了List界面清晰度......

答案 4 :(得分:0)

如果您正在使用Java 8或更高版本的函数式编程,您可能需要尝试JavaSealedUnions

Union2.Factory<String, Integer> factory = GenericUnions.doubletFactory();
Union2<String, Integer> strElem = factory.first("hello");
Union2<String, Integer> intElem = factory.second(3);
List<Union2<String, Integer>> list = Array.asList(strElem, intElem);
for (Union2<String, Integer> elem : list) {
    elem.continued(
        strElem -> System.out.println("string: " + strElem),
        intElem -> System.out.println("integer: " + intElem));
}

Haven没有对此进行测试,但我认为你有了这个想法。

答案 5 :(得分:0)

您要描述的内容是Visitor pattern

的完美用例
  • 100%进行了静态类型检查
  • 不需要Java 8或更高版本

用法:

List<UnionType> unionTypes = Arrays
    .asList(new StringContainer("hello"), new IntegerContainer(4));

for (UnionType unionType : unionTypes) {
    unionType.when(new UnionType.Cases<Integer>() {
        @Override
        public Integer is(StringContainer stringContainer) {
            // type-specific handling code
        }

        @Override
        public Integer is(IntegerContainer integerContainer) {
            // type-specific handling code
        }
    });
}

样板代码:

interface UnionType {
    <R> R when(Cases<R> c);
    interface Cases<R> {
        R is(StringContainer stringContainer);
        R is(IntegerContainer integerContainer);
    }
}

class StringContainer implements UnionType {

    private final String value;
    public StringContainer(String value) { this.value = value; }
    public String getValue() { return value; }

    @Override
    public <R> R when(Cases<R> cases) {
        return cases.is(this);
    }
}

class IntegerContainer implements UnionType {

    private final Integer value;
    public IntegerContainer(Integer value) { this.value = value; }
    public Integer getValue() { return value; }

    @Override
    public <R> R when(Cases<R> cases) {
        return cases.is(this);
    }
}