Java Memory, Pass-by-Value, Pass-by-Reference [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is Java pass by reference?
I have a question about passing by value and passing by reference in java.
I have a "Graph" class that I wrote to display a long array of doubles as a graph, The (simplified) constructor looks like this.
private double[] Values;
public Graph(double[] values) {
Values = values;
}
The array can be quite long and take up a reasonable amount of memory.
Essentially my question is this: If I call the constructor to create a new graph, will the array "Values" be a copy of the array that's passed to it, or will it be a reference?
In my mind, Primitives are "pass by value" and Objects are "pass by reference", which should mean that the array would be a copy. Although I'm aware that this definition is not technically correct.
If I am correct, and the array is a copy, what would be the best way to reduce the amount of memory this class uses, and reference the array from another class?
Would an abstract GetValues() method be a good way of achieving this?
Thanks in advance,
Chris.

While double is a primitive type, double[] is an Object type (array), so, no, the entire array will not be passed to the constructor, instead the array will be passed as "value of a reference". You will not be able to replace the array inside the constructor, but you could, if you wanted, replace individual values in the array.

Java is pass-by-value, period.
See the JLS, 4.12.3 Kinds of Variables:
Method parameters (§8.4.1) name argument values passed to a method. For every parameter declared in a method declaration, a new parameter variable is created each time that method is invoked (§15.12). The new variable is initialized with the corresponding argument value from the method invocation. The method parameter effectively ceases to exist when the execution of the body of the method is complete.
EDIT: To clarify my answer: The types of Java are divided in two categories: The primitives and the reference types. Whenever you call a method (or a constructor), the parameters get copied (because Java is pass-by-value). The primitives get copied entirely and for reference types, the reference gets copied. Java will never automatically deep copy anything, so as arrays are reference types, only the reference to the array gets copied.

It will be a reference of values. Java is Pass-by-value, but what's passed by value is a reference to the array, as the array is an object.
See also this answer, from just a few days ago.

It will be a reference. the parameter values is passed "reference by value", and the reference is attached to Values.
Thus - any cahnge to Graph.Value will also be reflected to values and vise versa.

Array is a reference type, passing by copy applies only to primitive types, which an array isn't. The other reference types include classes and interfaces, by the way.

// Points:
// 1) primitive variables store values
// 2) object variables store addresses(location in the heap)
// 3) array being an object itself, the variables store addresses again (location in the heap)
// With primitives, the bit by bit copy of the parameters, results in the
// value being copied. Hence any changes to the variable does not propagate
// outside
void changePrimitive(int a) {
a = 5;
}
// With objects, the bit by bit copy of the parameters, results in the address
// begin copied. Hence any changes using that variable affects the same object
// and is propogated outside.
class obj {
int val;
}
void changeObject(obj a) {
a.val = 10;
}
// Array is itself an object which can hold primitives or objects internally.
// A bit by bit copy of the parameters, results in the array's address
// being copied. Hence any changes to the array contents reflects in all
// the locations having that array.
void changeArray(int arr[]) {
arr[0] = 9;
arr[1] = 8;
}
// NOTE: when object/array variable is assigned a new value, the original
// object/array is never affected. The variable would just point to the
// new object/array memory location.
void assignObj(obj a) {
a = new obj();
a.val = 10;
}

Related

What's the deal with object array in java?

I know java is pass by value, period. However, I still can't figure out this.
public static void changeTheName(String obj){
obj.toUpperCase();
}
This method will not affect the original string object, Fairly understandable. Because strings are immutable and changing in string literals means that the reference variable will now refer to the new object and the old one will be left for the garbage collector. But when I pass a string array I'm able to change the string literals that means I'm able to change the references. Why is this happening with the array because if we do obj[]= new String[]{} it will not affect to the original array and the original still refers to the old array and that is similar to directly changing the string literals
public static void ChangeTheName(String obj[]){
for(int i=0;i<obj.length();i++) obj[i]=obj[i].toUpperCase;
}
Edit:
The answer I was looking for is that reference of obj and obj[0] are unique and that's why the second method is able to change the entire content of my array. As I'm from C background and I thought obj and obj[0] has same refernces but that is not the case in java for sure.
toUpperCase does not change the String, it returns a new String which is uppercase.
#karthikdivi said - toUpperCase() does not change the String. it returns a new String which is uppercase.
But as i understand that you want to know why object value is changed in method but not premitive data type value?
Although Java is strictly pass by value, the precise effect differs between whether a primitive type or a reference type is passed.
.
When we pass a primitive type to a method, it is passed by value. But when we pass an object to a method, the situation changes dramatically, because objects are passed by what is effectively call-by-reference. Java does this interesting thing that’s sort of a hybrid between pass-by-value and pass-by-reference. Basically, a parameter cannot be changed by the function, but the function can ask the parameter to change itself via calling some method within it.
While creating a variable of a class type, we only create a reference to an object. Thus, when we pass this reference to a method, the parameter that receives it will refer to the same object as that referred to by the argument.
This effectively means that objects act as if they are passed to methods by use of call-by-reference.
Changes to the object inside the method do reflect in the object used as an argument.
if you are doing like below will only change the value.
public static void(String obj[]){
for(String s:obj) {
s=s.toUpperCase();
}
}
I think thus make changes.

Java, passing variables/objects into a function [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
I'm interested to know exactly what's happening under the bonnet when passing a variable or object into a function.
When passing an object or variable into a function, is a new copy of the object/variable created in the new scope? (A set of parentheses constitutes a scope in java right?). Or is the reference to the existing variable/object in memory passed in? Although that would only make sense for a global object/variable?
java is always pass by value so a new variable or reference variable(which refer to some object) will be created in the function to receive the value that has passed to it...
The scope of these variable will be withing that function in which it has created.
One thing you should know that even object are passed by value in java...when people say we pass the object to method ,that time we actually pass the value referred by reference variable not the object...so both the old and new reference variable refer to same object in heap memory..
check this for reference...
http://javadude.com/articles/passbyvalue.htm
http://www.programmerinterview.com/index.php/java-questions/does-java-pass-by-reference-or-by-value/
The easiest way to think of this is to get away from thinking of variables as ever being objects. A reference variable or expression is either null or a pointer to an object of appropriate class for its type.
Under this model, all Java argument passing is by value.
When you pass a reference to a method, you pass the null-or-pointer value to it. Assignment to the argument only affects the argument. It does not affect any variables in the caller's environment. On the other hand, if it is not null it points to the same object as the caller's variable or expression pointed to. Calling a value-changing method in that object changes its value for all code using a pointer to that object, including the caller.
Both - you get a copy of the object reference (for objects), and a copy of the value for primitives.
So unlike C, you can't pass in a variable reference (for a string for example) and end up with it being repointed to something else. And you can't pass in an int, for example, and change it's value within the method - any changes it to it will only be within the method scope.
e.g:
MyObjectHolder holder = new MyObjectHolder();
holder.setObject(new Object());
//holder reference id = 1
// holder.object reference id = 2
doIt(holder);
public void doIt(MyObjectHolder methodScopeHolder) {
// methodScpeHolder reference id = 3
// methodScopeHolder.object reference id = 2
}
In Java your program's "local" variables are maintained in a "stack frame", which is a section of a large array whose elements can contain any data type.
When you call, you copy the parameters (which may be either "scalars" -- chars, ints, floats, etc -- or "references") into a new area of the array (the "top"). Then, during the call, the index values that control which elements of the array you can access are adjusted, and the copied parameters become the "bottom" of a new stack frame, with the called method's local variables being above parameters. So to the new method its copies of the parameters are just like local variables.
Effectively, each method has a "window" into the overall stack, and the "windows" overlap to cover the parameter list.
Of course, when you "pass" an object you're really just passing a reference to the object, and the object itself is not copied.
When you pass a variable, you are passing the reference.
When you pass an object, you are passing a copy of it.

Are arrays passed by value or passed by reference in Java? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 2 years ago.
Arrays are not a primitive type in Java, but they are not objects either, so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?
Everything in Java is passed by value. In case of an array (which is nothing but an Object), the array reference is passed by value (just like an object reference is passed by value).
When you pass an array to other method, actually the reference to that array is copied.
Any changes in the content of array through that reference will affect the original array.
But changing the reference to point to a new array will not change the existing reference in original method.
See this post: Is Java "pass-by-reference" or "pass-by-value"?
See this working example:
public static void changeContent(int[] arr) {
// If we change the content of arr.
arr[0] = 10; // Will change the content of array in main()
}
public static void changeRef(int[] arr) {
// If we change the reference
arr = new int[2]; // Will not change the array in main()
arr[0] = 15;
}
public static void main(String[] args) {
int [] arr = new int[2];
arr[0] = 4;
arr[1] = 5;
changeContent(arr);
System.out.println(arr[0]); // Will print 10..
changeRef(arr);
System.out.println(arr[0]); // Will still print 10..
// Change the reference doesn't reflect change here..
}
Your question is based on a false premise.
Arrays are not a primitive type in Java, but they are not objects either ... "
In fact, all arrays in Java are objects1. Every Java array type has java.lang.Object as its supertype, and inherits the implementation of all methods in the Object API.
... so are they passed by value or by reference? Does it depend on what the array contains, for example references or a primitive type?
Short answers: 1) pass by value, and 2) it makes no difference.
Longer answer:
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.
But not in Java. 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.
Here are some links that explain the difference between pass-by-reference and pass-by-value. If you don't understand my explanations above, or if you feel inclined to disagree with the terminology, you should read them.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/cplr233.htm
http://www.cs.fsu.edu/~myers/c++/notes/references.html
Related SO question:
Is Java "pass-by-reference" or "pass-by-value"?
Historical background:
The phrase "pass-by-reference" was originally "call-by-reference", and it was used to distinguish the argument passing semantics of FORTRAN (call-by-reference) from those of ALGOL-60 (call-by-value and call-by-name).
In call-by-value, the argument expression is evaluated to a value, and that value is copied to the called method.
In call-by-reference, the argument expression is partially evaluated to an "lvalue" (i.e. the address of a variable or array element) that is passed to the calling method. The calling method can then directly read and update the variable / element.
In call-by-name, the actual argument expression is passed to the calling method (!!) which can evaluate it multiple times (!!!). This was complicated to implement, and could be used (abused) to write code that was very difficult to understand. Call-by-name was only ever used in Algol-60 (thankfully!).
UPDATE
Actually, Algol-60's call-by-name is similar to passing lambda expressions as parameters. The wrinkle is that these not-exactly-lambda-expressions (they were referred to as "thunks" at the implementation level) can indirectly modify the state of variables that are in scope in the calling procedure / function. That is part of what made them so hard to understand. (See the Wikipedia page on Jensen's Device for example.)
1. Nothing in the linked Q&A (Arrays in Java and how they are stored in memory) either states or implies that arrays are not objects.
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.
No that is wrong. Arrays are special objects in Java. So it is like passing other objects where you pass the value of the reference, but not the reference itself. Meaning, changing the reference of an array in the called routine will not be reflected in the calling routine.
Everything in Java is passed by value .
In the case of the array the reference is copied into a new reference, but remember that everything in Java is passed by value .
Take a look at this interesting article for further information ...
The definitive discussion of arrays is at http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803 . This makes clear that Java arrays are objects. The class of these objects is defined in 10.8.
Section 8.4.1 of the language spec, http://docs.oracle.com/javase/specs/jls/se5.0/html/classes.html#40420 , describe how arguments are passed to methods. Since Java syntax is derived from C and C++, the behavior is similar. Primitive types are passed by value, as with C. When an object is passed, an object reference (pointer) is passed by value, mirroring the C syntax of passing a pointer by value. See 4.3.1, http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3 ,
In practical terms, this means that modifying the contents of an array within a method is reflected in the array object in the calling scope, but reassigning a new value to the reference within the method has no effect on the reference in the calling scope, which is exactly the behavior you would expect of a pointer to a struct in C or an object in C++.
At least part of the confusion in terminology stems from the history of high level languages prior to the common use of C. In prior, popular, high level languages, directly referencing memory by address was something to be avoided to the extent possible, and it was considered the job of the language to provide a layer of abstraction. This made it necessary for the language to explicitly support a mechanism for returning values from subroutines (not necessarily functions). This mechanism is what is formally meant when referring to 'pass by reference'.
When C was introduced, it came with a stripped down notion of procedure calling, where all arguments are input-only, and the only value returned to the caller is a function result. However, the purpose of passing references could be achieved through the explicit and broad use of pointers. Since it serves the same purpose, the practice of passing a pointer as a reference to a value is often colloquially referred to a passing by reference. If the semantics of a routine call for a parameter to be passed by reference, the syntax of C requires the programmer to explicitly pass a pointer. Passing a pointer by value is the design pattern for implementing pass by reference semantics in C.
Since it can often seem like the sole purpose of raw pointers in C is to create crashing bugs, subsequent developments, especially Java, have sought to return to safer means to pass parameters. However, the dominance of C made it incumbent on the developers to mimic the familiar style of C coding. The result is references that are passed similarly to pointers, but are implemented with more protections to make them safer. An alternative would have been the rich syntax of a language like Ada, but this would have presented the appearance of an unwelcome learning curve, and lessened the likely adoption of Java.
In short, the design of parameter passing for objects, including arrays, in Java,is esentially to serve the semantic intent of pass by reference, but is imlemented with the syntax of passing a reference by value.
Kind of a trick realty... Even references are passed by value in Java, hence a change to the reference itself being scoped at the called function level. The compiler and/or JVM will often turn a value type into a reference.

