Java 中枚举中的 EnumSet 修饰符

问题描述

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

示例:

public enum guitar {
    STRATOCASTER,LES_PAUL,CLASSIC;

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

谢谢!

解决方法

在带有修饰符的枚举中声明一个 EnumSet 是有意义的 静态和最终?还是多余的?

不,它们不是多余的。考虑以下示例,其中可以设置 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 是合适的。枚举定义了其类的特定数量的命名实例。当类在运行时首次加载时,实例化会自动发生。所以每个枚举对象都是一个单独的对象。不需要每个人都有自己的一套。该集合是不变的,因此只需通过将其标记为 static 来定义该集合的单个实例。

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

Set < Guitar > guitars = Guitar.ELECTRICS ; 

或者:

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

final

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

EnumSetSet

关于第一个 EnumSet,将其简化为 Set

通常最好承诺一个更通用的超类或接口,而不是将自己锁定在特定的具体类中。

electricsELECTRICS

名称 electrics 应该全部大写,如果您打算将此设置固定不变。按照惯例,Java 中的常量以全部大写命名。所以,ELECTRICS

集合的复数命名

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

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

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

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

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

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

解决方案代码

所以我会把这段代码写成:

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

第三方库中明确不可变的集合

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

至于冗余,请参阅正确的 Answer by Live and Let Live