【问题标题】:Enum with other enum as type以其他枚举为类型的枚举
【发布时间】:2018-04-08 22:36:15
【问题描述】:

我想要一个像这样的枚举:

public enum Type {
    STRING, INTEGER, BOOLEAN, LIST(Type);

    Type t;

    Type() { this.t = this; )
    Type(Type t) { this.t = t; }

}

这样我就可以为LIST 输入各种Types,比如可以打电话给Type.LIST(STRING)。这在 Java 中可行吗?

【问题讨论】:

  • 不可能从枚举外部将数据传递给枚举定义的构造函数,但是,请说明您想如何使用它,以及您想要实现的目标,我/我们可以建议另一种选择。
  • @weston 我想创建一个 Map 来定义某些值的类型。我不想使用 Object,因为我不想实例化任何对象,尽量保持抽象,仅限于包含任何其他枚举的字符串、数字、布尔值、列表。
  • 你可以;只需让构造函数采用Type...,但我想你只能持有上面已经定义的Types LIST
  • @JacobG。是的,但这有两个问题。首先是我只能从枚举中调用Types,其次我只能定义一次LIST(X),所以当我定义LIST(STRING)时,我将无法定义LIST(INTEGER).
  • 那么,这对你有用吗? public enum Type { STRING, INTEGER, BOOLEAN, LIST_STRING, LIST_INTEGER, LIST_BOOLEAN 还是需要LIST(LIST(X))

标签: java generics parameters enums


【解决方案1】:

enums 是有限的,你不能有未知数量的条目。所以你不能将 LIST(LIST(LIST(LIST(...))) 作为单独的 Type 枚举。你需要一个类,但这并不意味着你必须实例化很多对象:

这可能是过早的优化,但您可以使用享元模式来确保您不能获得多个Type 的实例:

package com.example;

public final class Type {

    public enum LeafType {
        STRING,
        INTEGER,
        BOOLEAN
    }

    //Gives you the familiar enum syntax
    public static final Type STRING = new Type(LeafType.STRING);
    public static final Type INTEGER = new Type(LeafType.INTEGER);
    public static final Type BOOLEAN = new Type(LeafType.BOOLEAN);

    private final LeafType leafType;

    private final Type listType;
    private final Object lock = new Object();
    // This is the cache that prevents creation of multiple instances

    private Type listOfMeType;

    private Type(LeafType leafType) {
        if (leafType == null) throw new RuntimeException("X");
        this.leafType = leafType;
        listType = null;
    }

    private Type(Type type) {
        leafType = null;
        listType = type;
    }

    /**
     * Get the type that represents a list of this type
     */
    public Type list() {
        synchronized (lock) {
            if (listOfMeType == null) {
                listOfMeType = new Type(this);
            }
            return listOfMeType;
        }
    }

    public boolean isList() {
        return listType != null;
    }

    /**
     * If this type is a list, will return what type of list it is
     */
    public Type getListType() {
        if (!isList()) {
            throw new RuntimeException("Not a list");
        }
        return listType;
    }

    /**
     * If this type is a leaf, will return what type of leaf it is
     */
    public LeafType getLeafType() {
        if (isList()) {
            throw new RuntimeException("Not a leaf");
        }
        return leafType;
    }

    @Override
    public String toString() {
        if (isList()) {
            return "LIST(" + getListType() + ")";
        }
        return getLeafType().toString();
    }
}

用法:

简单类型:

Type string = Type.STRING;

列表:

Type stringList = Type.STRING.list();

列表列表:

Type stringListList = Type.STRING.list().list();

而且你永远不会遇到这样的情况:你有两个描述相同类型的 Type 实例,例如:

Type t1 = Type.BOOLEAN.list().list().list();
Type t2 = Type.BOOLEAN.list().list().list();

System.out.println(t1 == t2 ? "Same instance" : "Not same instance");

我添加了toString进行调试:

Type listListListInt = Type.INTEGER.list().list().list();
System.out.println(listListListInt);

给予:

LIST(LIST(LIST(INTEGER)))

【讨论】:

  • 我已经修复了一些我在制作 toString 时发现的初始错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-16
  • 2020-05-17
  • 1970-01-01
  • 2010-10-11
  • 2014-02-13
相关资源
最近更新 更多