【问题标题】:Java Optional<T> questions, am I doing this right?Java Optional<T> 问题,我这样做对吗?
【发布时间】:2014-11-24 10:20:53
【问题描述】:

我有一个“坏习惯”,即在某些地方不存在时将null 扔到诸如枚举器之类的地方。

例子:

private enum Foo {
    NULL(1, null, 2),
    NOT_NULL(3, new Bar(), 4);

    private int a, c;
    private Bar b;

    Foo(int a, Bar b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}

所以现在我正在尝试将我的代码转换为使用Optional&lt;T&gt; 就像每个人都建议的那样,但我不确定我是否正确地做。

这是我的代码(修剪过的枚举):

public static enum Difficulty { 
    EASY, MEDIUM, HARD
}

public static enum SlayerTasks {
    NONE(0, Optional.empty(), Optional.empty(), Optional.empty()),
    NPC(1, Optional.of(Difficulty.EASY), Optional.of("That one place."), Optional.of(1));

    private int taskId;
    private Optional<Difficulty> difficulty;
    private Optional<String> location;
    private Optional<Integer> npcId;

    SlayerTasks(int taskId, Optional<Difficulty> difficulty, Optional<String> location, Optional<Integer> npcId) {
        this.taskId = taskId;
        this.difficulty = difficulty;
        this.location = location;
        this.npcId = npcId;
    }

    public int getTaskId() {
        return taskId;
    }

    public Difficulty getDifficulty() {
        return difficulty.get();
    }

    public String getLocation() {
        return location.get();
    }

    public int getNpcId() {
        return npcId.get();
    }
}

困扰我的是在here 找到的引用#get() 的文档,其中指出:

如果此 Optional 中存在值,则返回该值,否则抛出 NoSuchElementException。

所以,我想为了防止这种情况,我会将 getter 包装在 #isPresent() 中,但后来我不知道如何返回空。

这是正确的做事方式,还是我错过了什么?我不是在寻找“修复”,而是在寻找有关效率和正确做法的信息。

【问题讨论】:

  • 如果你调用 Optional.get() 你可能做得不对。

标签: java java-8 optional


【解决方案1】:

如果没有什么可以返回,你需要问问自己你想让你的 getter 做什么。

实际上只有四个选项:

  1. 返回一个空值(但随后你又回到了你试图避免的状态);
  2. 让您的 getter 返回 Optional&lt;T&gt; 而不是 T
  3. 如果没有设置则返回默认值;
  4. 抛出异常。

除非对默认值有一个非常明确的正确答案,否则我会选择 2。 4 仅适用于客户端代码应该始终知道那里是否有某些东西并且只有在存在时才请求它(这将是不寻常的,但并非不可能)。

【讨论】:

  • 一个快速的题外话问题,你知道如何从 steam().filter() 中获取 EnumSet 吗?例如:private static final EnumSet&lt;SlayerTasks&gt; ELEMENTS = EnumSet.of(SlayerTasks.class); public static EnumSet&lt;SlayerTasks&gt; byType(Difficulty difficulty) { return ?; }
  • @Christian.tucker: collect(Collectors.toCollection(()-&gt;EnumSet.noneOf(SlayerTasks.class)))
【解决方案2】:

如果您希望避免异常,可以将location.get() 替换为location.orElse("SomeDefaultValue")。这允许您在 Optional 为空时返回默认值。

【讨论】:

    【解决方案3】:

    IMO,如果您使用 'maybe' monad(可选值)来实现您的逻辑,您应该坚持使用 Optional 对象并将其折腾,仅在需要时提取包装的值。

    要修改不符合条件的值,您可以使用Optional.ifPresent()Optional.map()Optional.flatMap() 方法,例如

    Optional<Difficulty> difficulty = NPC.getDifficulty();
    difficulty.ifPresent(diff -> { /* do comething here ... */ });
    

    【讨论】:

      猜你喜欢
      • 2012-08-13
      • 2023-03-19
      • 1970-01-01
      • 2015-01-13
      • 2015-06-09
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      • 2012-07-13
      相关资源
      最近更新 更多