Java Optional<T>问题,我做得对吗?

3

我有一个“坏习惯”,就是在某些情况下会把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<T>,就像大家建议的那样,但我不确定我是否做得正确。

这是我的代码(简化的枚举):

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();
    }
}

我困扰于文档中有关#get()的内容,文档链接在这里,其中说明:

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

因此,我想通过将getter方法包装在#isPresent()方法中来避免这种情况,但是我无法找到如何返回空值。

请问这样做是正确的方法吗?还是我漏掉了什么?我不是要“修复”,而是要了解效率和正确的实践方法。


如果您正在调用Optional.get(),那么您可能做错了。 - Brian Goetz
3个回答

4
你需要问自己,如果没有返回值,你希望你的getter做什么。
实际上只有四个选项:
1. 返回null(但这样又回到了你试图避免的问题); 2. 使你的getter返回一个Optional<T>而不是T; 3. 如果没有设置,则返回默认值; 4. 抛出异常。
除非有很明确的正确答案可以确定默认值,否则我会选择第2种方法。第4种方法只适用于客户端代码始终知道是否有内容,并且只在有内容时请求内容(这可能很少见,但并非不可能)。

一个题外话,你知道如何从steam().filter()获取EnumSet<>吗?例如:private static final EnumSet <SlayerTasks> ELEMENTS = EnumSet.of (SlayerTasks.class); public static EnumSet<SlayerTasks> byType(Difficulty difficulty) { return ?; } - Hobbyist
2
@Christian.tucker:collect(Collectors.toCollection(()->EnumSet.noneOf(SlayerTasks.class))) - Holger

2

如果你想避免异常,可以用 location.orElse("SomeDefaultValue") 替换 location.get()。这样,当Optional为空时,你就可以返回一个默认值。


1

在我看来,如果你正在使用“maybe”单子(可选值)来实现你的逻辑,你应该坚持使用Optional对象并将其传递,仅在需要时提取包装值。

要修改基础值,您可以使用Optional.ifPresent()Optional.map()Optional.flatMap()方法,例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接