The following code is used to create an object of a class within a variable:
ClassName obj = new ClassName();
But what if we do not create any variable and just type the following?
new ClassName();
When I used it, there was no error. But what it actually does when no variable is created?
Both methods create an object, but the second method has no name for it.
When you create an instance of the ClassName, the difference between your first method and second method is that for your first method, you can actually access variables and methods within the class.
For example,
ClassName obj = new ClassName();
System.out.println(obj.x);
Where ClassName
class ClassName {
public static int x = 2;
}
The benefit of this approach is you can access the variables within the class. If you used the second approach, then the instance would have no name, so you wouldn't be able to access the variables.
new ClassName() calls a special method called a constructor and, like any method, it returns a value1. The value that it returns is an instance of ClassName. You can choose to assign that value to a variable, or not, just as you can do with the return value of any method. So you simply need to decide whether you need to assign the returned value to a variable, or not. If you do, then you need the first statement, namely:
ClassName obj = new ClassName();
And if you don't need to assign the returned value to a variable, then you can use:
new ClassName();
1 - a method can return void which means it doesn't actually return a value
To answer to your question I think is useful to see how objects are managed by JVM during execution.
All java objects reside in a JVM area called heap and can ( note that this is not mandatory ) be pointed by one or more variables.
The variables that hold references to objects reside on another area of JVM called stack.
Every time an instruction like new SomeClass(); is executed a new object is allocated on that area. When the heap area becomes full, garbage is collected and during the garbage collection objects that are no longer pointed by a variable are cleared in order to free space on heap for new objects.
What is the difference between your two instructions?
1- ClassName obj = new ClassName();
It allocates a new object on heap that is pointed by the obj variable on stack.
2- new ClassName();
It just allocates a new object on heap with no variables on stack that point to it.
When can be useful to use the second approach?
According to this, using the second approach could be useful if you want just to allocate a new object on heap without using it through a variable for example to test memory management on your program. Actually the second approach is used when you want to create a "one-shot" object and use a method or a variable of it in the same instruction improving the garbage collector efficiency and avoiding unexpectedly get an OutOfMemoryError exception like:
using once time an object variable:
System.out.println(new ClassName().x)
or
executing once time an object method:
new ClassName().evaluateResult();
NOTE: In this specific case you probably could evaluate instead to make a static method on the class.
Another usage can be to put new elements on a collection as follow:
final List<ClassName> objectList = new ArrayList<>();
for(int i=0; i<10; i++){
objectList.add(new ClassName());
}
You can may ask: What happens instead to objects that are pointed by
at least one variable like ones created with first approach?
All references that are held in a variable are naturally dropped when the variable goes out of scope so they became eligible for garbage collection automatically ( according how their scope is managed on code ).
Related
I'm saving the previous value of a Java object. I (almost) understand references are strong, weak, etc. but I can't find an example that classifies my specific situation that is apparently referencing an out-of-scope object. (I've looked at a lot of posts on this subject.)
Is the Java reference aTestCopy to the out-of-scope array of objects aTest valid?
It's a shallow copy but is it subject to garbage collection thus I need a deep copy for it to work reliably every time? Or should the declaration of the new object aTest be placed outside the while with the "previous" copied object aTestCopy?
Is the use of a null a good practice for the first-time-through switch or should that be a separate boolean variable?
Thanks.
Tester[] aTestCopy = null;
while(true)
{
Tester[] aTest = myMethodReturnsATesterArray(); // new values
// need code to skip using aTestCopy the first time through - no previous value
// else use the previous value here
aTestCopy = aTest; // save them for the next use of previous values
}
There is no problem to use null as initial value for reference types in Java. But there isn't any relevance between initialize a reference type as null and garbage collection. You should initialize aTestCopy as null to use in another scope like in your case in while.
Garbage collection is triggered whenever an object in memory is not pointed anymore by any reference.
When you assign a reference type to another reference type (if it is not immutable in this case), you made copy the memory address of that value. So when you can make a change in aTestCopy will be reflected to the reference aTest.
In Java, variables do not hold objects, only references to objects.
The lifetime of objects is largely independent of the lifetime of variables: Objects are created by executing new, and reclaimed once the program has relinquished all means of accessing them (i.e. the object is no longer reachable form the references the program holds).
Put differently, the first variable to hold a reference to an object holds no special significance. In particular, it does not determine the lifetime of that object. Any reference will keep the object alive, and there can be no such thing as an "out of scope" object.
Similarly, when you assign a variable of reference type, you are only assigning the reference, causing both variables to point to the same object, and to see any changes done to this object though the other variable.
If you want a new object, you must use new (or call a method that uses new).
In your case, I'd make sure that myMethodReturnsATesterArray returns a new array, referencing new Tester objects. Then, the objects created by separate iterations of the loop will exist independently, allowing the loop to reference both the old and new objects and do whichever comparision it deems appropriate, without having to fear that the invocation of myMethodReturnsATesterArray has somehow changed the previous object.
This question already has answers here:
Where does class, object, reference variable get stored in Java. In heap or in stack? Where is heap or stack located?
(8 answers)
Closed 4 years ago.
This question is regarding Java, and how Objects are created, passed, and "deleted".
From what I know, when you want to create an object, you use the "new" keyword. From my understanding, this operator (new) allocates memory for the object, and the = operator assigns the reference to the location of this object in memory, to the variable name you give it.
For example, let's say you create an array in Java like so.
int[] arrayX = new int[size];
the = operator now stores the reference to the array in memory to the variable name arrayX.
This is all fine.
Now let's think about methods (functions).
Firstly, from my understanding, when you call a method, memory is allocated on the stack for this method's variables and processes, and when the method returns, it's instance on the stack is closed/deleted/put in garbage. However, this doesn't explain how you can return objects (such as arrays) which were created in the method back to the caller's scope using the return keyword.
From what I understand, since the method is returning, the data in its stack is going to be deleted. Therefore, the array that was created within this method's scope, will also be deleted. So the reference returned to the array's location, will point to "garbage" values. However, this is clearly not the case. In Java, if you return an Object, you can keep using it.
This makes me confused about how Objects are created, stored and returned...
are objects created always stored in permanent memory? or
does the return operator move the array or object from the method's temporary stack to the caller's stack?
if the second case is true, then are objects created within methods deleted after the method returns to the caller (but does not return the object)? In this third case, it would mean that one shouldn't worry about creating objects in methods, as those objects will be deleted. Thus, if a program was to call a method 1000 times, we shouldn't worry about the memory filling up with objects that we only use once.
I have looked through courses offered on edX on Java and even read a book (although not finished) and still haven't found an answer to this so I would appreciate your input (if you know).
EDIT: Please note, this questions asks 3 separate things:
1. Where are Objects and primitives stored
2. what does the new operator do specifically
3. what does the return operator do
However, this doesn't explain how you can return objects (such as arrays) which were created in the method back to the caller's scope using the return keyword
The reason you can do it is that the object is not created on the stack; only the reference to it is. The array stays in the dynamically allocated memory until it becomes eligible for garbage collection. When you assign the result returned from a method to another variable or to a field, the value of the reference is preserved, so the object stays in memory.
does the return operator move the array or object from the method's temporary stack to the caller's stack?
Only the value of the reference gets copied. The reference is a relatively small object, whose size depends only on the system on which JVM is running. In particular, the size of the reference does not change with the size of the object being referenced, so the amount of required copying is limited.
One important point to note is that if you return an object in a method and don't save it, it does in fact get garbage collected. For example if you have:
public int somemethod(){
int myint = 9;
return myint;
}
And then call someMethod() in your main method, in order to access this return for the future you have to store it.
public static void main(String [] args){
this.someMethod(); //can't access myInt.
int savedInt = someMethod(); // Saves the value 9 for future access.
}
So in general when you call a method and then the return type is present before that method gets removed from the stack, but in order to use it in the future you must store the value in a variable that will still be present.
Let's say I am trying to sort a collection with a specific Comparator. Does it matter from a performance point of view to have a comparator defined in the sorted() clause of as a an anonumous instance, or it is better to create an instance once and just call compare method in the sorted() clause?
In essence, what is better:
myCollection.stream().sorted(
new Comparator<String>(){
public int compare(String a, String b){
//code
}
})
Comparator<String> comp = new MyCustomComparator<>();
myCollection.stream().sorted(comp::compare)
Note: neither syntax, nor comparing values matter - I want to know conceptually whether JVM is smart enough to initialize my anonymous comparator only once (case 1) and keep reusing just one method, or it will keep creating new instances (then I would choose case 2)
A new instance of an anonymous class will be created every time the expression using new is evaluated.
In your first example, a new one is created every time the statement runs where you are passing it to sorted.
In your second example, a new one is created wherever the comp variable is being initialized. If comp is an instance member, then it gets created whenever the object that owns it is created. If comp is a local variable in a method, then it gets created every time the method is called.
A static, stateless and non-capturing Comparator is always going to be the most efficient way, because you can create it once and keep it forever. (See for example String.CASE_INSENSITIVE_ORDER.)
That's not to say you shouldn't use another way.
In Java 8, you should prefer lambdas over anonymous classes. Non-capturing lambdas can be cached and only created once. For example, this program outputs true:
class Example {
public static void main(String[] args) {
System.out.println(comparator() == comparator());
}
static Comparator<String> comparator() {
return (lhs, rhs) -> lhs.compareTo(rhs);
}
}
(Example on Ideone.)
All that said, you shouldn't worry about creating a few small objects here in there in Java, because it's unavoidable and the garbage collector is optimized for it. The vast majority of the time, the "best" way to do something is also the most readable.
Note that you do not have to use a method reference in your second example. You can pass it to the method directly:
Comparator<String> comp = new MyCustomComparator<>();
myCollection.stream().sorted(comp)...
Runtime for both approach will be the same. This can be expressed as below :
For 1st scenario, first JVM create instance of comparator with your custom code for compare method and allocated space for this object anonymously. So ultimately object is created and allocated memory without some pointing reference for user and once function call is over object is registered for GC.
For 2nd scenario, JVM again created new instance of comparator with custom code and allocated space and also provide reference stored in separate variable so that this object can be used again but here object won't be collected by GC if same is used again in code anywhere else. So when GC runs for next time, it has to scan for references of variable and figure out whether it can be GCed or not.
suppose i have a code snippet like this:-
class A {
void help() {
Help helper = new Help();
}
}
in the above case, the object reference helper will be allocated memory in the stack.
now if i have a case like this
class A {
Help helper = new Help();
}
in this case, helper will not be allocated memory inside of a stack frame(I am sure of that).
will it behave like an instance variable and will be allocated space inside of an object on heap.
This type of declaration is only located to your instance. the helper attribute will be assigned each time you instanciate you Class A.
It is definitely an instance variable. it goes in the heap
In order to separate the instance and the variable you can use static attribute. Then it is linked to the class so it goes in the code segment.
Yes, You are correct. In the second case, the Help object will behave as an instance variable of the class.
When you declare the object inside the function, stack memory is used up (local variables). Whereas for instance variables ,heap memory is used.
Yes, in the second case the memory will be allocated to object helper as soon as the object of class A will be initialized but in the first case the memory will be allocated on the stack to the function named void help() and will be destroyed as soon as the function ends because helper object is a local variable to this function.
There is a difference between object and reference variable. For example:
//Here 'helper' is the reference variable
Helper helper = new Helper ();
Whenever we create any object (new Helper()), it’s always created in the Heap space and it's reference (helper) in the Stack space.
Java Stack memory is used for execution of a thread. They contain
method specific values that are short-lived and references to other
objects in the heap that are getting referred from the method.
(Source: https://www.journaldev.com/4098/java-heap-space-vs-stack-memory#java-stack-memory)
So the two objects are stored in the heap but their two reference variables are stored in different stacks.
I'm trying to perform a small memory optimisation for my Java game. It is a bit unclear to me how does Java allocate memory when it comes to fields:
public class Test {
private HashMap<String, String> info;
public Test(boolean createInfo) {
if (createInfo) {
info = new HashMap<String, String>();
}
}
}
As you can observe, the HashMap info is initialised if you pass true to Test's constructor.
Does new Test(true) take up more memory than new Test(false)?
Which leads to the more general question:
When you create a field in a class, does Java "reserve" the necessary memory for such field in case it is initialised, or will it do nothing until you actually initialise it?
There is this question: Is memory allocated for unused fields in Java? which seems to be almost exactly what I am looking for, but they seem to be asking what already instantiated fields that are unused, whereas I am asking for uninstantiated fields that may or may not be used.
Does new Test(true) take up more memory than new Test(false)?
Yes.
When you create a field in a class, does Java "reserve" the necessary memory for such field in case it is initialised, or will it do nothing until you actually initialise it?
There are two things here - the HashMap reference, and the HashMap object. Both of them require memory. When a class instance is created, memory is allocated for all its instance variable. In case of int type field, it will allocate 4 bytes, similarly for a reference, it will allocate some memory for that reference (I don't know exactly how much it is). But surely it will allocate memory for the fields.
Then when you initialize the fields in the constructor, the actual HashMap object is created, which will again take up memory to store the object.
The field itself has space for a reference to an object, and that space is allocated when the containing class (Test) is instantiated, even if the value placed in that field is null. Your example code doesn't create an extra object whose reference will go in that field when you pass in false.