I feel like a novice for asking this question -- but why is it that when I pass the Set below into my method and point it to a new HashSet, it still comes out as the EmptySet? Is it because local variables are allocated on the stack, and so my new is blown away when I exit the method? How could I achieve the functional equivalent?
import java.util.HashSet;
import java.util.Set;
public class TestMethods {
public static void main(final String[] args) {
final Set<Integer> foo = java.util.Collections.emptySet();
test(foo);
}
public static void test(Set<Integer> mySet) {
mySet = new HashSet<Integer>();
}
}
Memory Allocation in Java 1 The code section contains your bytecode. 2 The Stack section of memory contains methods, local variables, and reference variables. 3 The Heap section contains Objects (may also contain reference variables). 4 The Static section contains Static data/methods.
Memory in a C/C++/Java program can either be allocated on a stack or a heap. Prerequisite: Memory layout of C program. Stack Allocation: The allocation happens on contiguous blocks of memory. We call it a stack memory allocation because the allocation happens in the function call stack.
Unlike a Java stack, where memory is allocated when the program is compiled, a Heap allocates Memory while the program is run. When opposed to the direct and fast access of a stack, accessing variables stored here is a little slower.
The memory size of a Java stack is generally much less than in a Java heap space because when a method ends, all the variables created on the stack are erased forever. Here’s an example of how to create an object in the stack: What Is Java Heap? Java objects are in an area, which is called the heap.
Java passes references by value, think of mySet
as just a copy of the foo
reference. In void test(Set<Integer> mySet)
, the mySet
variable is just a local variable within that function, so setting it to something else doesn't affect the caller in main
.
mySet
does reference(or "point to" if you like) the same Set as the foo
variable does in main
though.
If you want to alter the reference in main, you could do e.g.:
foo = test(); //foo can't be final now though
public static Set<Integer> test() {
return new HashSet<Integer>();
}
... Is it because local variables are allocated on the stack, and so my new is blown away when I exit the method?
No. It is because of the argument passing semantics of Java.
Java arguments are passed "by value", but in the case of an object or array type, the value you are passing is the object/array reference. When you create and assign a new set object to mySet
, you are simply setting the local variable / parameter. Since Java uses pass by value, this has no effect on the foo
variable in the main
method.
When you enter the test
method, you have two copies of the reference to the HashSet
instance created in the main
method; one in foo
and one in mySet
. Your code then replaces the reference in mySet
with a reference to a newly created HashSet
, but this new reference doesn't get passed back to the caller. (You could change your code to pass it back ... for example as the result of the test
method. But you have to do this explicitly.)
OK - however -- if I were to do add or some other operation within my method call, that allocation would be preserved. Why is that?
That is because when you call an instance method using the reference in foo
or mySet
, that method is executed on the object (HashSet
) that the reference refers to. Assuming that the two references point to the same object, your "allocation will be preserved". Or more precisely, you can observe the effects of operations on one reference to an object via operations on other references to the same object.
Just remember that Java method calls copy references to object, not the objects themselves.
By the way you won't be able to add elements to a set returned by Collections.emptySet()
. That set object is immutable. Calling (for example) add
on it will throw an exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With