1

How many distinct String object instances are created in the following code segment?

String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;

Not sure about all my reasoning here.

By using the keyword new that creates an instance from the String class, I am guessing that has to be an object. However, I am confused, is String after the new now considered a method because it has ( ) and then it is calling a String literal "hello" in it?

String s2 = "Goodbye"; I think this is a String literal, and since Strings are actually objects even the String literal is considered object. Not 100% sure if that is true.

String s3 = s1; Just refers back to s1. Therefore, it is not distinct.

So my answer is 2 distinct objects.

Please explain if I am a right or wrong.

matt.
  • 2,355
  • 5
  • 32
  • 43
Foo Fighter
  • 193
  • 1
  • 8
  • 2
    @YassinHajaj Wouldn't it be 3 objects? Two in the string pool (the literals) and another one created by the constructor. – Fernando Matsumoto Oct 20 '15 at 21:29
  • @YassinHajaj *"one in the string pool"* and which one? Since he has two literals someone has to decide that. – Tom Oct 20 '15 at 21:34
  • 1
    Possible duplicate of [How many object creates with new operator?](http://stackoverflow.com/questions/6633852/how-many-object-creates-with-new-operator) – Tom Oct 20 '15 at 21:35
  • I think this is just a basic newbie question Tom. When you say Constructor you mean 'new', right? That's a constructor? And the String pool is that where the memory for the String is stored. I know the heap belongs to all objects so is the String pool a portion of the Heap specific for Strings? – Foo Fighter Oct 20 '15 at 21:42
  • Thanks for the science. Did not know new String("") created two objects if "" was not in the pool. – Yassin Hajaj Oct 20 '15 at 21:44
  • @Tom new creates on the heap and the litteral in the pool if not exist. That was my Logic. – Yassin Hajaj Oct 20 '15 at 21:45
  • @YassinHajaj This is right, but have you ignored *"hello"*? Just because it was passed as an argument to the String constructor, it doesn't mean it is not a String literal ;). – Tom Oct 20 '15 at 21:48
  • @Tom Yes, I was missing this actually. I actually thought that this litteral would be somehow stocked on the heap within the new String object. But it's good to learn everyday :) – Yassin Hajaj Oct 20 '15 at 21:50
  • Another thing that I don't quite get. When you say "hello" was passed in as an argument. Isn't "passing" referring to putting something into something else. But in this case it's just...there... as hello. Is there actually any passing going into the method? Confused on the programming lingo. – Foo Fighter Oct 20 '15 at 21:52
  • Possible duplicate of [Questions about Java's String pool](http://stackoverflow.com/questions/1881922/questions-about-javas-string-pool) – fabian Oct 20 '15 at 21:58
  • @FooFighter "passing" means that you pass/give "something" (either a object reference, a primitive value or `null`) into a method, so it can use it there. In this case the constructor gets a String reference (here: a reference to the literal *"hello"*), so it can use it to create a very new String object with the same content. – Tom Oct 20 '15 at 22:14
  • @Tom How is new String("hello"); being passed/given hello? since it was already in there to begin with. Or is it thought of as a structure which you the programmer PUTS/PASSES/GIVES to the function. Because I thought for something to be passed it would have to be assigned later on like method(x) then int x = 7; something like that. – Foo Fighter Oct 20 '15 at 22:28
  • @FooFighter You can either pass the "content" of a variable (if the type is correct), or you could also pass [literals](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html) (e.g. `method(7)`). It is not necessary to store "something" in a variable first to be used as a method/constructor argument. So something like `new Person("Firstname", program.getSurname())` works perfectly fine. Neither `"Firstname"`, nor the returned value of `program.getSurname()` need to be stored in a variable. But you _could_ store them in a variable if you like. – Tom Oct 20 '15 at 22:41
  • @Tom I think I understand. So when you pass something it's not necessarily to evaluate something into it later on. Passing can just refer to the programmer putting some characters into a String object and making a String literal and that would be considering passing. Because the programmer is passing something into the method by typing it out? – Foo Fighter Oct 20 '15 at 22:50
  • This tutorial might help you to understand what it means: https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html. – Tom Oct 20 '15 at 23:04

1 Answers1

6

The correct answer is 3.

String s1 = new String("hello");
String s2 = "GoodBye";
String s3 = s1;

The compiler will put both literals "hello" and "GoodBye" into a "constant pool" during compilation time, which then will be loaded by the classloader. So the JVM automatically interns all String literals used by this class, when it loads that class. More about this: When are Java Strings interned?. The String constant pool is then managed during runtime.

During runtime the JVM will create the third String object when it reaches the line String s1 = new String("hello").

So you would and up with three distinct String objects, where two of them contain the same word "hello". So s1.equals("hello") would be true, but s1 == "hello" would be false, because s1 references to a different String on the heap, than the literal "hello".

The line String s3 = s1 just creates a variable s3 with a copied reference to the String object of s1. It doesn't create a new object.

Also mind that you can "manually" add Strings into the String constant pool by using the method String#intern. So s1.intern() == "hello" is true, because the String reference returned from s1.intern() is the reference to the literal "hello" which was already in the constant pool.

If you like to get another and maybe more detailed explanation with some drawings about objects and their location, you can check this article on javaranch.

Community
  • 1
  • 1
Tom
  • 16,842
  • 17
  • 45
  • 54
  • 1
    @sam2090 (first comment): when you use the search engine to search for similar question, when you will see that a lot users are confused about that. So no worries :). – Tom Oct 20 '15 at 22:09
  • Thanks I got the notes. – Foo Fighter Oct 20 '15 at 22:10
  • @FooFighter About your question to fabian: It means the same what I wrote in my answer: the String *"hello"* is a String literal and therefore an object on the heap. The String created by `new String("hello")` is _another_ object, but it contains the same word, namely *hello*. – Tom Oct 20 '15 at 22:11
  • 1
    Nice answer. I think it would be much understandable with a nice drawing of references pointing to the pool and heap. Don't you think? – Yassin Hajaj Oct 20 '15 at 22:19
  • @Tom thank you for your answer! If I have this conceptually right the JVM runs from top to bottom. Therefore it reads the new String with a String literal inside and hello gets sent to the String constant pool, then reads the real String literal Goodbye, therefore likewise. Then when it reads the third line it allocates new memory because it has a new variable s3 and copies the reference of s1 BUT this in turn creates a new object because it's a new variable? Is this correct? – Foo Fighter Oct 20 '15 at 22:20
  • @YassinHajaj You mean like here: http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html? :D This is right, but it would also take some time and I'm bad at drawing so I just leave this link in the answer :D. – Tom Oct 20 '15 at 22:21
  • @Tom Yes exactly ! I guess we both are so this link is perfect lol :D – Yassin Hajaj Oct 20 '15 at 22:25
  • And is String s3 = s1 saying that they are equal in the sense of their characters but unequal in terms of their memory allocation. Because new memory is allocated for the s3? How can both new String("Hello"); and "Goodbye"; both be considered String literals when they are set up differently? – Foo Fighter Oct 20 '15 at 22:30
  • @Tom I think I understand. It's sort of like something within something else right? new String("Hello"); String(x) itself is an object and then there is another object within that object, namely the String literal "hello" Is this correct? – Foo Fighter Oct 20 '15 at 22:32
  • *"And is String s3 = s1 saying that they are equal in the sense of their characters but unequal in terms of their memory allocation."* No, this is wrong. `s3` and `s1` point/reference to the _exact same_ String object. *"Because new memory is allocated for the s3?"* There is memory allocated for the variable itself, but there is no new String object. *" How can both new String("Hello"); and "Goodbye"; both be considered String literals when they are set up differently?"* The first one isn't a literal ;). "hello" is one, but `new String(...)` isn't. – Tom Oct 20 '15 at 22:43
  • @Tom I see, s3 and s1 point to the exact some object. s3 and s1 are just variables so they are in the stack? pointing to the same String object in the heap? What makes it a distinct new object if s3 and s1 are only variable references to the same object? And I thought variables didn't get memory only objects in the heap. Sorry for all the questions pretty new to this stuff! – Foo Fighter Oct 20 '15 at 22:57
  • Well, a variable in the stack is also memory ;). *"What makes it a distinct new object if s3 and s1 are only variable references to the same object?"* Nothing, because you already got your 3 objects after the very first line. The mentioned third line doesn't add more objects. – Tom Oct 20 '15 at 23:03
  • @Tom ok, I was totally unaware about these ordered "time sequences" for different processes to be carried out. When the program compiles it scans for String literals and things of that type? so therefore it takes the String literals and they are created in the heap. – Foo Fighter Oct 20 '15 at 23:35
  • Conti. Then runtime takes more into account new String("hello"); as another object? I think what confuses me is how new String("hello"); and String literal "hello" can be considered different at different time sequences. Is it just because during compilation time Is it taken once as a string literal and then secondly during the runtime as a String object? Again, n00b here. – Foo Fighter Oct 20 '15 at 23:35
  • @Tom What is new String("hello"); exactly? and what causes the compilation time to take it as string literal? then runtime takes it as something different? – Foo Fighter Oct 20 '15 at 23:39
  • The compiler doesn't care about `new String(..)`, it cares about the `"hello"` part, because this is a _literal_ of type String. Like `1` is an integer literal and `1.5D` is a double literal. The JVM cares about `new String(..)` during runtime, because it has to create a new String here. – Tom Oct 20 '15 at 23:48