views:

1513

answers:

13

I want to convert a primitive to a string, and I tried:

myInt.toString();

This fails with the error:

int cannot be dereferenced

Now, I get that primitives are not reference types (ie, not an Object) and so cannot have methods. However, Java 5 introduced autoboxing and unboxing (a la C#... which I never liked in C#, but that's beside the point). So with autoboxing, I would expect the above to convert myInt to an Integer and then call toString() on that.

Furthermore, I believe C# allows such a call, unless I remember incorrectly. Is this just an unfortunate shortcoming of Java's autoboxing/unboxing specification, or is there a good reason for this?

+22  A: 

Java autoboxing/unboxing doesn't go to the extent to allow you to dereference a primitive, so your compiler prevents it. Your compiler still knows myInt as a primitive. There's a paper about this issue at jcp.org.

Autoboxing is mainly useful during assignment or parameter passing -- allowing you to pass a primitive as an object (or vice versa), or assign a primitive to an object (or vice versa).

So unfortunately, you would have to do it like this: (kudos Patrick, I switched to your way)


   Integer.toString(myInt);
Justin Standard
+20  A: 

Ditto on what Justin said, but you should do this instead:

Integer.toString(myInt);

It saves an allocation or two and is more readable.

Patrick
A: 

@Justin Standard

Interesting, I always had assumed autoboxing occurred purely at compile time since the compiler should have all the information to do it there. Regardless, it seems like a shortcoming of the specification to me... I see no reason why Java should box it in one case, and not in another.

And FYI, for my situation I was able to just change the method parameters to make it work... since the primitives were being passed in, I could just use the boxed types as the parameters, problem solved.

Mike Stone
The autoboxing does occur at compile time, so your confusion is justified. It seems like what you're asking for is reasonable.
erickson
+2  A: 

seems like a shortcoming of the specification to me

There are more shortcomings and this is a subtle topic. Check this out:

public class methodOverloading{
public static void hello(Integer x){
System.out.println("Integer");
}

public static void hello(long x){
System.out.println("long");
}

public static void main(String[] args){
int i = 5;
hello(i);
}
}

Here "long" would be printed (haven't checked it myself), because the compiler choses widening over autoboxing. Be careful when using autoboxing or don't use it at all!

david
+1  A: 

This should work

myInt+""
Thej
Not as clear as the two top answers :)
willcodejavaforfood
A: 

@david: Yeah, that's one of the reasons I disliked autoboxing in C#... ambiguous situations like that which the compiler doesn't throw an error about. I actually had a case once (don't remember the details, was a long time ago) where I was unknowingly calling a method with Object as the parameter, but I was passing an int. That to me should have been a compiler error... it might have been C#, I don't remember.

@Thejesh GN: I am aware of that option as well, but it's not as concise as myInt.toString() would be.

Mike Stone
A: 

@Thejesh GN

myInt+""

is a worse solution than

Integer.toString(myInt);

because it involves not only the conversion, but also a string concatenation, which is expensive and should therefore be avoided.

A: 

In addition to the toString() methods on the primitive wrapper classes, you can call String.valueOf() on any of the primitive types to get a String representation of the value.

+9  A: 

One other way to do it is to use:

String.valueOf(myInt);

This method is overloaded for every primitive type and Object. This way you don't even have to think about the type you're using. Implementations of the method will call the appropriate method of the given type for you, e.g. Integer.toString(myInt).

See http://java.sun.com/javase/6/docs/api/java/lang/String.html.

SaM
A: 

I personally just totally avoid auto(un)boxing, mainly because it makes it entirely too easy to forget to handle the null case when autounboxing. I'm all for reducing gruntwork, but autounboxing just makes it too easy to accidentally introduce a NullPointerException problem. So I just set Eclipse to consider any instance of auto(un)boxing a compiler warning.

Robert J. Walker
A: 

In C#, integers are neither reference types nor do they have to be boxed in order for ToString() to be called. They are considered objects in the Framework (as a ValueType, so they have value semantics), however. In the CLR, methods on primitives are called by "indirectly" loading them onto the stack (ldind).

Mark Cidade
+2  A: 

The valid syntax closest to your example is

((Integer) myInt).toString();

When the compiler finishes, that's equivalent to

Integer.valueOf(myInt).toString();

However, this doesn't perform as well as the conventional usage, String.valueOf(myInt), because, except in special cases, it creates a new Integer instance, then immediately throws it away, resulting in more unnecessary garbage. (A small range of integers are cached, and access by an array access.) Perhaps language designers wanted to discourage this usage for performance reasons.

Edit: I'd appreciate it if the downvoter(s) would comment about why this is not helpful.

erickson
I wish all down voters would comment on why something gets down voted. I always do unless it's obvious (like the answer is totally wrong or nonsense).
Jason Coco
Probably voted down by people that just read the code bits and thought your were advocating such code.
Kris
A: 

As everyone has pointed out, autoboxing lets you simplify some code, but you cannot pretend that primitives are complex types.

Also interesting: "autoboxing is a compiler-level hack" in Java. Autoboxing is basically a strange kludge added onto Java. Check out this post for more details about how strange it is.

Yar