zeme
zeme

Reputation: 437

What does the 'new' keyword actually do in Java, and should I avoid creating new objects?

I signed up a few moments ago, though I've been making great use of this site since I took up computer programming, which I've been teaching myself and consider a little hobby of mine.

I did look up for similar questions, but in fact I couldn't find the answer I was seeking for. Now, being aware that, in Java (that's the language I was suggested to start off with), it is considered good programming practise to declare and instantiate variables as you need them, please consider the following lines:

class MyClass {
    void myMethod() {
        AnotherClass myObject = new AnotherClass();
        myObject.doStuff();
    }
}

Now, suppose I invoke myMethod(), say, 10 times while running my program, how does that work? Is a new object create every time? Is the myObject variable reallocated every time? Does the complier skip that like of code as it sees that the object has already been created and the variable myObject already been assigned to such object? In a nutshell: should I write code like that only if I plan to invoke that method only once? I know... shame on me for asking such a stupid question, but please give me a chance! Thanks in advance!

--------------------------- edited -----------------------------

So now am I supposed to edit this post after I get new answers? btw... gosh that was quick, thanks a lot! And wow that confused me, a lot, I guess that's due to the fact that I've been teaching myself so... Anyways, isn't it useless to create a new AnotherClass Object for the myObject variable every time? I mean, if i want to use the myObject variable throughout my program, shouldn't I declare it Once And For All? maybe in another method, that I'm going to invoke only once? Because as far as I understand, every time i invoke myMethod() a new object is creating, thus overriding myObject's own properties aka variables or am I just talking nonsense?

--------------------------- edited -----------------------------

My doubts came after reading this code from some website I can't remember right now:

    public class DataBase {

    private static String buf, retString = "\n";
    private static File file = new File("test.txt");

    public static void readText(JTextArea area) {   
        try {
            FileReader fr = new FileReader (file);
            BufferedReader br = new BufferedReader(fr);
            while ((buf = br.readLine()) != null) {
                area.append(buf); 
                area.append(retString);
            }
            br.close(); 
            fr.close();
        }
        catch (IOException e) {
            System.out.println("Exception: " + e);
        }
    }

    public static void writeText(JTextArea area) {
        try {
            FileWriter fw = new FileWriter (file);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(area.getText());
            bw.close(); 
            fw.close();
        }
        catch (IOException e) {
            System.out.println("Exception: " + e);
        }
    }
}

I mean, why not declare FileWriter, FileReader, BufferedReader and BufferedWriter at the top of the class as they did for the other variables? and why not initialise them as well maybe in the constructor? Why doing it every time the method is called rather than using maybe the same instance variable?

Upvotes: 34

Views: 86114

Answers (6)

Tom
Tom

Reputation: 45114

Yes, a new object is created every time. The reference to each myObject is allocated in the stack.

In a nutshell: should I write code like that only if I plan to invoke that method only once?

If you want myObject to disappear after the method execution is completed, then yes. If for some reason, you need to keep a reference to it, then you can declare it as a class member.

class MyClass {
    AnotherClass myObject;
    void myMethod() {
        myObject = new AnotherClass();
        myObject.doStuff();
    }
}

This way, it will still be created each time you call myMethod(), but it will still exist after myMethod completes. This can be handy, or not, depending on the situation.

Does the complier skip that like of code as it sees that the object has already been created and the variable myObject already been assigned to such object?

This won't happen when using new. It is guaranteed that it will create a fresh instance. It can be implemented using FactoryMethods (not the compiler skipping lines of code, but preventing the creation of a new object). For example, the Integer class implements this: If you try to get an integer between -128 and 127, it will always return the same instance (won't create a new object) when using its Factory Method valueOf

 Integer five = Integer.valueOf("5");//Will always return the same instance.
 Integer otherFive = Integer.valueOf("5");

 assert(five==otherFive);//true

Of course, using new won't return the same instance, but always a new one:

 Integer five = new Integer("5");//Will create a new object each time.
 Integer otherFive = new Integer("5");

 assert(five==otherFive);//false

After question update

There's really not much to say about the code you added. However, if you take a look, you'll notice two methods. Based on its names, once seems to write, the other one seems to read. That behaviour is specific to each method, so the method that writeFile doesn't care about objects used for reading. And the method readFile doesn't care about objects used to write. So there's no sense on making a fileReader available to the writeFile method, and so on.

Coming back to your original question, yes, this instantiates a new object each time the method is called. It's not important. It's preferable to having to ask yourself "why does the readFile method has access to a FileWriter instance?

Upvotes: 4

linuscash
linuscash

Reputation: 1145

Yes, if you called myMethod() 10 times it will create 10 unique and separate objects.

The new keyword does exactly what it says on the tin, it creates a brand new object, irrespective of whether one already exists. It creates a new object and stuffs the reference to that object inside the variable it has been given, overwriting any previous value (object) the variable held.

Is the myObject variable reallocated every time?

