【问题标题】:Java enum fields serialization/deserializationJava枚举字段序列化/反序列化
【发布时间】:2014-08-10 02:03:17
【问题描述】:

简介

我在我的 Java 项目中使用Apache Storm(本地模式,而不是远程模式),在创建拓扑时我需要将一个对象传递给其中一个螺栓

TopologyBuilder builder = new TopologyBuilder();
.....
builder.setBolt("last-bolt", new MyBolt(Classifier.SECONDS)).someGrouping(...);
.....
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("test", conf, builder.createTopology());

对象本身有一些不可序列化的字段。我没有对这些字段所属的类进行子类化并使它们可序列化,而是采用了另一种方法。由于实际对象不会发生太大变化并且可以枚举,因此我决定将其设为枚举并将其传递给 Bolt 的任务。 enum 的好处是它可以不惜一切代价进行序列化。这种方法在本地模式下有效,因为(如果我正确理解 Storm)我的计算机上只有一个 JVM 运行,实际上事情不会变得复杂。

问题

如果枚举由一个静态的最终不可序列化字段组成,那么当该枚举被不同机器上的另一个进程或运行多个 JVM 的集群上的另一个进程反序列化时,该字段是否会正确构造?

实际枚举静态final字段在末尾​​em>)

public enum Classifier {
    SECONDS {            
        public String classify(String timestamp) {
            DateTime dateTime = formatter.parseDateTime(timestamp);
            int second = dateTime.getSecondOfMinute();
            if (second <= 30) {
                return "00 - 30";
            } else {
                return "30 - 60";
            }
        }


        public int getNumberOfCategories() {
            return 2;
        }
    },

    WEEK {            
        public String classify(String timestamp) {
            DateTime dateTime = formatter.parseDateTime(timestamp);
            int dayOfWeek = dateTime.getDayOfWeek();
            String typeOfDay = (dayOfWeek >= 1 && dayOfWeek <= 5) ? "workday" : "weekend";
            int hour = dateTime.getHourOfDay();
            String hourInterval = hour + " - " + (hour == 23 ? 0 : hour + 1);
            return typeOfDay + " " + hourInterval;
        }


        public int getNumberOfCategories() {
            return 48;
        }
    };

    private static final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

    public abstract String classify(String timestamp);

    public abstract int getNumberOfCategories();
}

更多详情

DateTimeFormatter 和 DateTime 来自org.joda.time 包。

【问题讨论】:

    标签: java serialization static enums apache-storm


    【解决方案1】:

    所有static final 字段在加载类时初始化。无论使用何种序列化机制,它都会首先初始化静态字段并执行静态初始化块。请注意,静态字段不会反序列化,因为我们不是反序列化类而是对象(另请参阅此答案https://stackoverflow.com/a/6429497/1937263)。

    所以答案是肯定的,应该正确构造字段。

    【讨论】:

    • 对于enums,字段是否为static 都无关紧要。在enum 的特殊情况下,(De-)Serialization nothing 除了enum 的类型和常量的名称之外,根本没有(de) 序列化。
    • 如果枚举实例有一个带有一些参数的构造函数,是否在反序列化过程中再次调用它?
    • 枚举都是静态的,所以构造函数在类加​​载阶段只被调用一次。同样,它实际上并没有被反序列化——它被初始化了。 stackoverflow.com/a/19433954/1937263 - 我在这里或多或少地讲述了枚举背后的内容。
    猜你喜欢
    • 2018-07-31
    • 2013-08-24
    • 1970-01-01
    • 2013-09-01
    • 1970-01-01
    • 2021-11-30
    • 2019-05-31
    • 2015-07-26
    • 1970-01-01
    相关资源
    最近更新 更多