54

I can create a literal long by appending an L to the value; why can't I create a literal short or byte in some similar way? Why do I need to use an int literal with a cast?

And if the answer is "Because there was no short literal in C", then why are there no short literals in C?

This doesn't actually affect my life in any meaningful way; it's easy enough to write (short) 0 instead of 0S or something. But the inconsistency makes me curious; it's one of those things that bother you when you're up late at night. Someone at some point made a design decision to make it possible to enter literals for some of the primitive types, but not for all of them. Why?

Will Wagner
  • 4,128
  • 3
  • 22
  • 14

4 Answers4

15

In C, int at least was meant to have the "natural" word size of the CPU and long was probably meant to be the "larger natural" word size (not sure in that last part, but it would also explain why int and long have the same size on x86).

Now, my guess is: for int and long, there's a natural representation that fits exactly into the machine's registers. On most CPUs however, the smaller types byte and short would have to be padded to an int anyway before being used. If that's the case, you can as well have a cast.

Julien Oster
  • 2,256
  • 16
  • 19
8

I suspect it's a case of "don't add anything to the language unless it really adds value" - and it was seen as adding sufficiently little value to not be worth it. As you've said, it's easy to get round, and frankly it's rarely necessary anyway (only for disambiguation).

The same is true in C#, and I've never particularly missed it in either language. What I do miss in Java is an unsigned byte type :)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 4
    yes, please add unsigned byte :( . for the issue at hand, i think it's worth to mention there is a long iteral because an int literal cannot represent all values of a long. But an int can represent all values of a short on the other hand. – Johannes Schaub - litb Nov 25 '08 at 16:04
  • But I think it does add value - not having to cast can be a big advantage. `short val = (short)(val + 10)` is just annoying although Java would have to also allow addition of `short`s for that to work. – mjaggard Apr 26 '13 at 09:34
  • @mjaggard: It's a matter of adding *sufficiently little value* to make it not worth it. It's slightly irksome, but far from the biggest problem... – Jon Skeet Apr 26 '13 at 10:39
4

Another reason might be that the JVM doesn't know about short and byte. All calculations and storing is done with ints, longs, floats and doubles inside the JVM.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 1
    Okay, but is that true of every JVM? And even if it is, should the language definition really be dependent on implementation details of the VM it runs on? Shouldn't that be the other way around? – Will Wagner Nov 25 '08 at 16:08
  • It's part of the JVM spec, so yes: the JVM has no way of knowing what type the value it handles really is. (Except for some operations such as array access, where separate opcodes exist). – Joachim Sauer Nov 25 '08 at 16:17
  • 5
    Storing *isn't* always done with ints etc. The obvious example is an array of bytes, which is certainly stored as an array of bytes rather than ints. See also http://stackoverflow.com/questions/229886/size-of-a-byte-in-memory-java – Jon Skeet Nov 25 '08 at 16:25
  • Right, arrays are a special case that *do* have per-type instructions (probably because byte[] that used 4 byte per entry would be a tiny bit too wasteful) – Joachim Sauer Nov 25 '08 at 22:38
  • 2
    "The JVM doesn't know about short and byte.": does this mean that when I declare a member variable to be of type byte or short it actually takes up as much as an int? – Giorgio Nov 27 '11 at 19:55
  • If JVM doesn't know about bytes, why `(int)(byte)100000001 == 1`? – kamczak May 19 '14 at 09:27
  • @kamczak: because the compiler (or "the Java language" if you want) has been designed to produce bytecode that produces that output. – Joachim Sauer May 19 '14 at 13:02
  • @kamczak Joachim is wrong. The JVM doesn't know about byte _constants_, but it does know about bytes. The JVM has 10 field types, and signed bytes are one of them. Bytes can be part of static method signatures, pushed on the stack, determine the types of arrays, converted to other data types, etc. The only real thing missing is byte constants. The major JVMs implement bytes using 32 bits, but that's an implementation detail: your example is part of the JVM's behavior, not something the compiler simulates through bytecode. Google for "JVM field descriptor" if you want more information. – Sarah G Aug 29 '14 at 10:28
  • @Giorgio: Yes, byte fields in OpenJDK, Oracle, and IBM JVMs occupy 4 bytes. It's a chicken-and-egg issue: nobody uses short fields because they save no space, and JVMs don't try to save space on short fields because nobody uses them. Array elements are different, of course. – Doradus Mar 29 '16 at 02:25
  • *"the JVM doesn't know about short and byte"* - Actually, it does now about them. Ref [JVMS 2.3](https://docs.oracle.com/javase/specs/jvms/se10/html/jvms-2.html#jvms-2.3) ... and opcodes like `i2b`, `baload` etcetera. You are correct that arithmetic etc are only done using 32 or 64 bit operations (bytecodes). But that is mandated by the Java spec rather than the JVM spec. – Stephen C Aug 15 '18 at 13:17
  • (Unfortunately, people are citing this Answer ...) – Stephen C Aug 15 '18 at 13:19
2

There are several things to consider.

1) As discussed above the JVM has no notion of byte or short types. Generally these types are not used in computation at the JVM level; so one can think there would be less use of these literals.

2) For initialization of byte and short variables, if the int expression is constant and in the allowed range of the type it is implicitly cast to the target type.

3) One can always cast the literal, ex (short)10