Java 多重枚举初始化

Java 多重枚举初始化,java,enums,Java,Enums,我一直在尝试建立一个类,我希望它或多或少保持静态,因此我可以按类别选择不同的元素,如下所示: MyClass.CategoryOne.ELEMENTONE 我为实现这一目标所做的是 public class ElementClass { public static List<Element> elementList = new ArrayList<Element>(); public enum Animals { DOG(new Dog()), CAT(

我一直在尝试建立一个类,我希望它或多或少保持静态,因此我可以按类别选择不同的元素,如下所示: MyClass.CategoryOne.ELEMENTONE

我为实现这一目标所做的是

public class ElementClass {
public static List<Element> elementList = new ArrayList<Element>();

public enum Animals {
    DOG(new Dog()),
    CAT(new Cat());

    private Animal element;

    private Animals (Animal element) {
        this.element= element;

        addToList(element);
    }

    public Animal getElement() {
        return element;
    }
}

public enum Plants {
    TREE(new Tree());
    BUSH(new Bush());

    private Plant element;

    private Plants (Plant element) {
        this.element= element;

        addToList(element);
    }

    public Plant getElement() {
        return element;
    }
}

public enum Buildings {
    FENCE(new Fence()),
    BRIDGE(new Bridge()),

    private Building element;

    private Buildings(Building element) {
        this.entity = element;

        addToList(element);
    }

    public Building getElement() {
        return element;
    }
}

private static void addToList(Element element) {
    if (!elementList.contains(element)) {
        elementList.add(element);
    }
}
而且很早就打电话给了我但我想知道。。有没有一种方法可以做到这一点,而不必在没有其他目标的情况下添加值调用?我认为我的方法不是最好的,但我不知道其他方法可以让我以这种方式访问每个元素(例如ElementClass.Animals.DOG)


如果方法还不错,那么在类启动时是否有方法遍历所有枚举?或者将其添加到for循环中的方法(我不知道getClass().getFields()是否有帮助,或者是否可以将字段强制转换为enum以获取值)。

此代码有几个问题

  • 它使用非最终静态字段。这几乎总是一种代码气味。这个列表应该是最终的:任何代码都可以用另一个代码替换这个列表
  • 该列表是可修改的。任何代码都可以从列表中删除元素、对其排序或向列表中添加元素。它应该包装在一个不可修改的视图中
  • 当类加载器加载每个枚举时,列表将被延迟填充。看来你很想把它装上。这也会导致线程安全问题
  • 列表由枚举构造函数填充。那不应该在那里做
  • 我的建议是,从构造函数中删除addToList调用,并使用如下方法:

    public static final List<Element> ELEMENT_LIST = createList();
    
    private static List<Element> createList() {
        List<Element> result = new ArrayList<>();
        List<HasElement> enumValues = new ArrayList<>();
        enumValues.addAll(Arrays.asList(Animal.values));
        enumValues.addAll(Arrays.asList(Plant.values));
        ...
        for (HasElement hasElement : enumValues) {
            result.add(hasElement.getElement());
        }
        return Collections.unmodifiableList(result);
    
    }
    
    interface HasElement {
        Element getElement();
    }
    
    public enum Animals implements HasElement {
        DOG(new Dog()),
        CAT(new Cat());
    
        private Animal element;
    
        private Animals (Animal element) {
            this.element = element;
        }
    
        @Override
        public Animal getElement() {
            return element;
        }
    }
    
    public静态最终列表元素_List=createList();
    私有静态列表createList(){
    列表结果=新建ArrayList();
    List enumValues=new ArrayList();
    enumValues.addAll(Arrays.asList(Animal.values));
    addAll(Arrays.asList(Plant.values));
    ...
    for(HasElement HasElement:enumValues){
    add(hasElement.getElement());
    }
    返回集合。不可修改列表(结果);
    }
    界面元素{
    元素getElement();
    }
    公共枚举元素{
    狗(新狗)(),
    猫(新猫());
    私人动物因素;
    私人动物(动物元素){
    this.element=元素;
    }
    @凌驾
    公共动物元素(){
    返回元素;
    }
    }
    
    跳过所有枚举并使用静态内部类怎么样?例如:

    public final class ElementClass {
    
    public static void main(String[] args) {
        ElementClass.Animal.DOG.makeSound();
        ElementClass.Animal.CAT.makeSound();
    }
    
    
    public static abstract class Animal {
        public static Animal DOG = new Dog();
        public static Animal CAT = new Cat();
    
        public abstract void makeSound();
      }
    
    }
    
    // NOTE: Put in separate file if it needs to be accessible outside package. 
    final class Dog extends ElementClass.Animal {
    
        @Override
        public void makeSound() {
            System.out.println("WOOF!");
        }
    }
    
    final class Cat extends ElementClass.Animal {
        @Override
        public void makeSound() {
            System.out.println("MEOW!");
        }
    
    }
    
    这还避免了两种反模式:静态集合和可公开访问的集合


    您没有指定任何给定类别的元素都需要是可迭代的,因此我没有将其作为一项要求,只是您可以按照指定的方式处理它们

    问题是类初始化被推迟到第一次使用

    您可以以某种形式使用枚举类本身

    public class ElementClass {
    
        public static List<Class<Enum<?>>> enumClasses() {
            List<Class<Enum<?>>> clazzes = new ArrayList<>();
            Collections.addAll(clazzes,
                Animals.class, Plants.class, Buildings.class);
            return clazzes;
        }
    
    公共类元素类{
    公共静态列表>>clazzes=newArrayList();
    集合。添加所有(分类,
    动物类、植物类、建筑物类);
    回击;
    }
    
    手动添加每个类似乎是一个很小的开销

    然后:

    for (Class<Enum<?>> clazz : ElementClass.enumClasses()) {
         // Getting a single value:
         Object dog = Enum.valueOf(clazz, "DOG");
    
         // Getting all values:
         Object[] all = clazz.getEnumConstants();
    }
    

    for(classe)在代码中的某个点上向我们展示了该代码。您如何对enum进行子类化?我认为这在Java中是不可能的。
    
    for (Class<Enum<?>> clazz : ElementClass.enumClasses()) {
         // Getting a single value:
         Object dog = Enum.valueOf(clazz, "DOG");
    
         // Getting all values:
         Object[] all = clazz.getEnumConstants();
    }