4

Sorry if I got the wording wrong in my title, but it would be easiest to provide an example in JavaFX

primaryStage.setScene(new Scene(grid, 300, 275));

Now from what I understand, this code is instantiating and initializing a Scene object, but it is not declaring it. If this is the case then would it be right to say that it is not stored in memory? Why would we want to do this? How is it that we can pass this Scene object to the setScene method successfully but not save the Scene object?

manlio
  • 4,166
  • 3
  • 23
  • 35
Pat Nak
  • 41
  • 1
  • 3
  • 8
    The reference is saved to a variable inside the `setScene` method, probably a `private Scene` of the `primaryStage` object. – Karl Bielefeldt Jun 11 '16 at 04:34
  • 2
    consider the code `double x = Math.sqrt(2);`. Would you like to rewrite this as `double n = 2; double x = Math.sqrt(n);`? Why? 2 isn't really what we're interested in, we just want to pass it to some other method so it can do some work we want it to do. Why would we save the parameter when it's the WORK we're interested in? – sara Jun 11 '16 at 07:17
  • @DocBrown I'm guessing "lack of understanding" (with partial understanding of concepts such as instantiation). Which should be an opportunity to explain and educate! :) – Andres F. Jun 12 '16 at 01:30

3 Answers3

9

If this is the case then would it be right to say that it is not stored in memory?

Not really. The Scene object is being instantiated, which by definition means memory is allocated.

Why would we want to do this?

As user232967 pointed out, it's a convenient way to declutter your source code. Why write (and force others to read) 5 lines of code when 1 is just as easy to read?

How is it that we can pass this Scene object to the setScene method successfully but not save the Scene object?

Because we don't need that Scene object anymore. The setScene method used it (and probably saved a reference to it), but that's not our problem, so we don't have to worry about it.

Dan Pichelman
  • 13,773
  • 8
  • 42
  • 73
5

If this is the only place that scene is used, then there isn't much point to declaring a variable, assigning the value and then passing that on.

In similar fashion, you could make do the following:

int x = 300;
int y = 275;
primaryStage.setScene(new Scene(grid, x, y));

If it can reasonably be encapsulated in a single statement, like in your example, it makes more sense to do that. Declaring single use variables like above can cause clutter in your code.

1

If this is the case then would it be right to say that it is not stored in memory?

No. The object is definitely still stored in memory. If it has no declaration, it can still have a reference pointing to it from within another object, which is the case here since you initialized the object within a setter method for object primaryStage.

If you were to instantiate it without any reference to it at all and just wrote:

new Scene(grid, 300, 275);

it would be still be stored in memory but likely would be short-lived as it would be unreachable and would likely be garbage collected eventually because there is nothing referencing (pointing to) it.

Anytime you instantiate an object, it will be stored on the heap memory space whether it has a declaration or not. Heap memory is the area of memory that is allocated for storing objects. Stack memory is the area in memory allocated for storing local variables.

In your example, you initialized Scene within a primaryStage setter method, meaning that primaryStage now has a reference pointing to Scene thus preventing it from being cleaned up by the garbage collector. Therefore, Scene will remain in memory for at least as long as primaryStage does.

Objects have a lifecycle - meaning that they exist in memory as long as the JVM is able to reach them. For the life of an object to continue, there must be a reference variable that can point to it. If there is no reference variable pointing to that object, that object becomes eligible for garbage collection, which is a process by which the JVM has determined that this object is no longer useful and will likely remove that object from memory in order to clear space for storing new objects.

For a more in-depth understanding about memory management, check out the Oracle docs on this subject and you will be able to understand the differences between stack and heap memory as well as some of the different types of garbage collection built in the JVM. https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/garbage_collect.html

Why would we want to do this?

A common case would be to invoke methods that require object references you don't already have. There will be times where you would want to call a non-static method but have no pre-existing instances to invoke it with. Below is an example:

class Orange {
  void printOrange(){
    System.out.print("Oranges are my favorite fruit.");
  }
}
class OrangeJuice extends Orange {
  public static void main(String[] args) {

  // some other useful code for OrangeJuice

    new Orange().printOrange();
  }
}

In this example, the output would be:

