26

In Java we usually do:

Class myObject = new Class();

because the new keyword returns an address.

But why can we do this?:

String myString = "Hello";

as if String were a primitive?

I asked this to my teacher and he replied that it is because what is in quotes is equivalent to an address, but he is not sure. Can you confirm?

Is "Hello" stored in an instance variable of the class String?

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
AlessandroF
  • 542
  • 5
  • 16
  • 2
    Facetiously, it's because Java is kludged in this respect. Consider it an exception that the language makes. Cf C++ where there is no such special treatment extended to 'standard' objects. I'm glad you're asking such questions. Have an upvote! – Bathsheba Apr 02 '17 at 18:06
  • 2
    Not a duplicate per se, because the proposed duplicate is about c# –  Apr 02 '17 at 18:07
  • 1
    @Ousmane That's not a Java question – OneCricketeer Apr 02 '17 at 18:07
  • 18
    Note: "Has a literal form" != "is a primitive type" – Jon Skeet Apr 02 '17 at 18:08
  • Try to do this int i = null – bichito Apr 02 '17 at 18:32
  • 2
    “_Equivalent to an address_”! The concept of an address is more or less foreign to the Java Language Specification (SE 8 Edition): I only see it (in this sense) under **Semantics of `final` fields**. A string literal is simply an expression of type `String`, as pointed out (with a reference) in T.J. Crowder’s answer. – PJTraill Apr 03 '17 at 08:50

4 Answers4

16

...as if String were a primitive?

As Jon points out in a comment, "has a literal form" != "is a primitive type." :-) Strings have a literal form in Java because the spec defines one for them. String is still an object type.

Some languages have other object types that also have literal forms (JavaScript, for instance, has literal forms for regular expressions, arrays, and non-array objects [its literal form for strings does actually define what it calls a string primitive rather than string object — JavaScript has both primitive and object versions of strings]). I think strings are the only one in Java (other than null, which is the literal for "no object"), although of course there are array initializers, which are similar but not quite the same as literals.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Due to autoboxing, other literal forms may appear as evaluating to object instances as well: `Boolean b = true;` or `Number n = 42;`… – Holger Apr 03 '17 at 11:58
  • @Holger: The literal, though, results in a primitive; the boxing happens separately. (Which you know, but flagging it for lurkers.) – T.J. Crowder Apr 03 '17 at 12:00
  • 2
    Now that I had a second thought: **Class Literals**. Since Java 1.1, there are class literals. `Class> cl = Long.class;` These definitely qualify, even if the JLS authors forgot naming them in the [Literals section](https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10). They are there in [their own section](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.8.2)… – Holger Apr 03 '17 at 12:05
  • @Holger Good one. I don't know why those feel different to me than normal literals. They do, but I can't immediately think of a good reason... – T.J. Crowder Apr 03 '17 at 12:11
13

The fact that you can use a literal expression doesn't mean that the expression results in a primitive type! That is simply a misconception on your end.

You see:

 Integer[] numbers = { 1, 2, 3 };

is also a literal (well, "almost"; as you can only use it for such kind of array init statements); but it is not a primitive type!

And to ask the why part in your question: chances are - simply for convenience. When Java was created, it was meant to be "better" than the C and C++ of those days. And guess what: dealing with strings was pretty annoying and error prone in those languages.

In that sense: introducing string literals could be seen as unique selling point to differentiate Java from its competition!

GhostCat
  • 137,827
  • 25
  • 176
  • 248
8

Other answers are pretty good. Some specific points:

I asked this to my teacher and he replied that it is because what is in quotes is equivalent to an address, but he is not sure. Can you confirm?

Yes. He is right. As others have pointed out, a string literal, i.e. a valid Unicode character sequence enclosed inside a pair of "s is recognized by the Java Language Specification. When the Java compiler (the javac program) encounters such a literal (e.g. "Hello") in your Java source file, it takes it literally and places it in a specific section inside the compiled class file. This section is called the runtime constant pool. It then creates a particular instruction called ldc that it places in the class file where the compiled code for your initialization is stored. For instance, the body of the main method in the following Java source code:

