In Java, the type of a literal is fixed; the type of `0` is always `int`, regardless of context.
Of course, we would also want to use literal `0` in places where other numerical types are expected,
e.g. use `0` as byte or double. Java approaches that problem by performing type conversion.
In general, there is no problem to use an `int` as `long/float/double`;
widening primitive conversion is generally allowed and implicitly carried out.
On the other hand, narrowing primitive conversion ($5.1.3) is very limited; it's performed in
n1. explicit casting, e.g. `(byte)anInt`
n2. ++ and --, e.g. `aByte++` (increment is done on `int` level)
n3. += etc, e.g. `aByte+=anInt`
n4. when a constant value fits a narrower type, e.g. `byte b=0;`
Let's catalog the places where [n4] applies. It is mostly specified by
assignment conversion ($5.2) which other parts of JLS reference to.
c1. assignment
byte b = 0; // int `0` is converted to byte
c2. array initializer
byte[] bs = { 0, 1 };
c3. return
byte foo(){ return 0; }
(ByteSupplier)()->0
c4. switch-case
switch(aByte){ case 0: }
c5. annotation
@interface Foo
{
byte aByte() default 0;
byte[] aByteArray() default {0,1};
}
@Foo( aByte=2, aByteArray={3,4} )
c6. conditional expression
bool ? 0 : aByte
the type of this expression is `byte`, because constant `0` fits `byte`.
If we change `0` to `300`, the type of the expression becomes `int`.
These are all that I can find in JLS-8.
--
[c1-6] only apply for `byte/short/char/int`; they don't apply for `long` etc, for example
int i = 0L; // does not compile
[c1-6] apply for constant expressions, not just int literals. For example
byte b = 1 + 1; // ok; equivalent to `byte b=2`
This makes sense for simple expressions. If the constant expression becomes more complicated, it gets confusing
byte b = true ? 0 : 300; // ok
// the conditional expr is a constant expression that evaluates to an int `0`
// therefore the code is equivalent to
byte b = 0;
[c6] only applies if the constant expression is `int`. We don't need to dwell more on it,
the whole conditional expression spec is insane anyway.
---
What's apparently missing among [c1-6] is method invocation
void foo(byte b){}
foo(0); // error
here `0` is not implicitly converted to `byte`.
See end of $5.3 for justification (complication of method overload resolution).
Note also that in `aByte>0`, `0` is not narrowed to a byte; instead, `aByte` is widened to an int.