Oranges are my favorite fruit.

We didn't need to create a reference variable in order to simply invoke a print method, so why waste time and memory doing so if this is the only way in which you wish to use class Orange? In this case, you are able to invoke printOrange() while:

  • not using any space in stack memory for creating a reference variable
  • using heap space efficiently by reducing the lifetime of the Orange object you initialized for merely invoking printOrange()
  • made your code simpler by not creating an irrelevant declaration. You're keeping it as simplified as possible, which is good for organization's sake, understandability, and build time

Another reason to instantiate without a declaration, and this is typically the case for programs that handle copious amounts of data, would be to prevent a stack overflow, which is when the stack space has caused a crash from its storage space being overused due to local variables maxing out on the stack storage.

Objects can only be declared/created at runtime. Just because it compiles and runs with no exception errors doesn't mean it can't eventually crash. When declaring objects on a large scale and not allowing them to be garbage collected, this can result in your program crashing from overusing memory.

By making as few declarations as possible (without affecting the functionality of your program), you reduce the likelihood of this happening, since reference variables are stored in stack memory. Of course this is a problem usually associated with larger programs or programs that process large streams of data.

How is it that we can pass this Scene object to the setScene method successfully but not save the Scene object?

The compiler was designed to understand the need for memory management. You don't need to make an explicit declaration in order to make use of an object. Declarations cost memory and build time.

In this case, You did "save" the object. By initializing Scene within the setter method setScene for object primaryStage, you created a pointer to that Scene's space in memory. It now lives there and can be referenced through the primaryStage object.

When invoking a non-static method that is meant to produce an output that refrains from having any object-oriented outcome, the compiler simply needs the object as a stepping stone to produce that outcome. It allows you to put an instantiation in place of where a reference variable would normally be used to invoke the method in order to allow more efficient use of code.