public class StringAsPrimitive {
    public static void main(String[] args) {
        String s = "Hello";
    }
}

gets compiled to:

     0: ldc           #2                  // String Hello
     2: astore_1
     3: return

(There is no magic here. Just compile your code using javac program and view the class file using the javap program. You can even see the contents of the .class file using a hex viewer and you will see the String Hello literally).

This code is then interpreted by the JVM when you ask the java program to run this class file.

The ldc instruction to the JVM is documented here. This is what the JVM then does when it interprets #2 which is a reference to the actual location where the literal string "Hello" is stored in the computer's memory (RAM):

Otherwise, if the run-time constant pool entry is a reference to an instance of class String representing a string literal (§5.1), then a reference to that instance, value, is pushed onto the operand stack.

So, what your teacher said turns out to be right, although we don't say it quite that way. In Java, there are two kinds of types: primitive and reference. So, it would be more appropriate to say that the value of the String literal is a reference (and not address).

Is "Hello" stored in an instance variable of the class String?

No. The String variable initialized to a String literal could be anything, a static or class variable, an instance variable or a local variable (my code above). It is stored in the class file: StringAsPrimitive.class and later it is available to the JVM in a particular memory location. This happens when the JVM loads the class.

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
1

All literals are not primitives.

From JLS 3.10

3.10. Literals

A literal is the source code representation of a value of a primitive type (§4.2), the String type (§4.3.3), or the null type (§4.1).

Literal:

IntegerLiteral

FloatingPointLiteral

BooleanLiteral

CharacterLiteral

StringLiteral

NullLiteral

So String literals are not primitives but objects.

The JLS references it and you can also deduce it because String instances have methods while primitive cannot have methods.

String literals (String myString = "Hello") have very likely been introduced by the language to ease the declaration of String that is a type as common as primitive types such as int or boolean. Imagine a String concatenation such as :

new String("hello ") + new String (nameInput) + new String (" and welcome!");

This is clearly more verbose, less readable and therefore more error prone than :

 "hello " + nameInput +" and welcome!";
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • 1
    Thank you! But is the string "Hello" stored into an istance variable of the class String? – AlessandroF Apr 02 '17 at 19:53
  • @AlessandroF, no, the string "Hello" is stored in the so-called "runtime constant pool" (a specific location) inside the `.class` file of the Java source file where you have defined the variable like: `String myString = "Hello"`. – Kedar Mhaswade Apr 02 '17 at 20:43
  • it's still stored as a variable of class String though – Walfrat Apr 03 '17 at 08:18
  • @Walfrat, Nothing is ever stored _as_ a variable. A variable is a _place_ where a value can be stored, but it's not the only place. When you see `1` or `"hello"` in a program, those are _constant_ expressions---expressions whose values are compiled in to the program's byte-code. The value of the expression, `1` is of course a primitive, `int` value. The value of `"hello"` is a reference to an instance of the `String` class that is created when the class file is loaded. Either value can be _assigned_ to a variable, or it can be used directly, without any variable being involved. – Solomon Slow Apr 03 '17 at 09:55
  • @jameslarge I know, I don't think that AlessandroF who asked this was looking for that level of detail. – Walfrat Apr 03 '17 at 11:19
  • @davidxx Primitives types are immutable by definition see http://stackoverflow.com/questions/18037082/are-java-primitives-immutable – Walfrat Apr 03 '17 at 11:23
  • @Walfrat: you don’t need to dive deep into it; you may write `System.out.println("hello");` or `System.out.println(42);` without having a variable being involved. And you may declare a variable `String v="hello";` or `int v=42;`, if you wish, still, there is no difference between strings or primitive types in this regard. That’s basically, what @james large said, you can assign a value to a variable. Or you use the value without assigning it to a variable… – Holger Apr 03 '17 at 12:28
  • @Holger as I said earlier, I know – Walfrat Apr 03 '17 at 13:38