Java 枚举内的 EnumSet 修饰符

EnumSet modifiers inside an enum in Java

在带有修饰符 staticfinal 的枚举中声明 EnumSet 有意义吗?还是多余?

示例:

public enum Guitar {
    STRATOCASTER,
    LES_PAUL,
    CLASSIC;

    private static final EnumSet electrics = EnumSet.of(STRATOCASTER, LES_PAUL);
}

谢谢!

这不是多余的,枚举中的字段 class 不是静态的或最终的。 但是,您不能从其他 classes.

调用非静态枚举的字段

It makes sense declaring an EnumSet within a enum with the modifiers static and final? Or are redundant?

不,它们并不多余。考虑以下示例,其中 nonElectrics 可以设置,因为它不是 final.

import java.util.EnumSet;

enum Guitar {
    STRATOCASTER, LES_PAUL, CLASSIC;

    private static final EnumSet<Guitar> electrics = EnumSet.of(STRATOCASTER, LES_PAUL);
    static EnumSet<Guitar> nonElectrics = EnumSet.of(CLASSIC);

    public static EnumSet<Guitar> getNonElectrics() {
        return nonElectrics;
    }

    public static void setNonElectrics(EnumSet<Guitar> nonElectrics) {
        Guitar.nonElectrics = nonElectrics;
    }

    public static EnumSet<Guitar> getElectrics() {
        return electrics;
    }

    public boolean isElectronics() {
        return electrics.contains(this);
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Guitar.STRATOCASTER.isElectronics());
        System.out.println(Guitar.CLASSIC.isElectronics());
        EnumSet<Guitar> electrics = EnumSet.of(Guitar.STRATOCASTER, Guitar.LES_PAUL);
        Guitar.setNonElectrics(electrics);
        System.out.println(Guitar.getNonElectrics());
    }
}

tl;博士

static final public Set ELECTRICS = Set.of( STRATOCASTER , LES_PAUL ) ;

详情

关于您的代码:

private static final EnumSet electrics = EnumSet.of(STRATOCASTER, LES_PAUL);

private

正如所写,不需要 private

如果标记为 private,则其他代码将无法访问此集合。所以它没有用。

static

是的,static是合适的。枚举定义了其 class 的特定数量的命名实例。当 class 在 运行 时间首次加载时,实例化会自动发生。所以每个枚举对象都是一个单独的对象。不需要他们每个人都有自己的一套。该集合是不变的,因此只需通过标记 static.

来定义该集合的单个实例

这使语法更加清晰,因为我们不按名称涉及任何枚举对象。示例代码:

Set < Guitar > guitars = Guitar.ELECTRICS ; 

或者:

Guitar.ELECTRICS.stream.forEach( System.out::println ) ;

final

是的,如果此集合在此应用程序的整个 运行 期间不变,则将其标记为 final。标记为 final 可防止将任何其他集合分配给该字段。

EnumSetSet

关于第一个 EnumSet,只需 Set

通常最好承诺更通用的超级 class 或接口,而不是将自己锁定在特定的具体 class.

electricsELECTRICS

名字electrics应该全部大写,如果你想让这个集合固定不变。按照惯例,Java 中的常量以全部大写命名。所以,ELECTRICS.

集合的复数命名

很好,你将 ELECTRICS 命名为复数。这个名字表明它是一个集合而不是一个单一的枚举对象。

Set.of 对于不可修改的集合

至于第二个EnumSet,一般使用EnumSet是处理枚举对象的正确选择。 EnumSet class 针对枚举进行了高度优化,从而在使用非常少的内存的同时实现了非常快的性能。

但这里的问题是 EnumSet 是可变的。我希望您不希望任何错误的代码在您的集合中添加或删除元素。

所以我们想要一个不可变的集合。 Java 提供了 unmodifiable set via the Set.of… 方法。

在幕后,这些方法可以自由使用他们想要的任何具体 class,因此可以自由地优化底层 class 的选择。所以你最终可能会得到一个高效的具体 class,比如 EnumSet。但这并不是最重要的,因为在这种情况下,不变胜过性能。

解决方案代码

所以我会把代码写成:

static final public Set ELECTRICS = Set.of( STRATOCASTER , LES_PAUL ) ;

第三方库中的显式不可变集合

使用 Set.of 的替代方法是向您的项目添加一个库,该库提供不可变性作为其集合数据类型的显式部分。也许 Eclipse Collections or Google Guava.

关于冗余,请参阅正确的