0

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?

Yoda
  • 17,363
  • 67
  • 204
  • 344
  • Yay! [That's Java!](http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html) – Narmer Jul 07 '14 at 10:04
  • What's an "opaque type"? `String`s are a special case, `Integer` is just autoboxing, what other types were you thinking of? – awksp Jul 07 '14 at 10:05
  • `To retain primitives in OOP.` full story here : [How String can be initialized using ""??](http://stackoverflow.com/a/17489410/1927832) – Suresh Atta Jul 07 '14 at 10:06
  • @user3580294 Sorry I translated directly form polish to english. – Yoda Jul 07 '14 at 10:07
  • @Yoda Ah, OK, that's understandable. The rest of my comment should address the examples you had in your question though. Should either be the special case of `String`s or autoboxing. – awksp Jul 07 '14 at 10:10
  • In short, you can do it because the language specification says you can, because it's convenient to do it. – Boann Jul 08 '14 at 06:32

1 Answers1

2

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:

  • IntegerLiteral
  • FloatingPointLiteral
  • BooleanLiteral
  • CharacterLiteral
  • StringLiteral
  • NullLiteral

Where a StringLiteral is:

  • " {StringCharacter} "

And StringCharacter is:

  • InputCharacter but not " or \
  • EscapeSequence

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
awksp
  • 11,764
  • 4
  • 37
  • 44