how many objects will be created with keyword new in java?

2 weeks ago 22
ARTICLE AD BOX

That is misleading to the point of wrong.

The basic answer is 1. new makes a single object.

What does new do?

new does two things:

It creates exactly 1 object. Never more. Never less. It then runs the constructor. (Which will also always run parent constructors). This is ordinary java code, that can do anything ordinary java code can do. It therefore can also make more objects. It doesn't have to.

For example, trivially:

public class Example { Example() { new Object(); } } .... new Example(); // This makes 2 objects

The above snippet makes 2 objects. new Example does the two things:

It makes a new Example object. It runs the constructor.

That constructor ends up executing new Object(), making another object (this object is created, the reference to it is ignored, so this is a useless object that is instant garbage and is likely going to be collected very soon and essentially for free. But, it is made).

Hence, 'If I invoke a constructor, how many objects are created?' has a somewhat unsatisfying answer: That makes 1 + X objects, where X is the number of objects the java code in its chain of constructors ends up making.

You might mentally model a constructor as a thing you call that produces a new object. But that's not technically true: A new Foo() expression in java produces a completely blank (all fields null/0) new object and then hands that newly created object to the constructor you are invoking. The constructor therefore doesn't actually make the object; instead, it initialises it.

What is that youtube thing about?

java code is compiled to a class file, then class files are loaded by your JVM (i.e. java.exe), then their code can be executed.

But, imagine we have this code:

System.out.println("Hello");

How does that 'work'? At the runtime level, the JVM must find the out field in the System class, then load the value that it currently holds, then find the method "println" of the class PrintStream, and then invoke that method, passing a reference that is the receiver (System.out - i.e. the value of the out field of the System class), and a reference that is the argument, which is thus a reference to a string that is "Hello".

That's just how it works. It has to be that way. A reference is like a pointer, or an address to a home: "Hello" is the home, but when it is time to invoke that method, the JVM doesn't take the entire home, brick by brick, load it on a train, and ship it to the println method. No, it just writes the adress of that house on a piece of paper and hands that piece of paper to the println method. If the println method is interested in the house (and it is; it wants to know the characters so it can emit them to the screen), well, it has the address, it can go to the house itself and find out.

So, if that code only ships an address, who, how, and where is the house?. The JVM, obviously, doesn't have every imaginable string in memory.

So why is "Hello" in memory, and who made it?

Where do string constants go?

The answer is: The class loader did.

The class loader scans your .class file and notices all these string constants defined in one. To load this class file, the class loader creates all these string objects to represent all the constants listed in the class file, which are all the strings you use anywhere in the java source file that produced that class file. In fact, because string constants tend to be reused a lot, there's a 'cache': Strings made by the classloader specifically, i.e. literals, are cached - if you have one class file containing the literal "Hello" somewhere in it, and then a completely different class file is loaded by the same JVM half an hour later that so happens to also have "Hello" somewhere inside, the loading of this second class does not produce a new string. Instead, the already existing "Hello" reference is reused. Yes, that means "Hello" is a string in the lifetime of this JVM that is always somewhere in memory and is never garbage collected1. It's okay - you don't load an infinite amount of class files.

Thus: Misleading

The code:

new String("hello") causes lots of things to happen, including:

During the loading of this class, "hello" is in the 'list of string constants' section of that class file; as part of loading the class file that contains this method, the classloader will 'fix' this by 'linking' that code: That is turned into bytecode that is referring to an already existing "hello" string if a class that was loader earlier already contained it. Note that classes are only ever loaded once for a JVM lifetime 1.

Much, much later in the process this code is actually executed. To execute new String("hello"), the JVM will:

Create a new string object. Invoke the String(String) constructor, passing the newly created object as receiver and a reference to "hello" as argument.

Saying that this means "2 strings are created" is essentially wrong. The first bullet may or may not create a string (depends on what classes were loaded earlier); the second bullet definitely will.

Random Context

The .intern() method gives you access to this cache pool:

String a = "hello"; String b = new String("hello"); assert a != b; //== and != compare references; new String made a new object, so, false. assert a == b.intern(); // but this is true.

== and !=, if the left and right hand side are objects, compare the address. Imagine you have 2 identical houses. Especially outside of europe, extremely common: 1 house design replicated over and over, exactly the same colour, size, layout, and so on.

I ask you: "Are these 2 houses the same"?

The answer.. depends on what you meant. Did you mean 'same address'? Obviously, then the answer is 'NO'. These houses are not the same place.

If you meant 'the design, look, colour, and so on', then the answer is 'YES'.

In java, a.equals(b) is that second notion of equality (so, a.equals(b) is true when both are "hello", even if they aren't the same object) and a == b is the first notion (hence why in the above snippet, a != b was true).


[1] If you write your own class loaders, you can let those end up getting collected and, oversimplifying a lot, that may lead to classes actually being unloaded, or classes being loaded more than once. This text tries to keep things simple by assuming you aren't doing that. If you don't know what this means - you aren't using custom class loaders and can forget about this footnote.

Read Entire Article