Implicit cast to string - toString and int + "" - java

Why when i use this:
int a = 1;
methodWithParamString(a + "");
a is cast to String, bu i can't use toString() on integer?
int a = 1;
methodWithParamString(a.toString());
Doesn't this: a+"" works like: a.toString() + "" ?

No, it works like String.valueOf( a ) + "", which in turn behaves like new StringBuilder( String.valueOf( a ) ).append( "" ).toString().
The important thing to know is that it's all just done by the compiler, in other words it's syntactic sugar. This is why adding strings together in a loop isn't a good idea for example. (Although modern VMs might have some mechanism to reduce the performance overhead.)

a is cast to String
No. It is converted to a String. (You can't cast a primitive type to a String, either implicitly or explicitly.)
The details of this conversion are specified in the JLS - 15.18.1.1. The specification states that for a primitive type, the conversion is done "as if" you created an instance of appropriate wrapper type and then called toString() on it. This leaves the Java compiler the option of using other approaches provided that the end result is the same. (For reference types, the conversion turns null into "null" and other non-String types into String by calling toString().)
The JLS states that the concatenation is then performed "as if" by a call to String.concat(...), noting that the JLS explicitly permits optimization of sequences of concatenations. (JLS 15.18.1.2)

Doesn't this: a+"" works like: a.toString() + "" ?
True. it doesn't.
+ is overloaded internally. and Java doesn't support method calls on primitives.

The way this is accomplished in Java is actually a bit simpler than the other answers seem to suggest.
Using the string concatenation operator with a String and an object results in a call to that object's toString() method, then performs string concatenation.
Remember that whenever a primitive is passed to a context where an Object would be valid, Java performs "autoboxing", converting an int to an Integer, a double to a Double, etc.
So you can think of it as autoboxing followed by toString() followed by string concatenation.
At the same time, you should realize that the JLS string concatenation spec allows JVM implementations to optimize away the autoboxing, provided the result is the same, so your JVM may instead use a StringBuilder, or use any other valid JVM bytecode to create the resulting string, so the performance of the string concatenation operator is often better than performing boxing yourself would be.

Because int a - is not an object, it is primitive type.
So it doesn't have any methods.
You should use boxing:
Integer objectA = new Integer(a);
objectA.toString();

toString() is a method in Object class, any class that inherits from it will have that method, like Integer or String. But int is a primitive type not an Object, so the method does not exist.

No.int is a primitive type so it's not an object and can't have any methods.
Read this I think it will be helpful. There are wrapper classes for primitives for example Integer for int. You can call toString() method for them.
Actually String is a special class in java. And you can use + (and not only) operator for Strings and primitives. I think you'll find full answer to your question here.

Related

Java type casting. Logic behind (String), .toString() and "" + int

Java is a strongly typed language. Hence, less bugs in compiled code and better readability at a cost of slower coding. Hence, explicit type casting is required, this part is clear.
What is the difference between these snippets:
(String)myInt // obviously doesn't compile
Integer.toString(myInt)
"" + myInt
Is it purely for historical reasons, or there is some meaning behind it?
Which method is appropriate?
As was mentioned before, (String) myInt is a typecast. In Java, we can either cast within primitives or upwards in the object-hierarchy. Since int is a primitive and String is an object, we have a problem. Even Autoboxing cannot resolve this dilemma since Integer and String do not stand in an inheritance-relationship. Therefore, it is perfectly plausible for (String) myInt to result in a compilation error.
The semantics of Integer.toString(myInt) and "" + myInt are identical. The specifics, however, are different.
When executing Integer.toString(myInt), a new String is constructed, containing a String-representation of myInt.
When executing "" + myInt, Java first constructs a global String-constant, having the value "" (this is done by the JVM, we do not see this 1). The lexer demands a String on the right side of + since it found a String on the left side of +. For primitives, the JVM "knows" how to convert them into Strings. For objects, toString() is called. Since Object has this method and each class is (at least implicitly) derived from Object, each object is guaranteed to have a toString() method. This is the second String constructed. Since Strings are immutable, the JVM might create a third String, representing the concatenation of the first two Strings2.
Epilogue
And then, at execution time, the JIT-compiler strikes and most of this might be irrelevant since the JIT-optimized versions of both variants may look equal. Or not. Or maybe only sometimes. JIT does funny stuff. So in the end it is more a question of personal style than performance :)
1 This is actually a lie. When writing
String s1 = "";
String s2 = "";
System.out.println(s1 == s2);
one will observe that the result is true, whereas false is expected. This is due to the fact that the JVM creates a pool for all String constants to save some memory.
2 It is well possible that the JVM "recognizes" that something + "" == "" + something == something and therefore does not create this third String. I did neither test nor research this.
I tend to prefer String.valueOf(int), myself, but yes there are multiple paths to get there.
In general, if you're converting the int to a String in isolation, you want Integer.toString(int), String.valueOf(int), or similar.
Your "" + myInt will be markedly less efficient than the above (though it usually doesn't matter): It compiles to creating a new StringBuilder, then appending "" to it, then appending the int to it (which calls one of the methods above to convert it to a string first), and then getting the String from the StringBuilder. So while you might do it as part of an overall concatenation operation, on its own it's pretty poor.
Your (String) example doesn't work: You can't just cast an int to a String, you'll get a compile-time "incompatible types" error.
It's a language feature that "officially" overloads the + operator such that
"" + myInt
is compiled as if it were:
new StringBuilder().append("").append(myInt).toString();
and StringBuilder#append() (ultimately) calls String.valueOf() to render myInt.
This feature was done presumably because if they didn't, no one would use the language - it would just be too painful.
First of all, lets compare (String)val and val.toString().
The key difference in those two statements is that casting is made by compiler while toString() method is usually implemented by programmer. That said, you can cast only if value extends String and you can implement toString() of any class. toString() works just like any other method and nothing(almost) special about it.
Now let's take a look at ""+int. I personally consider this as anti-pattern, because it's compiled in to wildly unefficient code. A lot of useless objects being created; in short: the result is similiar with manually concatenating few string literals with StringBuilder. Also, in statements like ""+var var does not extends String, toString() implicitly called.
I hope this was clear.
(String) - this works only on strings, so if you have this:
Object test = "test";
String test2 = (String) test;
It will work (since Object test will be of String type).
If you have something like this:
Integer test = new Integer(2);
String test2 = (String) test;
You get ClassCastException.
Integer.toString(myInt)
This is what it does:
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
return new String(0, size, buf);
}
It just turns your number to string char by char.
"" + myInt
This will tell compiler that you want to join things as string, not add two numbers (since string is first, it will go with joining strings). myInt will be turn into the string, or if it is an object, it will call toString() method from it.
Also, make sure you read about String pool in JVM, to know what it will do here. In situations like this it can end up creating a lot of temporary strings (if you have a lot of +; avoid that by using StringBuilder).