By instantiating an object without a declaration, in your particular case, you are basically saying "I want to invoke the setScene method and I know that I need a Scene object to build off of in order to do that. I'm going to instantiate a Scene object strictly for that purpose and make my code more simple."

  • There isn't enough information in the question to decide "it will likely will be short-lived in memory". As we can see `primaryStage.setScene(...)` gets a reference, hence it is plausible to assume `primaryStage`retains the reference, and so the object created by `new Scene(grid, 300, 275)` may have a similar lifetime to `primaryStage`. So "since the object is unreachable without a reference variable having been declared" is misleading. – gbulmer Jun 11 '16 at 09:25
  • Further "Another reason to implement this practice would be to prevent a stack overflow" is misleading. Object are created on the heap, so it isn't going to make much difference. Also below the example it says "We didn't need to create a reference variable". That reference variable *is* created, memory *is* allocated on the heap for an Orange object. So that is also misleading. – gbulmer Jun 11 '16 at 09:30
  • gbulmer, you misread the part of the answer referring to stack overflow. I suggest you read it again. – We_are_the_Borg_ Jun 11 '16 at 09:35
  • @gbulmer, "That reference variable is created, memory is allocated on the heap for an Orange object. So that is also misleading" That is indeed incorrect. There is NO reference variable in the example I gave. The object can be stored on the heap space with or without a reference variable. I suggest you do a little research on the subject before saying things that are blatantly incorrect about the most basic areas of Java. – We_are_the_Borg_ Jun 12 '16 at 00:03
  • @gbulmer Thought I should clarify on this matter as well. You wrote "Further "Another reason to implement this practice would be to prevent a stack overflow" is misleading. Objects are stored on the heap, so it isn't going to make much difference." You need to understand how stack and heap work. Heap stores the object but local variables, including some reference variables, are stored in the stack. Memory is finite. Give it a good read! – We_are_the_Borg_ Jun 12 '16 at 00:04
  • I disagree, the space for the reference *is* allocated. Just because the program doesn't give it an explicit name, does *not* mean that it does not exist. It does exist, *and* it is named as a parameter to `primaryStage.setScene`. Think about the mechanics of passing an object reference to a method, it must exist. Further, in your second response, you haul the reference (on the stack) back into existence. So I assume you do agree with me now. Finally, I wrote 'it isn't going to make much difference', I didn't say no difference; a reference is usually small vs an object. I learned Java in 1995. – gbulmer Jun 12 '16 at 02:35
  • @gbulmer you need to make up your mind about what example you're referring to. You were citing the block of code I gave as an example when you said **"That reference variable is created, memory is allocated on the heap for an Orange object"** and now you're saying that you were referring to `primaryStage.setScene`? You learned Java in 1995? Terrific! Not sure what that has to do with the discussion, but I'm sure it adds value somehow. – We_are_the_Borg_ Jun 12 '16 at 05:13
  • @gbulmer **"Finally, I wrote 'it isn't going to make much difference', I didn't say no difference; a reference is usually small vs an object."** You're arguing for the sake of arguing and not being constructive at all. He asked "why would we do that" and I gave a stack overflow scenario as an example and said that it typically applies to programs processing large data streams, and you said that was **"misleading"**. For someone whom claims to have been programming for 21 years it doesn't really show. You really should read the entire thing and at least _try_ to understand it. It's not hard. – We_are_the_Borg_ Jun 12 '16 at 05:25
  • I've been programming for more than 37 years. I'd understood Pascal, FORTRAN, BASIC, several assemblers, C, Ada, Scheme, SmallTalk, C++, a few 4GLs and Delphi before I got to Java in '95. Once again, I suggest you think *very carefully* about where objects are allocated, and what happens to anonymous object references before claiming that they avoid stack overflow. I think, once you do that, you might choose to clarify what you wrote. The Orange example is rather poor, as the member would be static. Maybe you could offer evidence for stack-overflow avoidance, rather than sniping remarks? – gbulmer Jun 12 '16 at 23:16
  • @gbulmer **Oracle:** `int height = new Rectangle().height;` This statement creates a new Rectangle object and immediately gets its height. In essence, the statement calculates the default height of a Rectangle. **Note that after this statement has been executed, the program no longer has a reference to the created Rectangle, because the program never stored the reference anywhere. The object is unreferenced, and its resources are free to be recycled by the Java Virtual Machine.** https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html – We_are_the_Borg_ Jun 14 '16 at 03:42
  • I have no problem with that.. It's very useful to reduce clutter in the program's local name space (of the active functions/methods). I haven't checked the compiler's output in years, but clearly, the reference is available when the method is called. However, let's got back to the words you wrote "this is typically the case for programs that *handle copious amounts of data*, would be to prevent a stack overflow". Are you *really* suggesting a useful fraction of the stack would be saved that way? If you have real evidence or a real scenario, that it would, please just qualify your answer. – gbulmer Jun 15 '16 at 10:36
  • Let me try to be clear about my interpretation of "this is **typically** the case for programs that handle copious amounts of data", so that you might understand my issues. IMHO to save enough stack to prevent stack overflow, the technique would need to save a page, say 4kiB, which should be an easy target. That saving can *not* come from code that are so poorly written that class static data must be accessed by creating instances; the solution there is easy. More than 4GiB is copious amounts of data? It must not be a theoretical problem, but something plausible. Else it's misleading. Okay? – gbulmer Jun 15 '16 at 11:33
  • I've done large scale data processing and have built programs that process millions of tweets (twitter posts), emails, and combined Java with Hadoop, NoSQL, and Gephi to make programs that graph such data. Stack overflow was a common occurrence for a multitude of reasons and I've learned ways to avoid it. The less use of the stack the better. Now, I'm not saying all programmers will encounter this and that is why I said that it typically applies to programs that, for all intents and purposes, handle significantly large (1000's of gigs) amounts of data. Not sure how that's misleading. – We_are_the_Borg_ Jun 15 '16 at 11:54
  • I haven't used the same stack, but I've written programs in a variety of languages. Off the top of my head, I can't think of places where anonymous object creation was the killer, even in in graph building. I think some packages are a bit ropey, however better 'soon' and 'cheap' then 'good' but 'late' or 'too expensive', so you're stuck with the API. I really do think anonymous object are a drop in the ocean, and not typical fix for stackoverflow. However, you claim a real example, so use it; add what you wrote in your comment to the question, then it will clarify the context. – gbulmer Jun 15 '16 at 12:07