Confusion over Java's pass-by-value and immutability

In preparation for the SCJP (or OCPJP as it's now known) exam, I'm being caught out by some mock questions regarding pass-by-(reference)value and immutability.
My understanding, is that when you pass a variable into a method, you pass a copy of the bits that represent how to get to that variable, not the actual object itself.
The copy that you send in, points to the same object, so you can modify that object if its mutable, such as appending to a StringBuilder. However, if you do something to an immutable object, such as incrementing an Integer, the local reference variable now points to a new object, and the original reference variable remains oblivious to this.
Consider my example here :
public class PassByValueExperiment
{
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder();
sb.append("hello");
doSomething(sb);
System.out.println(sb);
Integer i = 0;
System.out.println("i before method call : " + i);
doSomethingAgain(i);
System.out.println("i after method call: " + i);
}
private static void doSomethingAgain(Integer localI)
{
// Integer is immutable, so by incrementing it, localI refers to newly created object, not the existing one
localI++;
}
private static void doSomething(StringBuilder localSb)
{
// localSb is a different reference variable, but points to the same object on heap
localSb.append(" world");
}
}
Question : Is it only immutable objects that behave in such a manner, and mutable objects can be modified by pass-by-value references? Is my understanding correct or are there other perks in this behaviour?
There is no difference between mutable and immautable objects on the language level - immutability is purely a property of a class's API.
This fact is only muddled by autoboxing which allows ++ to be used on wrapper types, making it look like an operation on the object - but it's not really, as you've noticed yourself. Instead, it's syntactic sugar for converting the value to a primitive, incrementing that, converting the result back to the wrapper type and assigning a reference to that to the variable.
So the distinction is really between what the ++ operator does when it's used on a primitive vs. a wrapper, which doesn't have anything to do with parameter passing.
Java itself has no idea of whether an object is immutable or not. In every case, you pass the value of the argument, which is either a reference or a primitive value. Changing the value of the parameter never has any effect.
Now, to clarify, this code does not change the value of the parameter:
localSb.append(" world");
That changes the data within the object that the value of the parameter refers to, which is very different. Note that you're not assigning a new value to localSb.
Fundamentally, you need to understand that:
The value of an expression (variable, argument, parameter etc) is always either a reference or a primitive value. It's never an object.
Java always uses pass-by-value semantics. The value of the argument becomes the initial value of the parameter.
Once you think about those things carefully, and separate in your mind the concepts of "variable", "value" and "object", things should become clearer.