Again, yes it would be re-allocated with a new object every time the method was called. An interesting note about this would be that the variable wouldn't "really" be re-allocated as you are defining the variable within the method body itself, so every time the method ends it will remove the variables that were defined within its' scope. So what it actually does is create 10 individual variables and assign 10 individual objects, although as I said the others should have been removed automatically so it wouldn't use any additional memory.

In a nutshell: should I write code like that only if I plan to invoke that method only once?

Well as I said, in the example above each object would be destroyed at the end of method execution (assuming you didn't assign the object reference to a variable outside the scope of the method) so in your example you could happily call the method as many times as you wanted but each time would in no way be connected to the previous calls.

I realise my way of writing can be confusing, so if you want me to clarify anything just ask.

Updated Answer to reflect edited question

'why not declare FileWriter, FileReader, BufferedReader and BufferedWriter at the top of the class as they did for the other variables?'

Okay, I assume you understand that the variables are not actually called FileWriter, FileReader, BufferedReader, and BufferedWriter, but rather this is the variable type. Their names are fw, fr, br, and bw. If you don't understand what I mean just ask. From now on I will refer to the variables by the names you did to make reading more easy, afterall fw just stands for FileWriter anyway so there should not be too much confusion.

The key to this question is hidden within the names of the variables themselves. Notice how they either end in Reader or Writer this can give us a subtle clue about their uses. Clearly FileWriter and BufferedWriter are to do with output in some way. By looking over the code we see that our suspicions were right and that at no point other than within the writeText(JTextArea area) method do these variables appear. So if the variable aren't used anywhere else within the code it would make logical sense to define and initialise them within the method that they are used in, not only does it make the code easier to read because we then "know" those variables are only related to that method, but also has the benefit of those variables being removed at the end of method execution, thereby not leaving variables in existence that were only used very briefly. By these rules we can say the same is true of FileReader and BufferedReader.

Observe this example about variable scope. (Look at the comments I added to the code)

public class DataBase {

private static String buf, retString = "\n"; // buf & retString - created
private static File file = new File("test.txt"); // file - created

public static void readText(JTextArea area) {   
    try {
        FileReader fr = new FileReader (file); // fr (FileReader) - created
        BufferedReader br = new BufferedReader(fr); // br (BufferedReader) - created
        while ((buf = br.readLine()) != null) {
            area.append(buf); 
            area.append(retString);
        }
        br.close();
        fr.close();
    } // fr (FileReader & br (BufferedReader) - destroyed
    catch (IOException e) {
        System.out.println("Exception: " + e);
    }
}

public static void writeText(JTextArea area) {
    try {
        FileWriter fw = new FileWriter (file); // fw (FileWriter) - created
        BufferedWriter bw = new BufferedWriter(fw); // bw (BufferedWriter) - created
        bw.write(area.getText());
        bw.close(); 
        fw.close();
    } // fw & bw - destroyed
    catch (IOException e) {
        System.out.println("Exception: " + e);
    }
}
} // buf, retString and file - Still exist as long as the object exists

From this example it becomes more clear as to why the variables are defined in the methods rather than as instance variables and initialised within the constructor. It allows for much cleaner code as well as being more readabe.

Why doing it every time the method is called rather than using maybe the same instance variable?

Well this question has to do with variable types. We couldn't reuse a single variable for all the information as the types would have needed to be different.

If we take all the variables from the code

private static String buf, retString = "\n"; // valid
private static File file = new File("test.txt"); // valid

FileReader fr = new FileReader (file); // valid
BufferedReader br = new BufferedReader(fr); // valid
FileWriter fw = new FileWriter (file); // valid
BufferedWriter bw = new BufferedWriter(fw); // valid

Now we know that we cannot place a value that is not of the same type as the variable into that variable so something like

FileReader fr = new BufferedReader(fr); // Is not valid!

Because the types simply don't match.

Make sense?

Upvotes: 26

dongjk
dongjk

Reputation: 343

if you invoke 10 times, there will be 10 method frame in your java stack, each frame will act new() action and when frame finished, it will release.

enter image description here

Upvotes: 2

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81684

A new object is created every time the method is called. If control reaches a line of code with a "new" operator on it, then an object is going to be created; there's no behind the scenes caching or other magic.

Upvotes: 0

templatetypedef
templatetypedef

Reputation: 372814

Every time you call the myMethod method, the code executes from the top with no memory about what it did on previous executions (unless, of course, you changed some fields of the MyClass object. This means that every time you run the method, you will create a new AnotherClass object and store it in myObject. More generally, each execution of a method will run the code from the top and will not avoid recomputing values even if they could have been cached from previous iterations unless you explicitly store the values somewhere.

If this isn't what you want, and you instead want to store the object you allocated so that on future iterations you can reference it again, you can store it in an instance variable of the class.

Upvotes: 0

Bala R
Bala R

Reputation: 108957

Now, suppose I invoke myMethod(), say, 10 times while running my program, how does that work? Is a new object create every time?

Yes!

Reusing or not reusing an instantiated object depends on the design and situation. There are cases where it's better to reuse objects, in which case you can create a class field to hold on to the reference, and there are cases where it's best to create a new object every time(look into immutability, for instance).

Upvotes: 2

Related Questions