Сериализация/десериализация полей перечисления Java

Введение

Я использую Apache Storm (локальный, а не удаленный режим) в своем проекте Java и при создании топологии Мне нужно передать объект одному из болтов

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

Сам объект имеет несколько несериализуемых полей. Вместо того, чтобы создавать подклассы классов, которым принадлежат эти поля, и делать их сериализуемыми, я выбрал другой подход. Поскольку фактический объект не будет сильно меняться и его можно перечислить, я решил сделать его перечислением и передать его таким образом задачам болта. Преимущество перечисления в том, что его можно сериализовать любой ценой. Этот подход работает в локальном режиме, потому что (если я правильно понял Storm) на моем компьютере работает только одна JVM, и на самом деле все не может быть сложным.

Вопрос

Если перечисление состоит из статического конечного несериализуемого поля, будет ли это поле построено правильно, когда перечисление десериализуется другим процессом на другом компьютере или в кластере, на котором запущено несколько JVM?

Фактическое перечисление (статическое конечное поле находится в конце)

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.


person filip    schedule 19.06.2014    source источник


Ответы (1)


Все поля static final инициализируются при загрузке класса. Какой бы механизм сериализации ни использовался, он сначала инициализирует статические поля и выполняет статические блоки инициализации. Обратите внимание, что статические поля не десериализуются, потому что мы десериализуем не классы, а объекты (см. также этот ответ https://stackoverflow.com/a/6429497/1937263).

Так что да, поле должно быть построено правильно.

person macias    schedule 19.06.2014
comment
Для enums даже не имеет значения, являются ли поля static. В частном случае enum (де-)сериализации ничего вообще (де)сериализуется, кроме типа enum и имени константы. - person Holger; 19.06.2014
comment
Если экземпляры enum имеют конструктор с некоторыми аргументами, вызывается ли он снова во время десериализации? - person filip; 20.06.2014
comment
Все перечисления являются статическими, поэтому конструктор вызывается только один раз на этапе загрузки класса. Опять же, на самом деле он не десериализован — он инициализирован. stackoverflow.com/a/19433954/1937263 - здесь я рассказывал о том, что более или менее стоит за перечислением. - person macias; 20.06.2014