JDK-5009476 : Compound assignments don't work well with Byte, Short
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0,6
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic,windows_xp
  • CPU: generic,x86
  • Submitted: 2004-03-08
  • Updated: 2014-10-03
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description

Name: rmT116609			Date: 03/08/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta-b32c)
Java HotSpot(TM) Client VM (build 1.5.0-beta-b32c, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
WindowsXP

A DESCRIPTION OF THE PROBLEM :
The following does not compile, while I belive it should.
Unfortunately the JSR does not say anything about compound assignments

	public static void main(String[] args) {
		Byte b = (byte)100;
		// *= /= %= += -= <<= >>= >>>= &= ^= |=
		b+=1; b-=1; b*=1; b/=1; b%=7; b<<=2; b>>=1; b>>>=1; b^=8; b|=2; b&=9;
	}

Writing "b++", however works just fine.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile:
	public static void main(String[] args) {
		Byte b = (byte)100;
		// *= /= %= += -= <<= >>= >>>= &= ^= |=
		b+=1; b-=1; b*=1; b/=1; b%=7; b<<=2; b>>=1; b>>>=1; b^=8; b|=2; b&=9;
	}


ERROR MESSAGES/STACK TRACES THAT OCCUR :
inconvertible types  //  found   : int  //  required: java.lang.Byte

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class Test {

	public static void main(String[] args) {
		Byte b = (byte)100;
		// *= /= %= += -= <<= >>= >>>= &= ^= |=
		b+=1; b-=1; b*=1; b/=1; b%=7; b<<=2; b>>=1; b>>>=1; b^=8; b|=2; b&=9;
	}
}
---------- END SOURCE ----------
(Incident Review ID: 242329) 
======================================================================

Comments
EVALUATION This issue reduces to the following: (1) byte b; b+=1; converts to byte b; b = (byte)(b+1); The type of (b+1) is int, due to binary numeric promotion. Casting conversion allows int->byte, a narrowing primitive conversion - this is a judgement call since it may lose information, but as a practical matter Java decided to support it. (Against the wishes of 4655168.) (2) Byte b; b+=1; converts to Byte b; b = (Byte)(b+1); Casting conversion does not allow int->Byte. There is a plan to improve casting conversion in various safe and useful ways (6526446), but a narrowing primitive+boxing combination (int->byte->Byte) is not among them because it's not safe. JSR 201 could have introduced such a combination, but didn't. It looks like the wrapper types are causing an inconsistency (int->byte works, int->Byte doesn't work) when in fact the refusal to cast int->Byte (or int->Short or int->Character) is actually consistent with the rest of Java. Namely, at an assignment, the RHS is usually not coerced to the LHS type, e.g. byte b = 0, b2 = b + 0 *fails*. (The assignment conversion context does NOT allow a narrowing primitive conversion.) Only in the special case of a numeric constant on the RHS does assignment conversion check if it can fit the RHS value in the LHS type. This special case is not relevant for compound assignment operators, since the RHS is not a numeric constant - it's an expression with a cast (by definition of compound assignment). The question is: do you think a compound assignment to a wrapper should behave like a compound assignment to a primitive, even if both may lose information? Alternatively: given that we already have information-losing compound assignments, should we allow more? Since this issue unquestionably creates developer confusion, I have some sympathy with aligning compound primitive and wrapper assignments by allowing int->Byte/Short/Character. We could do this by expanding casting conversion, since the definition of E1 op= E2 casts to the target type: E1=(T)(E1 op E2). But this is a global change. It is better if JLS 15.26 identifies the types of E1 and E2 when the op= definition should not do a cast, but do a narrowing primitive+boxing conversion instead. JLS 5.2 shows the way.
24-09-2007

EVALUATION It fails as a consequence of the current spec. If it is to be allowed, the spec will need to be adjusted. ###@###.### 2004-03-08 The spec and implementation stay as they are. ###@###.### 2004-06-04
08-03-2004