Passing references type variable as method parameter

After running the code below I get this output:
Eve
1200
Could anyone explain me why the value of Person type variable is being changed and value of Integer type variable is not?
I have already read this:
www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
www.yoda.arachsys.com/java/passing.html#formal
but I don't get why with Person and Integer types it works different.
public class Test {
public static void main(String[] args) {
Object person = new Person("Adam");
Object integer = new Integer("1200");
changePerson(person);
changeInteger(integer);
System.out.println(person);
System.out.println(integer);
}
private static void changeInteger(Object integer) {
integer = 1000;
}
private static void changePerson(Object person) {
((Person)person).name="Eve";
}
}
In Java, primitive types (such as integer) are always handled exclusively by value, and objects (such as your Person) and arrays are always handled exclusively by reference.
If you pass a primitive the value will be copied, if you pass a reference type the address will be copied, hence the differences.
If you follow those links above and/or do a bit of googlin' you'll find out more.
In the Integer case, you're changing the value of the parameter itself (which is local to the method). In the Person case, you're changing the value of a field inside the parameter. That field is part of the object, and so it's visible to the caller.
In changeInteger() when you do integer = 1000 a new object is created and assigned a local variable integer.
So if you do
person = new Person();
person.name="Eve";
in changePerson()
you will get the same behavior as for integer.
PS: The old references are lost once you assign it to newly created objects inside the function.
Just for any future reference,the accepted answer isn't the correct answer in this case (although the links do provide enough informaiton to get the correct answer). The OP problem has nothing to do with primitves vs objects. In the exampe code given, there are no primitives used, both integer and person are full objects. Answers below that answer are more helpful. The key is that the parameter variable (i.e. the variable used to store the passed in parameter in the methods) is given the current value of variable used in the method call. Objects are stored by reference in Java, so they point to the object rather than storing the object directly. So the parameter variable in the method is given this pointer address and uses this to access the object details. So if the method changes the object, this is the same object that the calling code is pointing towards and so both places will see the change. In the integer example, when you say integer = 1000, it is overwriting the passed in pointer with a new pointer to a new Integer object - you have lost the connection to the original object.
Note that is no way to change an Integer object once it has been created (e.g. no .setValue() method) so there is no way to write the code in a way that could change the original Integer object.
In changePerson() you change the given object itself via his public name property.
In changeInteger() you change the local Integer Object;
Put a System.out.println(integer); inside the changeInteger() function and you will see, that the Integer changes, but only in function scope..
private static void changeInteger(Object integer) {
integer = 1000;
System.out.println(integer);
}
In the changeInteger() method you are assigning a completely new object (1000) to the reference variable integer. But the reference variable integer in the main() method still points to the old object (1200). Thus the print() statement in the main() method prints the old value (1200)
However, in the changePerson() method the reference variable person still points to the old object. Just that a value of one of its field is being change.
Aslo, do keep in mind that Integer (and so are other primitive wrappers) mutable. Any time you need to assign a new value to the ref var, JDK will create a whole new object.
Hope this helps!
Your code below compiles? It needs a cast.
private static void changeInteger(Object integer) {
integer = 1000;
}
Your integer will be changed if it was embedded in another object e.g. Person.
EDIT :
Wrong on the compilation issue. In Java, references are copied by value. So in first case the reference get pointed to different memory. In the second case, name comes as part of Person. Since you are changing name through Person without changing Person, change in name is reflected outside method. Hope this helps.

Categories