wen
wen

Reputation: 3848

Javac and Primitives: Boxed vs. Unboxed

My question is: why do primitive types have to be wrapped in an object, when it is also a possibility to have the compiler set things right for you?

  1. calls to a primitive value x's methods can be translated from x.call() to X.call(x) - this is what I try to illustrate below.
  2. generics aren't kept around at runtime (right?), so it isn't the case that you need to access class information at runtime - you could simply replace every instance of Integer by int and rewrite method calls as above, and end up with executable code.

So basically, what I'm asking is: what am I missing here?


I've been wondering about this for some time: Why can't the Java compiler translate...

int a = 482;
int b = 12;
System.out.println((a + b).toHexString());

...to the following code...

int a = 482;
int b = 12;
System.out.prinln(Ints.toHexString(a + b));

...and thus remove the entire need for boxing and unboxing?

(Thus, compile method calls to (static) function calls, and keep a single instance of Int.class around in case it's needed - e.g. after a call of Ints.getClass(_)?)


Comment added for clarity:

@Adam: No, I do not think it causes boxing/unboxing. The example attempts to illustrate how primitives could be treated as objects in the language, but as primitives by the compiler. This would remove the (slight) overhead in runtime, and a confusing thing in the language. Therefore the intended question was exactly: why didn't the extremely talented compiler developers pick this solution? Because if they didn't, there must be a clear impossibility that I'm not seeing. And I'd like to know what it is. – Pepijn

Upvotes: 1

Views: 2346

Answers (3)

Paŭlo Ebermann
Paŭlo Ebermann

Reputation: 74760

So, we could map methods called on primitive types to static methods of their wrapper types, fine.

This does not relate to boxing/unboxing at all, it is only syntactic sugar to write the same method call in another way - and only a quite small number of methods, these predefined in the wrapper classes.

Boxing is necessary when you want to treat a primitive value as an object, for example:

  • pass it to a method which only accepts objects
  • put it in a variable of object type
  • return it from a method which has to return objects

Special (but quite important) cases of these are:

  • put it into an object array
  • put it into a collection

Unboxing is necessary if we got such a boxed primitive and want to have the pure form of it, for example after calling a method which returns objects, or taking the value from a variable.

Before Java 5 (or 1.5), we had to do all this boxing and unboxing manually, by the .valueOf() method or toXXX(). Now it is done automatically whenever necessary (autoboxing).

Upvotes: 1

C. K. Young
C. K. Young

Reputation: 223043

I presume you meant Integer.toHexString, not Ints.toHexString. The latter is not part of java.lang and the compiler would have no way to know anything about it.

In theory, the compiler could translate calls of (a + b).toHexString() to Integer.toHexString(a + b), if the Java language specifies such a translation. (For example, auto-boxing of an int a to an Integer is specified to be Integer.valueOf(a).)

I guess the Java language maintainers decided that that is too "magical" for Java programmers---in all versions of Java, primitive types do not have methods or fields. Java, in general, is designed to avoid syntactic sugar---that is why it's generally more verbose than most other languages.

Upvotes: 3

JB Nizet
JB Nizet

Reputation: 691765

What would the compiler do for

List<Integer> list = new ArrayList<Integer>();
list.add(5);
int i = list.get(0);

You need an instance of Integer here, hence the need for boxing/unboxing.

Upvotes: 0

Related Questions