Java中Either类的使用与错误处理:结合自定义类的技术咨询
用Either类结合Human/Weapon/Magazine实现状态处理与错误处理
看起来你想通过Either类优雅处理Human实例的三种状态(无武器、无弹匣、装备齐全),同时规范错误处理逻辑。我来一步步帮你实现这个场景:
1. 先定义基础实体类
咱们先把Human、Weapon、Magazine的基础结构写好,确保它们能准确表达自身状态:
class Magazine { private final int capacity; public Magazine(int capacity) { if (capacity <= 0) { throw new IllegalArgumentException("弹匣容量必须大于0"); } this.capacity = capacity; } public int getCapacity() { return capacity; } } class Weapon { private final Magazine magazine; public Weapon(Magazine magazine) { this.magazine = magazine; } public Magazine getMagazine() { return magazine; } // 判断武器是否有可用弹匣 public boolean hasMagazine() { return magazine != null; } } class Human { private final Weapon weapon; public Human(Weapon weapon) { this.weapon = weapon; } public Weapon getWeapon() { return weapon; } // 判断人类是否持有武器 public boolean hasWeapon() { return weapon != null; } }
2. 实现通用Either类
Either是典型的代数数据类型,用来表示「要么是错误信息,要么是有效对象」。咱们实现一个泛型版本,方便复用:
import java.util.function.Function; // 抽象父类 abstract class Either<L, R> { // 禁止直接实例化 private Either() {} // match方法:统一处理Left和Right两种情况 public abstract <T> T match(Function<L, T> leftHandler, Function<R, T> rightHandler); // Left子类:存储错误信息 public static class Left<L, R> extends Either<L, R> { private final L value; public Left(L value) { this.value = value; } @Override public <T> T match(Function<L, T> leftHandler, Function<R, T> rightHandler) { return leftHandler.apply(value); } } // Right子类:存储有效对象 public static class Right<L, R> extends Either<L, R> { private final R value; public Right(R value) { this.value = value; } @Override public <T> T match(Function<L, T> leftHandler, Function<R, T> rightHandler) { return rightHandler.apply(value); } } // 静态工厂方法,简化对象创建 public static <L, R> Either<L, R> left(L value) { return new Left<>(value); } public static <L, R> Either<L, R> right(R value) { return new Right<>(value); } }
3. 结合Either创建并校验Human实例
接下来写一个工具方法,根据Human的状态返回对应的Either对象:状态不符合预期(无武器/无弹匣)返回Left(错误描述),状态正常返回Right(有效Human):
public class HumanEitherDemo { public static Either<String, Human> createValidHuman(Human human) { if (!human.hasWeapon()) { return Either.left("该人类没有武器"); } else if (!human.getWeapon().hasMagazine()) { return Either.left("该人类的武器没有弹匣"); } else { return Either.right(human); } } public static void main(String[] args) { // 三种测试实例 Human noWeapon = new Human(null); Human noMag = new Human(new Weapon(null)); Human hasAll = new Human(new Weapon(new Magazine(2))); // 处理无武器的情况 Either<String, Human> eitherNoWeapon = createValidHuman(noWeapon); String result1 = eitherNoWeapon.match( error -> "错误:" + error, validHuman -> "人类装备齐全,武器弹匣容量:" + validHuman.getWeapon().getMagazine().getCapacity() ); System.out.println(result1); // 输出:错误:该人类没有武器 // 处理无弹匣的情况 Either<String, Human> eitherNoMag = createValidHuman(noMag); String result2 = eitherNoMag.match( error -> "错误:" + error, validHuman -> "人类装备齐全,武器弹匣容量:" + validHuman.getWeapon().getMagazine().getCapacity() ); System.out.println(result2); // 输出:错误:该人类的武器没有弹匣 // 处理装备齐全的情况 Either<String, Human> eitherHasAll = createValidHuman(hasAll); String result3 = eitherHasAll.match( error -> "错误:" + error, validHuman -> "人类装备齐全,武器弹匣容量:" + validHuman.getWeapon().getMagazine().getCapacity() ); System.out.println(result3); // 输出:人类装备齐全,武器弹匣容量:2 } }
4. 错误处理的扩展思路
- 如果需要更细粒度的错误区分,可以把Left的类型从
String改成自定义枚举(比如ErrorType.NO_WEAPON、ErrorType.NO_MAGAZINE),后续处理错误时能精准分支。 - 可以在Human/Weapon的构造方法里提前做参数校验(比如Weapon不允许传入null弹匣),但用Either的好处是可以把错误延迟到使用时统一处理,灵活性更高。
- 可以扩展Either的方法,比如添加
isLeft()/isRight()判断,或者getOrElse()方法提供默认值。
内容的提问来源于stack exchange,提问作者Cole
相关产品推荐
相关产品推荐

