I've been reading many posts about this, all are full of answers that tend to counter the answer before it and they all seem to be by high ranked people so im very confused and would just like to know if this works:
public class Object{
private int someNumber = 5;
public void setSomeNumber(int newNumber){someNumber = newNumber;}
}
public class Main {
Object myObject = new Object();
public static void main(String[] args){
changeNumber(myObject);
}
void changeNumber(Object obj)
{
obj.setSomeNumber(10);
}
}
Would this change myObject.someNumber to 10?
My understanding is that obj is pointing to the same place in memory as myObject so calling its method useing obj is the same as calling it with myObject because obj is not just a copy of myObject?
I thought it was clear to me till i started reading threads on here about it lol
Edit: Thanks for correcting code, i just wrote it out in here as a example, didnt see the mistakes
Thanks guys. Also i was confused by people saying pass by value so i wasnt sure if it was passing the address in memory or not because to me thats passing a refrence so it became unclear to me.
You are correct. changeNumber() would change the someNumber variable of the object passed to it. You are passing a reference to the object itself, not a copy.
Although this code won't compile (you can't use Object, and can't access from static method non static data field), but I've got your question.
Basically you're right, and this is why:
In Java when you pass parameters into the method, they're passed by reference, but the reference itself is passed by value.
This is done for optimization reasons I believe.
So in fact, another reference is produces that points to the same Object in memory.
If you take a look on these references by themselves they're different, but they both point on the same object. So when you change the internal state of the object from within 'changeNumber' method, its goes to the object that reference 'obj' refers to and changes it.
The only exception is primitives - they aren't passed by reference, instead they're passed by value as you probably have learnt in other languages.
Once you get aware of what exactly goes on when you call methods and pass parameters to it this will stop confusing you :)
Hope this helps
You are right, java does manipulate objects by reference, and all object variables are references, and doesn't pass method arguments by reference but by value.
Take a look at this article and see the difference in behaviour between objects and method arguments in the examples provided.
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 months ago.
I'm Ryan who's a rookie in programming. I was going through the OOP part of my textbook today and I found a part that I won't understand at all. There are 2 codes, I'll have them copied here.
The first one is :
public class Change {
public static void main(String[] args) {
int x = 17;
dontChange(x);
System.out.println(x);
}
static void dontChange(int z) {
z = 42;
}
}
When the code was executed. The output would still be 17, which is not the expected 42(in my understanding of parameter and Method.)
The textbook provided another example as well, which results in a change.
public class Change {
void change(Student s) {//student is a type
s.name = "Fred";
public static void main(String[] args) {
stu.name = "Jane";
change(stu);
System.out.println(stu.name);
}
}
This code would result in the output the name as 'Fred', I was wondering where's the difference between them and what was the reason behind these codes when they look similar and worked totally differently.
Thank you for going through the whole post, I wish you have a great day!
You need to distinguish between “passing by value” and “passing by reference”. Maybe this helps
If you want to understand the answer to this Question, why the value does not change, you have to understand, why the value sometimes change.
The values changes,if the Datatyp is referencial. This means, that the data is stored at the heap(a part of memory) and our variable only points to this data. This means, that your variable only stores, where the data is really stored.
If we change our data,we are following our reference and change it there.
This means, that every reference, which points at our data is also changed. It is the same object.
What happens here is different. You are not dealing with referencial Datatyps.
You are dealing with primitives(int, float, char....). Those datatyps aren't stored in the heap. They are stored in the stack(another part of memory). This means, that the data is really stored in our variable. So, if we change our data in our variable, we aren't following an reference and change it there. We are really changing the value in our variable.
An analogy:
Referencial types are like notes, which point to a different note. In the second note is the data. If we try to change the datanote, we take a look at our first note with the reference to the datanote and then change the datanote. Any note pointing to the datanote has now the updated data.
primitives are like, if our first note has all the data. There is no pointing to somewhere else. It is our data
Primitives start most of the time with a lower case letter. Primitives can't have any functions or anything.
Refercal start most of the time with a Capital letter. They can have functions and are most of the time classes
What you wanted to do was to return the new value and set it equal to x.
I hope, i've helped you a bit.
If you have any Questions left, feel free to ask
sorry for my English:)
Firstly, I would point out the difference between the two examples you've shown. The method Change#change(Student)
public class Change {
public void change(Student s) {
s.name = "Fred";
}
}
Compared to Change#dontChange(int)
public class Change {
public void dontChange(int i) {
i = 42;
}
}
The most notable difference between these two methods is where they assign (=) the value they're passing. s.name vs i. Note the presence of the dot operator (.) indicating that there's access of an Object's field or method. This can help start the explanation of why change(Student) updates the value it assigns to as compared to dontChange(int).
There was reference of looking into the difference between pass-by-value and pass-by-reference in other answers, and that will be required information for WHY this happens. However, I think there should be a slightly deeper understanding of what a variable is in java for that to help explain it. The easiest explanation I find is that a variable in java is a number. Period. Always. Now that might seem weird, right? You obviously have an object when you do Student stu = new Student(), but that's only partially correct. You do instantiate (create/construct) an object, but the value stored in Student stu can actually be thought of as a number pointing to a spot in memory where stu's values are stored. There IS a difference in how these number are handled, but they are, in essence, all numbers.
Knowing this, you can work with the thought that values passed to a method in java are always passed-by-value. If you wanted to test this you could see the output of changing the body of Change#change(Student) to
public class Change {
void change(Student s) {
Student newStudent = new Student();
newStudent.name = "Fred";
s = newStudent;
}
}
You may expect the output name to still be "Fred", but it should result in "Jane". We didn't modify the object that Student s refers to, we updated what the variable s points to. The difference being that in the original Change#change(Student) method you assigned the value "Fred" to the name field (s.name) of the object that Student s refers to.
When you call Change#change(Student) with the variable stu the parameter s's value becomes the same identifying number that stu points to, but the variables themselves are entirely different. They only, when s is initialized, have the same value (a number pointing to a space in memory).
It should be noted that assigning "Jane" and "Fred" to the Student's name field is actually assigning a reference to a String which represents "Jane" or "Fred" to the Student's name field. As the name field's type is, assumed to be, String which is not a primitive type. Meaning it's a reference to some String object in memory.
What is happening here is passing by value and passing by reference. In Java all primitive types(int, char...) are passed by value to any method, this means the value of them are copied for the method to use.
Anything else like objects from classes you create are passed by reference. This means the contents of the object are not copied but the address of where that object is in memory is copied to the method. The value at this address(the original object) is then used within the method meaning changes to it are seen outside of the method.
To go into more detail and why this happens can get quite confusing as a beginner but other people have linked good articles to read. To put it simply in my own words.
Whenever you are using an object(non-primitive type) i.e Student. Java is actually seeing this as an address to that object but to keep things easier for the programmer Java doesn't make you declare this in any way. Any access to this object is automatically handled by Java to mean the value of the address you are using.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
Java is pass-by-value. This means that a called method acts on a copy of an object that was passed in, not on the original object.
If the object is not changed in the method, creating an actual copy seems unnecessary. So a compiler that implements the program to create such a copy would be pretty inefficient. Are all Java compilers (javac, gcj, ECJ, etc.) really doing that?
At least in the case where a parameter is declared final it would make a lot of sense not to copy.
EDIT
OK, so objects are not copied. I got confused because String is special in that it is copied (immutable). Sorry about my unknowings. Just to make up for it, here is a thousandth example of what happens when an object is passed:
import java.lang.System;
class C { int member; }
public class Test {
static void subMethod(C object) { object.member=1; }
public static void main(String[] args) {
C object = new C();
object.member=0;
subMethod(object);
System.out.println(object.member); // prints "1"
}
}
Yes, Java is always pass-by-value. But for objects, it passes the reference value. In other words, the object isn't copied, but its reference is. Changing an object's attributes inside a method changes it outside the method as well.
From here,
However, Objects are not passed by reference. A correct statement would be Object references are passed by value.
On-topic: the compiler simply copies the reference to its chunk of memory in the stack.
Objects in Java are references, and it is this reference which is passed by value; meaning Java is pass-by-reference with objects for practical purposes.
EDIT
It seems my use of the term 'practical purposes' is causing a lot of controversy, so let me clarify. I simply meant that what most people think of when they think of 'pass-by-reference' is that changes to the passed in value are persisted outside of that method, which is the case in Java. e.g.
void someMethod(SomeClass a) {
a.mutateState();
}
SomeClass a = new SomeClass();
someMethod(a); //passes reference to a by value;
a.methodInvolvingSomeState(); //mutations of object state persist to here, as if the previous call were pass-by-reference.
That's all I meant by 'for practical purposes'; OP was under the impression that a copy of a was made, which I was trying to explain was not true. I am fully aware that java is always pass-by-value, hence explicitly stating that it is the reference that is passed by value. As has been pointed out in the comments there are plenty of occasions where it is not the same as if it were actually pass-by-reference, and it was not my intention to indicate that any of those were possible in Java.
I can't understand why the overloaded function 'increase' does not change Integer but does change Point.
The propuse of 'Integer' class is to wrap int so it will be a reference Type.
import java.awt.Point;
public class test2 {
public static void main(String[] args) {
///1
Integer i = new Integer(0);
increase(i);
System.out.println(i);
///2
Point p = new Point(0,0);
increase(p);
System.out.println(p);
}
public static void increase(Integer i){
i = 1;
}
public static void increase(Point p){
p.setLocation(1, 1);
}
}
the output is :
0
java.awt.Point[x=1,y=1]
Also, is their a simple way to pass a variable to a function by reference in Java?
Integer class is an immutable class, that means its content can't be changed after it's created.
Also, Java is pass-by-value so the variable i is passed by value, and the fact that it changes inside the function has no effect on the caller.
Read here: http://en.wikipedia.org/wiki/Immutable_object for more information on immutable objects.
The simple answer is that Java uses pass by value, not pass by reference.
In the Point case, the method is changing a field of the point object whose reference was passed into the method.
In the Integer case, the method is simply assigning a new value to the local variable i. This does not update the variable i in the calling method, because Java uses pass by reference.
The other issue is that Integer has no setValue methods because it is immutable. If you want to do the equivalent of what the Point version of the method is doing, you will have to define an IntegerHolder class that has both a getter and a setter, together with methods such as increase, that your application needs. (Alternatively, find such a class in a 3rd party library.)
Integer objects are immutable, i.e. you can't change them. If you could, the syntax would be like
i.setValue(1);
If you want to pass a non-object by reference, you can either wrap it in an array of length 1 or (better) create a trivial wrapper. However, there is little reason to do so - don't port your code from C 1:1. Usually, you should have a semantically loaded object, like an Account on which you can call the increase and decrease (or maybe just setBalance) methods.
In this function:
public static void increase(Integer i){
i = 1;
}
autoboxing makes this equivalent to:
public static void increase(Integer i){
i = new Integer(1);
}
i.e. it changes the reference that i contains, not the value that it contains. The Integer object is itself immutable, there's actually no way to change the value of one after it has been created.
Since that reference is a local variable, any changes to it will not affect the variable that was passed in.
When you write i = 1, you are changing the i parameter to point to a new boxed Integer instance.
The original Integer instance that you passed to the function is not—and cannot be—changed—Integers are immutable
Answer here: http://www.javaworld.com/javaworld/javaqa/2000-06/01-qa-0602-immutable.html
This reference could be useful: http://javadude.com/articles/passbyvalue.htm
If you wanted the two methods to be equivalent, the second one would look like this:
public static void increase(Point p){
p = new Point(1, 1);
}
And then you would see that it outputs the original point here, too.
There is no pass a variable to a function by reference in Java.
You can simulate it by passing an object which contains the variable (like you did in your increase(Point) method) - you'll have to be sure to assign to the variable, though, not to the object containing the variable.
As said before, there are several "mutable wrappers" around (for example org.omg.CORBA.IntHolder and java.util.concurrent.AtomicInteger in the standard API), but it is not difficult to create your own, and in most cases it would be better to use a sensible "Business object" like an "Account" instead.
Is there any way that I can pass mutable Objects by value to a function in java?
What I actually want is to pass an object to a method, do some operations on it (change it) and again call that method with that old object only(not the changed value).
here is some sample:
{ MyObj obj = new MyObj(); obj.setName("name");
append(obj);
System.out.println(obj.name);
prepend(obj);
System.out.println(obj.name);
}
void append(MyObj obj){ obj.name+="1"; }
void prepend(MyObj obj){ String a = "1"; obj.name=a+obj.name; }
At the end of this code, I want output as:
name1
1name
Objects themselves aren't passed at all in Java. Ever.
But everything is passed by value - where the only things that can be passed are primitive values and references.
It's not quite clear what you're trying to do - is the idea that you'd like to have a method with (say) a StringBuilder parameter, but without any changes made to the object from within the method being visible to the caller? If so, you basically need to clone the object yourself.
Unfortunately, no. Java never passes Objects by value, it passes the reference of the object by value.
Explanation from here:
What's really happening is that
objects are always held by reference
in java -- never by value -- and the
references are, indeed, being passed
by value.
Why do you need to do this? If you don't change the object, then it doesn't matter. If you do change the object, and don't want to affect the caller's object, then just make a copy locally. But I would guess that at least 90% of the time people think they need to do that, they really don't.
Show some code. What are you really trying to do?
AFAIK immutable/mutable is not related with passing by value/reference. Strings are passed by reference, not value. What makes string immutable is design of string class itself.
Perhaps you may explain a bit more what you looking for.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Java “pass-by-reference”?
I found an unusual Java method today:
private void addShortenedName(ArrayList<String> voiceSetList, String vsName)
{
if (null == vsName)
vsName = "";
else
vsName = vsName.trim();
String shortenedVoiceSetName = vsName.substring(0, Math.min(8, vsName.length()));
//SCR10638 - Prevent export of empty rows.
if (shortenedVoiceSetName.length() > 0)
{
if (!voiceSetList.contains("#" + shortenedVoiceSetName))
voiceSetList.add("#" + shortenedVoiceSetName);
}
}
According to everything I've read about Java's behavior for passing variables, complex objects or not, this code should do exactly nothing. So um...am I missing something here? Is there some subtlety that was lost on me, or does this code belong on thedailywtf?
As Rytmis said, Java passes references by value. What this means is that you can legitimately call mutating methods on the parameters of a method, but you cannot reassign them and expect the value to propagate.
Example:
private void goodChangeDog(Dog dog) {
dog.setColor(Color.BLACK); // works as expected!
}
private void badChangeDog(Dog dog) {
dog = new StBernard(); // compiles, but has no effect outside the method
}
Edit: What this means in this case is that although voiceSetList might change as a result of this method (it could have a new element added to it), the changes to vsName will not be visible outside of the method. To prevent confusion, I often mark my method parameters final, which keeps them from being reassigned (accidentally or not) inside the method. This would keep the second example from compiling at all.
Java passes references by value, so you get a copy of the reference, but the referenced object is the same. Hence this method does modify the input list.
The references themselves are passed by value.
From Java How to Program, 4th Edition by Deitel & Deitel: (pg. 329)
Unlike other languages, Java does not allow the programmer to choose whether to pass
each argument by value or by reference. Primitive data type variables are always passed
by value. Objects are not passed to methods; rather, references to objects are passed to
methods. The references themselves are passed by value—a copy of a reference is passed
to a method. When a method receives a reference to an object, the method can manipulate
the object directly.
Used this book when learning Java in college. Brilliant reference.
Here's a good article explaining it.
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
Well, it can manipulate the ArrayList - which is an object... if you are passing an object reference around (even passed by value), changes to that object will be reflected to the caller. Is that the question?
I think you are confused because vsName is modified. But in this context, it is just a local variable, at the exact same level as shortenedVoiceSetName.
It's not clear to me what the exact question within the code is. Java is pass-by-value, but arrays are pass-by-reference as they pass no object but only pointers! Arrays consist of pointers, not real objects. This makes them very fast, but also makes them dangerous to handle. To solve this, you need to clone them to get a copy, and even then it will only clone the first dimension of the array.
For more details see my answer here: In Java, what is a shallow copy? (also see my other answers)
By the way, there are some advantages as arrays are only pointers: you can (ab)use them as synchronized objects!