This question already has answers here:
Does initialized java array go onto stack or heap?
(2 answers)
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 5 years ago.
Is the following code safe in Java? My concern is due to the fact that in function f() variable arr is allocated on stack and as such is deallocated upon leaving the scope but is still referred to outside the scope.
public class Main {
public static class Array {
public final int[] arr;
public Array(int arr[]) {
this.arr = arr;
}
}
public static Array f() {
int arr[] = {1, 2, 3};
return new Array(arr);
}
public static void main(String[] args) {
Array a = f();
System.out.println(a.arr[0]);
System.out.println(a.arr[1]);
System.out.println(a.arr[2]);
}
}
In f you create variable arr which is an int array and then construct an Array object which ends up having a pointer to that same primitive int array.
Function f then ends returning the Array object - the variable arr goes out of scope but the memory location it points to is still referenced by the Array object being returned so the memory location cannot be garbage collected. The return value is then assigned to variable a of your main method meaning that the memory that arr originally pointed to still cannot be garbage collected until the main method ends. This is shown by the fact that the values of what was originally called arr are output as part of the main function
Short answer, yes this is safe to do. Memory is garbage collected when nothing is left pointing to it / when it is no longer referenced
It's safe because java uses references to track it. Even when arr goes out of scope in f, data is still referenced by a. Garbage collector will not clean it in the time it takes for the return value to be assigned, either.
On a side note, try to avoid using the same name both as local variable and field.
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 3 years ago.
i was working on stacks when i came across a problem where i had to double the array. i used this code which did not work but it should have.
class ArrayDouble
{
public static void main(String []args)
{
int arr[] = new int[10];
sizeChange(arr);
for(int i=0;i<arr.length;i++)
System.out.print(arr[i]+ " ");
}
public static void sizeChange(int arr[])
{
arr[0]=1;
arr = new int[2*arr.length];
arr[1]=1;
}
}
from what i have seen, any changes that takes place in an array which has been passed as a parameter, the changes reflect back in the actual parameters right? So why doesn't the change in size of the array is reflected in the original parameter?
Also, arr[0] becomes 1 in the original array but arr[1] remains 0. why does that happen?
PS: the problem was solved when i changed the return type of sizeChange to int[] and passed arr of sizeChange and collected it into the Main arr. So i dont need the correction of the code, i just need the answer as to why this is happening.
Thank you in advanced.
Arrays are not a primitive type in Java, but they are not objects either ... "
In Java, the called method can update the contents of the array, and it can update its copy of the array reference, but it can't update the variable in the caller that holds the caller's array reference. Hence ... what Java is providing is NOT pass-by-reference.
Like all Java objects, arrays are passed by value ... but the value is the reference to the array. So, when you assign something to a cell of the array in the called method, you will be assigning to the same array object that the caller sees.
This is NOT pass-by-reference. Real pass-by-reference involves passing the address of a variable. With real pass-by-reference, the called method can assign to its local variable, and this causes the variable in the caller to be updated.
Detailed Explaination :
Arrays are in fact objects, so a reference is passed (the reference itself is passed by value, confused yet?). Quick example:
// assuming you allocated the list
public void addItem(Integer[] list, int item) {
list[1] = item;
}
You will see the changes to the list from the calling code. However you can't change the reference itself, since it's passed by value:
// assuming you allocated the list
public void changeArray(Integer[] list) {
list = null;
}
If you pass a non-null list, it won't be null by the time the method returns.
This question already has answers here:
Where is allocated variable reference, in stack or in the heap?
(4 answers)
Closed 5 years ago.
please let me know where does my static reference, static primitive, object reference , object itself and method itself along with class information is stored.
*please let me know who does this memory management?
*please let me know what gets stored in permgen place?
*please specify the storage space(heap or stack) which will be allocated for all the object references,object, primitive data (for both static and non-static types) for the following program.
package training;
public class Memory {
static int var =1;
static String s="hi";
static Threadtutorial th;// this is another class in the same project,consider this an object.
static Threadtutorial tt = new Threadtutorial();
int are =2;
int d;
static float value;
public static void main(String[] args) {
// TODO Auto-generated method stub
int a;
int b=1;
Threadtutorial th;// this is another class in the nsame project,consider this an object.
Threadtutorial tt = new Threadtutorial();
final int var =1;
value=8;
}
void somemethod(){
int ne=3;
String something;
Object ref;
Object dereee= new Object();
}
static void another(int b){
int c=b;
Object ref2;
Object der= new Object();
}
}
Where things are conceptually per the JLS is one thing and deterministic, where they are physically in the JVM is another and varies with circumstances.
The easy part is where things are conceptually. Type definitions including method areas, space for static fields, and other type-level information are in the class area of heap. Method arguments and other method control information live on the stack as methods are invoked. Instances live on the heap.
Physically those things can live in various places at different times or even disappear altogether. Member variable values might live for a while on the stack or in registers while the rest of the object is not even in memory. Method calls might vanish altogether. The runtime interpreter/compiler combination has wide leeway in how it handles program logic.
Have you actually tried researching your question? What have you come up with?
Let's change the way I am asking the question. For constructing an object in a class, we can also use some other variables. Consider this example:
public class Foo {
int X1;
int X2;
public Foo(int a) {
int[] array=new int[4];
// ...
}
}
If we create 2 objects of this class, we will have 2 variables per object and totally the memory will be occupied for 4 integer variables. My concern is the memory dedicated to the integer array defined inside the constructor. How the memory will be assigned when creating several objects?
Thanks,
To answer your first question, yes. If you create an array in the main method of one class, then you create the same array again in the constructor of another class, then there will be two copies of that array in memory. More importantly, if you later modify one copy, the other copy will not be modified.
The best way to solve your problem is to pass the array into the constructor as a parameter. Then, you'll be able to access (and even modify) elements of the original array. For example:
public class Driver{
public static void Main(String[] args){
int[] array = {1, 2, 3};
CustomObject otherObject = new CustomObject(array);
}
}
//And, in a different file....
public class CustomObject{
public CustomObject(int[] array){
int x = array[0];
//etc..
}
}
If you have two references to the same object there won't be any useless memory usage.
For better understand how it works, look at the difference between stack and heap memory in Java
(Basically, your array in main method and the array defined in the class's constructor point to the same memory area)
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
public class Foo {
public static void change(int[] arr){
arr = null;
}
public static void change2(int[] arr){
arr[0] = 99;
}
public static void main (String[] args){
int[] arr = {1,2,3,4,5};
change(arr);
System.out.println("it should null: "+Arrays.toString(arr));
change2(arr);
System.out.println("updated array : "+Arrays.toString(arr));
} }
CONSOLE OUTPUT
it should null: [1, 2, 3, 4, 5]
updated array: [99, 2, 3, 4, 5]
I need to get understanding about pass by reference as i passed int[ ] to first method i.e change() it does not null the array as per my understanding it should change to NULL as array references are pass by reference but if i pass array to second method i.e change2() it changed the value at specific index. It means that reference is being passed.
It is because the Array in java are objects, and the array reference variable is passed by value in public static void change(int[] arr){ , hence you cannot change the reference variable by doing:-
arr = null;
//or
arr=new int[10];
But you can change the object pointed by the copy of array reference variable (i.e arr passed to the method):-
arr[0]=1
This is not pass by reference. In Java everything is passed by value. What gets passed to the method is copy of the reference. Since this new reference is also pointing (referencing) the same object, you can manipulate the object using new reference.
But if you assign a different object to this new reference, it will not change which object is pointed (referenced) by the old reference. Old reference still points the same object, which it used to point. So no problem for old reference.
So the outputs are perfectly fine.
C# allows pass by ref. Though to mention this.
This question already has answers here:
Changing array in method changes array outside [duplicate]
(2 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
method(arr);
System.out.println(arr[0]);
}
private static void method(int[] array)
{
array[0] = 2;
}
}
After invoking method, arr[0] becomes 2. Why is that!?
You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.
If Java were pass by reference, this would pass:
public class Test {
public static void main(String[] args) {
Test test = new Test();
int j = 0;
test.setToOne(j);
assert j == 1;
}
public void setToOne(int i) {
i = 1;
}
}
Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm
This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.
When you pass an object -- including arrays -- you pass the object itself. A copy is not created.
If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)
Here is the code above, annotated:
public static void main(String[] args)
{
int[] arr = new int[5]; // create an array object. let's call it JIM.
// arr evaluates to the object JIM, so sets JIM[0] = 1
arr[0] = 1;
System.out.println(arr[0]); // 1
method(arr); // fixed typo :-)
// arr still evalutes to JIM
// so this will print 2, as we "mutated" JIM in method called above
System.out.println(arr[0]); // 2
}
private static void method(int[] array)
{
// array evaluates to the object JIM, so sets JIM[0] = 2
// it is the same JIM object
array[0] = 2;
}
Happy coding.
*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.
Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.
Additional:
Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?
Make copy of array Java -- note this only creates a "shallow" copy.
Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.
A quick example for thought:
If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.
Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method
however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place
method(arr[0]);
I think that's supposed to be
method(arr);
But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.
Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.