1

For a little code , willing to save some Boxing/Unboxing hassle introduced because I further have to use an int constant as an Integer (mandated by Generics method call), I went from this simplified example

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;
    }
}

to this

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;
    }
}

No such a big deal.

As I said I went this way because a helper method relaying on 'width'. This method (which will be called very often) needed some generic type parameters (no primitive allowed), so there came the need for introducing Integer.

Well seems obvious to my eyes that the TYPEnnn_ORD where still constant, and still compile-time-constant but that's not the point of view of the java compiler : "constant expression required" is the error.

Just wanted to know why in this simple case ? It has to do with the boxing, but how and why ?

Meanwhile ,I just went back to the primitive int, hoping moderns jdk like Jdk 8 and Jdk 9 won't waste so much effort in boxing/unboxing.

By the way, as a subsidiary, you know how java competes on this point nowadays ? Is this something we should still minimize ?

  • 1
    The error message is pretty self-explanatory: you didn't provide a [constant expression](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28). To your eyes it may be obviously constant, but according to the JLS it obviously isn't. (And rightly so, if the value of `width` was more than `48`, the autoboxing operation would give you a different `Integer` instance every time you box `width*3` – biziclop Apr 07 '17 at 13:36
  • I don't get it, What's the point about 48*3 (= 144) ? Could you be a little more explicit please... – Henoc TheDev Apr 07 '17 at 14:10
  • Sorry, it should be `43`. The point is that autoboxing is only guaranteed to return an interned instance up until `127`, beyond that you will (probably) get a different instance of `Integer` every time a value is boxed. – biziclop Apr 07 '17 at 14:14
  • Thanks for this clarification. it all makes sense now. and my comment on @markbernard's answer is irrelevant as it is the JLS specification statement which prevails. Think I should read it one day ;-) – Henoc TheDev Apr 07 '17 at 14:20

1 Answers1

1

Auto-unboxing works by calling the appropriate method in the background. Integer.intValue() in your case. You cannot call a method in the case statement it must be a primitive value to check.

markbernard
  • 1,412
  • 9
  • 18
  • Crystal clear ! Accepted answer. But I'm puzzled that (as long as boxing primitives int to Integer , or long is so basic, so many times mandatory, how is it that the compiler just refuse to assume that if my Integer is a constant, so is it's intValue ? at least in case of Long or Integer It got that information . – Henoc TheDev Apr 07 '17 at 14:15
  • The compiler doesn't know the value that is in the Integer object like it does with a primitive int. With a primitive it can make a direct replacement from a declared constant. All the compiler does is call the method for unboxing. Since method calls are not allowed it can't allow unboxing. – markbernard Apr 07 '17 at 17:30
  • oups, I forgot. Sorry for the delay. Thanks – Henoc TheDev Apr 11 '17 at 13:09