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.
Related
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.
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;
}
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.
I have a function that returns a user-defined object. First I want to know if that object is returned by reference and what if it was private?
Also, how do I return it as Constant (final) reference because I don't want someone to mess with it? I'm so confused between returning an object and returning object.copy(); or object.clone();
In Java, You always return a reference (unless returned value is a primitive type such as int, float, char, ...).
So, if you don't want the returned object to be modified, you must return a full copy of it (you could use Clonable interface and clone method if your class defines it).
So, to answer your questions you have to at first know how Java passes Variables.
a Variable has a value:
int i = 1234;
Person p = new Person("Peter");
Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.
so i contains 1234 and p contains the adress (let's say a4dfi3).
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
somePerson.rename("Homer");
}
so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to).
So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
somePerson = new Person("Walter");
}
In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s.
BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".
Now, let's see how this behaves with primitives:
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
someInt++;
}
So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.
This is the big difference between Objects and primitives in Java.
Now to your questions:
1. As you can read here, yes Java always passes the Reference Adress of the Object.
2. If you don't want someone to mess with the values of your Objects, you HAVE to first create a new Object with that information (e.g with Cloneable and clone()), but it's a real mess because you have to make sure, that everything in your Object that is not primitive gets re-created, which is just awful when you have huge Tree-structures of Objects.
I hope I could help,
Ferdi265
What you should really realize is that there is nothing special about "passing" or "returning". Whenever you "pass" or "return" something, it just passes the value of the thing. Period. For any type. Whenever you "pass" or "return" something, it's exactly the same as simply assigning it to a variable.
However, what is the value of the thing you are passing or returning? That is where your confusion seems to lie. Your question asks about "returning an object"; however, such a thing does not make sense in Java. Objects are not values in Java. It is impossible to have a variable whose value is an object.
The only types in Java are primitive types and reference types. Hence the only values are primitives and references. (References are pointers to objects.) In Java, we only manipulate objects through references (pointers to objects). We cannot store an object in a variable; but we can store a reference (pointer to an object) in a variable. So when you talk about passing or returning objects, you are almost certainly instead talking about passing or returning references. And, as said before, there is nothing special about passing or returning references -- the value of the reference (a pointer) is passed or returned.
It returns the object's reference.
say suppose you have a method call like.
Object obj = makeObject();
which creates an Object and returns(which is the reference of the object created in the makeObject method).
1) Yes, it returns a reference to the object.
2) If the method is private, then it can only be called from within the class itself.
3) Making an object final does not stop others from calling methods on it. There are ways to make an object immutable by using packages and method visibility. (Look up how public, protected, and private work)
4) There is no Object.copy()
5) Object.clone() is a messy beast.
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.