Operator definition in java

int i = 10;
i++; // it ok primitive value can use ++.
Integer integer = 10;
integer++; // how it can use ++
MyClass myClass = new MyClass();
myClass++; // then why myclass can't use ++.
C++ has the ability to overload operators. The Java language considers this to be open to too much abuse (overloaded operators can be obfuscating) so it was never incorporated into Java.
Therefore, you can't write myClass++ as the syntax is not available to specify that operation.
But ++ does work on a selection of non-primitives. The mechanism exploited is called autoboxing. (Essentially the underlying plain-old-data type is extracted from the boxed type, incremented then re-boxed to the original reference type).
Somewhat related to this is the ability to apply += and + to java.lang.String instances. Simply put, this is a special case. Although fully aware of the risk of downvotes I regard this as one of the worst kludges in Java, particularly += which will create a new instance of a string (as strings themselves are immutable), and many Java programmers will be unaware of the effect this has on memory.
It is because of Java's autoboxing feature which is added in Java 1.5
The compiler will convert the statment as follow
Integer integer = 10;
integer.iniValue++;
You can try to add the compiler flag "javac -source 1.4" and it will return an error
From the Link provided in a comment by Konstantin V. Salikhov,
Integer has a defined method to return an int, which then has the ++ operator defined.
MyClass has no ++ operator, hence myClass++; is invalid
The method in question goes like:
Integer myInteger = 10;
myInteger.intValue++;
Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes.
Operator overloading in Java has a description (as to it being not allowed) at Operator overloading in Java

Java Integer vs. String Autoboxing Design

