我建议使用类似“任何一种”类型的东西。任何一个都可以保存一种类型或另一种类型的值,但不能同时保存两者。然后,您的列表具有两者之一的类型。这是一个更明确的解决方案。
这里是用法:
final List<Either<Integer, String>> list = new ArrayList<>();
list.add(Either.left(1234));
list.add(Either.right("hello"));
for (final Either<Integer, String> i : list) {
if (i.isLeft()) {
System.out.println(i.left());
} else {
System.out.println(i.right());
}
}
代码如下:
package com.stackoverflow.q1351335;
public interface Either<L, R> {
boolean isLeft();
L left();
R right();
static <L, R> Either<L, R> left(final L value) {
return new EitherLeft<>(value);
}
static <L, R> Either<L, R> right(final R value) {
return new EitherRight<>(value);
}
}
package com.stackoverflow.q1351335;
import java.util.Objects;
public final class EitherLeft<L, R> implements Either<L, R> {
private final L value;
public boolean isLeft() {
return true;
}
public L left() {
return value;
}
public R right() {
throw new IllegalStateException("Cannot get right value from an EitherLeft");
}
public EitherLeft(final L value) {
super();
this.value = value;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof EitherLeft) {
Objects.equals(this.value, ((EitherLeft) obj).value);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@Override
public String toString() {
return "EitherLeft[" + Objects.toString(value) + "]";
}
}
package com.stackoverflow.q1351335;
import java.util.Objects;
public final class EitherRight<L, R> implements Either<L, R> {
private final R value;
public boolean isLeft() {
return false;
}
public L left() {
throw new IllegalStateException("Cannot get left value from an EitherRight");
}
public R right() { return value; }
public EitherRight(final R value) {
super();
this.value = value;
}
@Override
public boolean equals(final Object obj) {
if (obj instanceof EitherRight) {
Objects.equals(this.value, ((EitherRight) obj).value);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(value);
}
@Override
public String toString() {
return "EitherRight[" + Objects.toString(value) + "]";
}
}
更新
对这段代码的一个很好的改进是向Either添加一个“匹配”函数:
// Illustration of usage:
myEither.match(
leftValue -> {
// Do stuff with left
},
rightValue -> {
// Do stuff with right
});
这种方法的优点是不可能意外访问EitherRight 的左侧或EitherLeft 的右侧。这是对更多功能(如在 FP)语言中使用的方法的模仿。