постоянное выражение, необходимое для изменения поведения Java для int и Integer

Для небольшого кода, желающего сэкономить некоторые проблемы с боксом / распаковкой, введенные, потому что мне также нужно использовать константу int в качестве целого числа (требуемый вызовом метода Generics), я пошел от этого упрощенного примера

enum SOQ {
    TYPEA,
    TYPEB,
    TYPEC;
    public static final int width = 10;

    public static SOQ of(int i) {
        switch (i) {
            case UIOrdinals.TYPEA_ORD:
                return TYPEA;
            case UIOrdinals.TYPEB_ORD:
                return TYPEB;
            case UIOrdinals.TYPEC_ORD:
                return TYPEC;
        }
        throw new UnsupportedOperationException("Not supported yet."); //TODO : implement
    }

    public static class UIOrdinals {

        public static final int TYPEA_ORD = width * 1;
        public static final int TYPEB_ORD = width * 2;
        public static final int TYPEC_ORD = width * 3;
    }
}

к этому

enum SOQBOX {
    TYPEA,
    TYPEB,
    TYPEC;
    public static final Integer width = 10;

    public static SOQBOX of(int i) {
        switch (i) {
            case UIBoxOrdinals.TYPEA_ORD:
                return TYPEA;
            case UIBoxOrdinals.TYPEB_ORD:
                return TYPEB;
            case UIBoxOrdinals.TYPEC_ORD:
                return TYPEC;
        }
        throw new UnsupportedOperationException("Not supported yet."); //TODO : implement
    }

    public static class UIBoxOrdinals {

        public static final Integer TYPEA_ORD = width * 1;
        public static final Integer TYPEB_ORD = width * 2;
        public static final Integer TYPEC_ORD = width * 3;
    }
}

Нет ничего страшного.

Как я уже сказал, я пошел по этому пути, потому что вспомогательный метод передает «ширину». Этот метод (который будет вызываться очень часто) требовал некоторых параметров универсального типа (примитивы не допускались), поэтому возникла необходимость во введении Integer.

Что ж, мне кажется очевидным, что TYPEnnn_ORD все еще константа и все еще константа времени компиляции, но это не точка зрения компилятора java: «требуется постоянное выражение» - это ошибка.

Просто хотел знать, почему в этом простом случае? Это связано с боксом, но как и почему?

Между тем, я просто вернулся к примитивному int, надеясь, что современные jdk, такие как Jdk 8 и Jdk 9, не потратят столько усилий на упаковку / распаковку.

Кстати, как дочерняя компания, вы знаете, как сейчас конкурирует Java в этом вопросе? Нужно ли это минимизировать?


person Henoc TheDev    schedule 07.04.2017    source источник
comment
Сообщение об ошибке говорит само за себя: вы не предоставили постоянное выражение. На ваш взгляд, это может быть очевидно постоянным, но, согласно JLS, это явно не так. (И правильно, если бы значение width было больше, чем 48, операция автобокса выдавала бы вам другой Integer экземпляр каждый раз, когда вы устанавливаете width*3   -  person biziclop    schedule 07.04.2017
comment
Я не понимаю, какой смысл в 48 * 3 (= 144)? Не могли бы вы быть более откровенными, пожалуйста ...   -  person Henoc TheDev    schedule 07.04.2017
comment
Извините, это должно быть 43. Дело в том, что автобокс гарантированно возвращает интернированный экземпляр только до 127, кроме того, вы (вероятно) будете получать другой экземпляр Integer каждый раз, когда значение помещается в коробку.   -  person biziclop    schedule 07.04.2017
comment
Спасибо за это разъяснение. Все это имеет смысл сейчас. и мой комментарий к ответу @ markbernard не имеет значения, поскольку преобладает инструкция спецификации JLS. Думаю, однажды мне стоит это прочитать ;-)   -  person Henoc TheDev    schedule 07.04.2017


Ответы (1)


Автоматическая распаковка работает путем вызова соответствующего метода в фоновом режиме. Integer.intValue() в вашем случае. Вы не можете вызвать метод в операторе case, это должно быть примитивное значение для проверки.

person markbernard    schedule 07.04.2017
comment
Кристально чистый ! Принял ответ. Но меня озадачивает то, что (пока примитивы бокса int в Integer или long настолько просты, так часто обязательны, как получается, что компилятор просто отказывается предполагать, что если мое Integer является константой, то это intValue? по крайней мере, в случае Long или Integer. Он получил эту информацию. - person Henoc TheDev; 07.04.2017
comment
Компилятор не знает значение, которое находится в объекте Integer, как это происходит с примитивом int. С помощью примитива он может произвести прямую замену объявленной константы. Все, что делает компилятор, это вызывает метод распаковки. Поскольку вызовы методов не разрешены, распаковка невозможна. - person markbernard; 07.04.2017
comment
упс, я забыл. Извините за задержку. Спасибо - person Henoc TheDev; 11.04.2017