This became obvious, but if you ask me I don't know why I can use just String s = "ABC";
or Integer i = 1;
Why can we initialize String, Integer, and other by literal?
This became obvious, but if you ask me I don't know why I can use just String s = "ABC";
or Integer i = 1;
Why can we initialize String, Integer, and other by literal?
OK, because no one else has bit, I'll take a stab at it.
Why I can use just
String s = "ABC";
You can do this because "ABC"
is defined to be a String
literal by the language, and because the type of the literal is the right type to be assigned to a String
reference. To expand on this (apologies for the formatting):
The Java Language Specification, section 3.10 defines 6 different literals:
Where a StringLiteral is:
"
{StringCharacter} "
And StringCharacter is:
"
or \
And later on, in JLS section 3.10.5:
A string literal is a reference to an instance of class
String
.
So the assignment makes sense from a type-checking perspective, and because "ABC"
is defined to represent a String
object, while skipping the usual new <constructor>(...)
notation.
Strings were judged to be used so commonly in programming that the language designers chose to treat them specially in the language grammar. Java isn't the only language to do this -- you can see the same special treatment of String
literals in many other languages.
Integer i = 1;
Actually, you could only do this starting from Java 5, when autoboxing was introduced. The reason this works is because the compiler turns the literal assignment into a method call behind the scenes, thus allowing transparent translation from the primitive types to their wrappers. Thus, this code:
class A {
Integer i = 1;
int i2 = i;
}
Gets processed to this code before compilation to bytecode:
class A {
A() {
super();
}
Integer i = Integer.valueOf(1);
int i2 = i.intValue();
}
You can verify this by passing the -XD-printflat
flag to javac
before compiling. You have to also use the -d <path>
flag to specify an output path. This shows what the compiler processes your source code to immediately before it turns your Java source code into Java bytecode. So this shows the result of autoboxing, generic erasure, etc.
Those method calls you see are the reason you can "initialize Integer
by literal". You technically aren't doing so, because the initialization gets compiled to a method call, but autoboxing gives the illusion that the literal initialization is taking place. If you were to try this using a pre-Java 5 compiler, you'd get an error. You can test this by running this command:
javac -source 1.4 A.java
On my computer, this gives the following output (minus some irrelevant warnings):
A.java:2: error: incompatible types: int cannot be converted to Integer
Integer i = 1;
^
A.java:3: error: incompatible types: Integer cannot be converted to int
int i2 = i;
^
2 errors