In Java, I can do the following to succinctly guard against a NullPointerException:
if ("myString".equals(someOtherString))
But I cannot do the same with Integers, e.g.
if (5.equals(someOtherInteger))
I get a compile-time error. Any ideas on why this design decision was made? Or any resources that might explain it? Thanks in advance.
EDIT: someOtherInteger is an Integer, not an int.
String has always been an object in Java. There is no autoboxing for strings, and there can't be in principle. Autoboxing from the primitive int to the Integer object has been introduced fairly recently.
It is valid to ask why trying to access member variables of primitives doesn't invoke autoboxing (95.toString(radix) would actually be pretty convenient), but I imagine that the reason is that it wasn't considered a likely use-case, since since almost every wrappedPrimitive.method() has an equivalent WrapperClass.method( primitive ) version.
equals() is usually unnecessary for primitive types since == is already there. However, you do make a good case for it as a null-guard... 5 == integerInstance will try to unbox the instance, and throw a NullPointerException if the instance is null, unfortunately. (I didn't fully appreciate your point at first.)
That said, it would be really cool if we could hear from someone working on Java either currently or at the introduction of autoboxing about whether they considered this sort of functionality.
The JLS specifies that boxing conversions can only occur during assignment conversions, method invocation conversions, or casting conversions. Since you are neither assigning 5 to a variable, passing it as an argument to a method, nor explicitly casting it to Integer, it will not be autoboxed for you.
Assignment conversion (§5.2, §15.26) converts the type of an
expression to the type of a specified variable.
Assignment conversion may cause an OutOfMemoryError (as a result of
boxing conversion (§5.1.7)), a NullPointerException (as a result of
unboxing conversion (§5.1.8)), or a ClassCastException (as a result of
an unchecked conversion (§5.1.9)) to be thrown at run-time.
Method invocation conversion (§5.3, §15.9, §15.12) is applied to each
argument in a method or constructor invocation and, except in one
case, performs the same conversions that assignment conversion does.
Method invocation conversion may cause an OutOfMemoryError (as a
result of boxing conversion (§5.1.7)), a NullPointerException (as a
result of unboxing conversion (§5.1.8)), or a ClassCastException (as a
result of an unchecked conversion (§5.1.9)) to be thrown at run-time.
Casting contexts allow the use of one of:
...
a boxing conversion (§5.1.7) optionally followed by a widening
reference conversion (§5.1.5)
you can use
if (someOtherInteger!=null && someOtherInteger == 5)
I suspect that autoboxing is not implemented for the literal 5, whereas it is for a string myString, as a safety measure. It's safe to autobox a syntactic structure that is prepended and appended with double quotation marks "", because it's unlikely that the quotation marks are unintended, so the user's intention is clear and type-safety is not compromised.
However, the literal 5 could be a typo on the user's part - or it could be intended to be a string, rather than an integer. Therefore, to maintain the benefit that variables must be declared before use in object-oriented programming in order to prevent typos (among many other advantages) (even if it's implicit, as in the case of autoboxing), 5 is not autoboxed.
Here is a bit of reading on the different comparisons:
http://www.leepoint.net/notes-java/data/expressions/22compareobjects.html
Not sure if it was a built in design to reject int
If you do
Integer s=5;
Integer d=5;
if(d.equals(s)){
System.out.println("Fun");
}
It works just fine.
int is a primitive type it doesn't support any methods itself. To compare 2 ints you simply use the == convention as in:
if(a == b)
There is an Integer class that is a wrapper for an int that supports some other method calls
Edit:
Based on your edit you want to compare to Integer but the problem is the literal 5 isn't an Integer you have to create a new integer for it.
Integer myInt = 5;
if(myInt.equals(someOtherInteger)) ...
This design is inherent in the fact that primitives don't have any methods. As to whether primitives should support methods (or simply not exist) is integral to the debate as to whether Java is a Pure Object Oriented Language or not (many say no due to the fact that primitives exist).

auto boxing and boxing of wrapper classes

in wrapper classes we have two types of methods parseXxx() and valueOf() in every wrapper class for interconversion between primitive and wrapper objects.recently java 1.5 introduced auto boxing and boxing.so why they didn't deprecate those methods.
Because Autoboxing and Auto Unboxing are just compile time features. Try writing something like this in your source file and then have a look at the decompiled code:
Integer i = 10;
Decompiled code:
Integer i = Integer.valueOf(10);
Similarly,
int i = new Integer(100);
will give you the below when decompiled:
int i = (new Integer(100)).intValue();
Thus, the JVM still heavily relies on these methods at runtime, though it's masked when you write the code.
Well, parseXxx() is entirely unlike boxing; it turns a String into a primitive object. valueOf(), on the other hand, is actually used in boxing -- it either constructs a new wrapper object, or it fetches an existing one from a cache, depending on the value. The Java compiler generates a call to valueOf(), and that's precisely what boxing means.
1. There can be value sometimes in explicitly stating some conversion (for the clarity of e.g. some unobvious/obscure case).
2. Wouldn't that deprecation result in old programs becoming excessively littered with deprecation warnings?
As the command line arguments are treated as String Array, but given the condition when you are expecting command line argument other than String datatype(that may be primitives) i.e. boolean, int, byte, short, long, float, double, char than you need to parse the argument into the one what your program expects and here you use parseXXX() methods, to be precise parseXXX method take String argument and return the appropriate data type which you are trying to parse into.

Android: Cannot invoke toString() on the primitive type int

If I try
nltxt = nllen.toString();
with nllen being
int nllen = nl.getLength();
I get the error
Cannot invoke toString() on the primitive type int.
I want to convert the int to string so i can display the number of entries with Log...
Why doesn't it work?
Primitives do not have any fields or methods. Sometimes the compiler will "autobox" your primitive into the corresponding class, Integer in this case. Perhaps that is what you expected in this case. Sometimes the compiler will not do this. In this case it does not automatically autobox it.
You have a few alternatives:
String.valueOf(nltxt)
"" + nltxt (or if you have something useful to write along with the number, do "nltxt equals " + nltxt
Do the "autoboxing" manually: new Integer(nltxt).toString().
Format it in some custom way: String.format("nltxt is %d which is bad%n", nltxt)
Primitive types aren't objects and as such don't have any methods.
To convert it to a String use String.valueOf(nlTxt).
You could also use Integer.toString(nllen); for this.

Categories

Resources