int和Integer的Java行为更改中需要常量表达式

int和Integer的Java行为更改中需要常量表达式,java,autoboxing,compile-time-constant,Java,Autoboxing,Compile Time Constant,对于一段小代码,为了避免一些装箱/拆箱的麻烦,因为我还必须使用int常量作为整数(由泛型方法调用强制),我从这个简化的示例开始 enum SOQ { TYPEA, TYPEB, TYPEC; public static final int width = 10; public static SOQ of(int i) { switch (i) { case UIOrdinals.TYPEA_ORD:

对于一段小代码,为了避免一些装箱/拆箱的麻烦,因为我还必须使用int常量作为整数(由泛型方法调用强制),我从这个简化的示例开始

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\u ORD仍然是常量,编译时仍然是常量 但这不是java编译器的观点: “需要常量表达式”是错误

只是想知道为什么在这个简单的案例中?这和拳击有关,但如何以及为什么

同时,我又回到了原始的int,希望像jdk8和jdk9这样的现代jdk不会在装箱/拆箱方面浪费太多精力


顺便说一下,作为子公司,您知道java在这一点上是如何竞争的吗?这是我们仍然应该最小化的吗?

自动取消装箱通过在后台调用适当的方法来工作<代码>整数.intValue()在您的情况下。您不能在case语句中调用方法,它必须是要检查的基元值。

错误消息非常简单:您没有提供。在你看来,它显然是恒定的,但根据JLS,它显然不是。(正确地说,如果
width
的值大于
48
,则自动装箱操作将在每次装箱
width*3
时为您提供一个不同的
Integer
实例。我不明白,48*3(=144)有什么意义?请你再明确一点好吗?对不起,应该是
43
。问题是,自动装箱只保证返回一个在
127
之前的内部实例,超过这个范围,你(可能)会返回每次装箱一个值时,都会得到一个不同的
Integer
实例。感谢您的澄清。现在一切都有意义了。我对@markbernard答案的评论是不相关的,因为它是JLS规范声明。我想我应该有一天读它;-)非常清楚!接受答案。但我对此感到困惑(只要装箱原语int-to-Integer,或long是如此基本,那么很多次是强制性的,编译器怎么会拒绝假设如果我的整数是常量,那么它的intValue也是常量?至少在long或Integer的情况下,它得到了这些信息。编译器不知道Integer对象中的值,就像它使用pri一样mitive int。使用原语,它可以直接替换声明的常量。编译器所做的只是调用方法进行取消装箱。由于不允许方法调用,因此它不能允许取消装箱。我忘了。抱歉,耽搁了。谢谢