Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does automatic boxing work in eclipse but not in javac?

Tags:

java

eclipse

This code:

Integer ints[] = new Integer[]{'1', '2', '3'};

compiles just fine in eclipse, but javac (both version 1.6.0_27 and 1.7.0) gives the following error:

BoxTest.java:4: incompatible types
found   : char
required: java.lang.Integer
               Integer ints[] = new Integer[]{'1', '2', '3'};

BoxTest.java:4: incompatible types

Why?

I assume it's some kind of compiler flag, but digging trough eclipse to figure it out is not exactly straight forward.

like image 740
Nico Avatar asked Oct 27 '11 15:10

Nico


4 Answers

What javac is not doing, is not autoboxing, but is an automatic cast. In javac it compiles with:

Integer ints[] = new Integer[] { (int) '1', (int) '2', (int) '3' };

The same happens with just one Integer, again in javac, I've to do the explicit cast to compile:

Integer a = (int) '1';

But here is what I found. Using Eclipse JDT batch compiler from the command line it works, even without the casts:

$ java -jar org.eclipse.jdt.core_3.7.1.v_B76_R37x.jar -classpath rt.jar \
  -1.6 Appo.java 

I've looked at the options of javac and I don't think there is any way to change this behaviour.

I've to infer that the difference is caused by the fact that Eclipse is not using javac internally, but the JDT compiler.

like image 113
stivlo Avatar answered Oct 13 '22 12:10

stivlo


As already noted by stivlo the Eclipse JDT compiler silently treats the code like this:

Integer refI = Integer.valueOf((int)'a');

But the Java Language Specification says in chapter 5.2 (emphasis mine):

Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable. Assignment contexts allow the use of one of the following:

* an identity conversion (§5.1.1)
* a widening primitive conversion (§5.1.2)
* a widening reference conversion (§5.1.5)
* a boxing conversion (§5.1.7) optionally followed by a widening reference conversion
* an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

The (int) 'a' cast is the first conversion, the Integer.valueOf(int) is the second conversion. The javac compiler enforces the rules by allowing only one conversion.

So it seems, you have found a bug in the Eclipse JDT compiler.

like image 39
A.H. Avatar answered Oct 13 '22 11:10

A.H.


I found a lot of confusion on this thread on how Eclipse compiles Java code. Here's the deal - Eclipse uses its "own" JDT compiler, which has nothing to do with either Sun or Sun's(now Oracle's) javac compiler. It is an independently developed compiler, licensed under EPL, and follows the JLS, just as javac does. So whatever does/does not compile with javac, does/does not compile with Eclipse JDT.

That said, the problem reported here looks like a bug in the Eclipse compiler. https://bugs.eclipse.org/bugs/show_bug.cgi?id=362279

like image 38
Ayushman Avatar answered Oct 13 '22 11:10

Ayushman


Window -> Preference -> Compiler -> Errors/Warning -> Potential programming problems -> Boxing and unboxing conversions; set the value to Error

like image 29
manuzhang Avatar answered Oct 13 '22 12:10

manuzhang