constructorfactoryjava.lang.classjava

Java: Why does "Character newChar = 'c' " work if Character is a wrapper class? How come it doesn't need a constructor?


These are both fine for me:

Example 1:

Character newCharacter = 'c';

Example 2:

Character newCharacterOther = new Character('c');

But what are the differences?

In the first example, how does the Character class know to set its value to "c" without needing a constructor for that?

Does it use a factory method behind the scenes? Can someone please explain to me how the compiler knows what to do?

I have a provided an image of the constructor of the Character.class in java.lang.

It even says that it's deprecated and that it shouldn't be accessed like that, but I am still confused a bit.

Image showing the constructor of a java class


Solution

  • As described in the language spec:

    Assignment contexts allow the use of one of the following:

    • ...
    • a boxing conversion (§5.1.7)
    • ...

    Referring to section 5.1.7:

    Specifically, the following nine conversions are called the boxing conversions:

    • ...
    • From type char to type Character
    • ...

    At run time, boxing conversion proceeds as follows:

    • ...
    • If p is a value of type char, then boxing conversion converts p into a reference r of class and type Character, such that r.charValue() == p
    • ...

    So, your line is equivalent to:

    Character newCharacter = Character.valueOf('c');
    

    Indeed, if you decompile your class, you will see that's exactly what gets invoked.


    But what are the differences?

    new Anything is guaranteed to create a new instance of Anything (or fail with an exception). So, new Character('c') == new Character('c') is always false.

    On the other hand, Character.valueOf('c') == Character.valueOf('c') may be true, because there is no requirement for a method invocation to return a new instance. Indeed, it is guaranteed by specification that you won't get a new instance on these two invocations.

    This allows you to reuse existing instances, avoiding unnecessary allocations, thus saving memory.