This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
One of the most popular answers to one of the most popular questions in Java here reads:
Java is always pass-by-value. The difficult thing to understand is that Java passes objects as references and those references are passed by value.
So what does "Java passes objects as references and those references are passed by value." mean?
Does it mean that:
The memory location to which the original variable points is copied as the value of the new temporary variable? (if this is the case, all the changes made inside the function will be reflected in the original, right?)
If not, what does it mean?
Think of objects references as "pointers to a value"
When you pass a value into a method, you pass the pointer in, therefore the two pointers (the one in the method, and the one you passed in) point to the same thing.
Consider this
public static void main(String[] args){
Foo cl = new Foo();
cl.z= 100;
method(cl);
System.out.println(cl.z);
}
private static void method(Foo bar){
bar.z=10;
}
Before you call method, cl.z would be 100, but after you pass it in, it would be equal to 10.
What is not correct is this:
public static void main(String[] args){
Foo cl = new Foo();
cl.z= 100;
method(cl);
System.out.println(cl.z);
}
private static void method(Foo bar){
bar = new Foo();
bar.z=10000;
}
This would NOT print out 10000, because you cannot assign the pointer to reference a different object
When we say Java is pass-by-value, it means that if you modify a parameter inside a method, it has no effect on the caller. For example:
public void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
All this does is swap local copies of the parameters. Thus, if you say
int x = something;
int y = somethingElse;
swap(x, y);
x and y would not change.
The same is true for references:
public void someOperation(MyClass a) {
a = ...something...;
}
Inside your method, a is a copy of whatever reference you pass in; if you reassign a to something else in the method, it doesn't affect any variable in the caller.
MyClass x = ...;
someOperation(x);
x does not change, even though you've changed the parameter a inside the method.
Note that this means that x itself will not change. It will not point to a different MyClass instance, even though a in the method was changed to refer to a different MyClass instance. However, even though the reference does not changed, the object that the reference refers to could be changed by the method.
It means the reference (a memory pointer to the object) is passed by value. If you modify the object, you modify the reference to the object; thus the change will be seen across your application. If you modify the pointer, then your only change it for the scope of your method.
void method(Foo f) {
f.bar = 10; // Seen accross your application.
f = new Foo(); // Modifying your pointer. This does not change the previous object.
}
Yes, Java is always pass-by-value, with both reference types and primitive types. But that doesn't mean that changes within functions always affect the object passed in as an argument.
If a primitive type is passed in, then there is no reference passed, it's by pure value, and any values in the calling scope will not change.
If a reference type is passed in, whether or not a function can modify it depends upon if the type is mutable (the object can be modified) or immutable (the object itself cannot be modified, a new object must be created for all modifications).
If it is mutable, like StringBuilder or HashMap<String, String>, then the function is able to modify it and changes within the function will still be in place after the function call returns. However, note that changing what a reference type points to is not modifying it, in that case, you are only changing what the reference type points to, not the original object referenced by an argument, but doing an operation like strbuilder.append("xyz") is.
If it is immutable, like String or Integer then all modifications within the function will create a new object and the changes will not be in place after the function call returns.
Related
This question already has an answer here:
Java method doesn't change parameter objects [duplicate]
(1 answer)
Closed 8 years ago.
Ok. I'm completely aware that all values in Java are passed by value. But this example does not behave as I expected:
public class Test {
private static void changeInteger(Integer x) {
x = 5;
}
public static void main(String[] args) {
Integer x = 0;
changeInteger(x);
System.out.println(x);
}
}
Since I'm passing wrapper class to the changeInteger Method, I'm passing its address, so, after executing function that should affect my x variable and set it to 5. But eclipse says that output is still 0. What did I understand wrong?
Consider this example:
class Wrapper {
int n;
public Wrapper(int k) { n = k; }
public String toString() { return ""+n;}
public static Wrapper valueOf(int k) { return new Wrapper(k); }
}
Now let us replace Integer in your code with the Wrapper class above:
private static void changeInteger(Wrapper x) {
x = Wapper.valueOf(5);
}
public static void main(String[] args) {
Wrapper x = Wrapper.valueOf(0);
changeInteger(x);
System.out.println(x);
}
Since you mentioned that you know about passing by value, I hope that it is clear why this code does what it does.
Now let's go back to your code. Under the hood, it is exactly the same code. The only difference is that you do not call Wrapper.valueOf: the compiler does it for you through autoboxing. Once you realize that this is what is going on, the issue should be clear to you.
ByteCode of changeInteger() to show that Integer.valueOf() is called :
private static void changeInteger(java.lang.Integer);
Code:
Stack=1, Locals=1, Args_size=1
0: iconst_5
1: invokestatic #16; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
teger;
.... // some other code
With x = 5; you assign a new value to x inside changeInteger(). You are not changing the value of the current Integer object.
The value of x outside the method is not affected.
You get puzzled by the autoboxing function of java. You cannot assign a primitive value to an objec. When you call x=5 it creates a new Integer object with 5 value and assignes its reference to x. But this affects only the parameter in the scope of changeIngeger, the original object with 0 and the reference of x in main scope are untouched.
Your problem is the fact that Java is pass-by-value not by-reference so the x in the method is not the same x of main. The fact that Integer is an immutable class, here doesn't change anything.
All Java parameters are passed by value. For all non-primitive types, the value contains a reference to the object that's passed.
For your piece of code, the Integer object is stored at location A in memory. Another location B in memory represents the main's variable x and stores a value A.
For the changeInteger call, a new location C is created and a value in B (which is A) gets copied to it. This is the local x of the changeInteger function.
With the assigning, you create a new variable stored at D and its location is assigned to C. Then you return from the method.
You can see that A and B isn't modified anywhere and thus the value remains unchanged.
Keeping as simple as it is, All Java Wrapper classes are Immutable. So you cannot seeing the change.
If you want to see the change, just return from method (not main) and assign it back.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
So as far as I know, in java you can't access objects directly, you only have the pointer to it. So for example I have this code:
public class App {
public App() {
Thing t = null;
doStuff(t);
System.out.println(t);
}
public void doStuff(Thing a) {
a = new Thing();
}
public static void main(String[] args) {
new App();
}
}
class Thing { }
And the output is null. Why? I've passed the pointer to a method which gave it a new Thing instance to point to. Is it because it's a new pointer? Also how can I resolve it without returning anything from doStuff()?
You have references not pointers, and a method cannot update the callers reference without an assignment in the caller - so this
public App() {
Thing t = null;
doStuff(t);
System.out.println(t);
}
public void doStuff(Thing a) {
a = new Thing();
}
Would work if you did,
public App() {
Thing t = null;
t = doStuff(t);
System.out.println(t);
}
public Thing doStuff(Thing a) {
a = new Thing();
return a;
}
This is because Java works by pass by value of Object references and not pass by reference of an Object ,even if the reference is an Object,it still gets passed by the value of reference.So you always work with new references
Refer:http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
Declaring a Variable to Refer to an Object
Previously, you learned that to declare a variable, you write:
type name; This notifies the compiler that you will use name to refer
to data whose type is type. With a primitive variable, this
declaration also reserves the proper amount of memory for the
variable.
You can also declare a reference variable on its own line. For
example:
Point originOne; If you declare originOne like this, its value will be
undetermined until an object is actually created and assigned to it.
Simply declaring a reference variable does not create an object. For
that, you need to use the new operator, as described in the next
section. You must assign an object to originOne before you use it in
your code. Otherwise, you will get a compiler error.
A variable in this state, which currently references no object, can be
illustrated as follows (the variable name, originOne, plus a reference
pointing to nothing):
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
while learning C language I have learned that when you pass a variable to a function. you are not passing the variable itself you are passing a copy of it so the actual varible's value will not change unless the function returns a value and you assign that value to the variable.
but I just executed this program and this happened when I passed "Newobj" object to a "changer" function and then change the values of the variables and then print the new variables values it is working. It should not happen right? because I am sending the copy of "Newobj" to "copyobj". explain please I am confused.
Note: Explain in detail please. My brain is slow. I know the concepts of c and few concepts of c++;
here is my code:
public class PassObjects {
int regno;
String name;
double per;
PassObjects(int a,String s,double p){
regno=a;
name=s;
per=p;
}
PassObjects changer (PassObjects copyobj){
copyobj.regno=797;
copyobj.name="Srimanth";
copyobj.per=70.9;
return copyobj;
}
public static void main(String[] args){
PassObjects Newobj= new PassObjects(86,"srimanth",85.4);
System.out.println("The original values of Instance variables are "+Newobj.regno+" "+Newobj.name+" "+Newobj.per);
Newobj.changer(Newobj);
System.out.println("The changeed values of Newobj are "+Newobj.regno+" "+Newobj.name+" "+Newobj.per);
}
}
output is here:
The original values of Instance variables are 86 srimanth 85.4
The changeed values of Newobj are 797 Srimanth 70.9
What you are doing is passing a pointer to an object. You are effectively modifying the PassObjects object.
There is a difference between a reference type and a value type. For example, a function that takes an integer and modifies it will indeed receive a copy of that integer.
public void add(int x)
{
x = x + 1;
}
However, an array of ints is also a reference type.
When you call this function using the following code:
int x = 5;
add(x);
// X will still have a value of 5.
This is because x is a value-type. You call the function and pass in a copy of the integer.
However, when you create an object, you do not pass a copy of the entire object. See code below.
public void ChangeName(SomeObject x, String newname)
{
x.name = newname;
}
SomeObject x = new SomeObject("thename");
ChangeNameTo(x, "newname"); // As the comment below pointed out, you don't even have to reassign.
//x.name will have the value "newname" now.
You can read more here and here.
Java does manipulate objects by reference, and all object variables are references.
That means u only created a new reference to the same object and when u changed the values then it gets changed in actual object.
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
Ok so if primitive data types in java are passed into methods, they are treated as pass by value. And if object data types are passed into methods, they are treated as pass by reference right? So in this code:
//Class 1
public void passByValue(int x){
x = 0;
}
public void passByReference(Integer y){
y= 40;
}
//MainClass(contains main method)
int primitiveType = 50;
Integer wholeInteger = 100;
Class1 a = new Class1();
a.passByValue(primitiveType);
a.passByReference(wholeInteger);
System.out.println(primitiveType);
System.out.println(wholeInteger);
This should result in primitiveType being equal to 50(variable hasnt changed). I understand that, however the Integer object is also not changed... So how does this work? Thanks!
Object references are passed by value too. It is the reference that is passed and not the object. You confuse pass-by-reference of the object with pass-by-value of the reference.
In A x = new A() the symbol x is a reference to an object of type A.
If x is a reference and f(A a) { a = null; } is a method then f(x) will not set x to null. Hence, the reference was passed by value.
The reason behind this (and your confusion) is that - to some extend - the phrase "the object is passed by..." is already wrong. Because correctly we have to say "the object reference is passed by...". If A is a class then A a; means that a is a reference to an object of class A. If that is clear, it becomes clear why we have a pass-by-value.
First of all there is no pass by reference in java when you pass an object then it's also pass by value...
secondly, like String class , the wrapper class Integer is also immutable...
when you write Integer y= 40 ; then new Object new Integer(40); is being created by autoboxing feature java supports ..
That's why .... there is no change in value of wholeInteger you passed..
I want to use reference in Java but I don't know how!
for example in C++ we write:
void sum(int& x)
{
...
}
but in Java & sign is a compiler error!
please help me to understand references in Java.
Objects are passed by reference by default Objects are accessed by reference, but there is no way to create a reference to a primitive value (byte, short,int, long). You either have to create an object to wrap the integer or use a single element array.
public void sum(int[] i){
i[0] = ...;
}
or
public void sum(MyInt i){
i.value = ...;
}
public class MyInt{
public int value;
}
for your example something like the following could work
public int sum(int v){
return ...;
}
or
public int sum(){
return ...;
}
Update:
Additional/Better description of object references:
Java Objects are always accessed by a reference. Like the primitive types this reference is passed by value (e.g. copied). Since everything a programmer can access in java is passed by copying it (references, primitives) and there is no way to create a reference to a primitive type, any modification to a method parameter (references, primitives) only affects the local copy within the method.
Objects can be modified within a method since both copies of the reference (local and other) still point to the same object instance.
example:
Modify a primitive within method, this only affects the internal copy of i and not the passed value.
void primitive(int i){
i = 0;
}
Modify a reference within method, this only affects the internal copy of ref and not the passed value.
void reference(Object ref){
ref = new Object();//points to new Object() only within this method
}
Modify an object, visible globally
void object(List l){
l.add(new Object());//modifies the object instead of the reference
}
Both the array and MyInt above are based on the modification of an object.
An ordinary Java parameter already is closer to a C++ reference than to C++ pass-by-value or pass-by-pointer. So, all your Java methods are already like this.
int and other primitives are special in Java, however; the above is true for object references.
Edit: More precisely, as stated #fatih, all Java invocations are pass-by-value. However, when you pass an object you are passing a reference by value. So, as a first approximation, the above statement is correct: An ordinary Java parameter is more similar to a C++ reference than to C++ pass-by-value or pass-by-pointer.
Required reading on understanding Java's Pass By Value semantics:
http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
http://javadude.com/articles/passbyvalue.htm
http://javachannel.net/wiki/pmwiki.php/FAQ/PassingVariables (links to several other pages)
Completely remove the notion from your head that Java can have anything passed by reference. Let's look at an example, shall we?
public class App
{
public static void main( String[] args )
{
Foo f1 = new Foo();
doSomethingToFoo(f1);
System.out.println(f1.bar); //Hey guess what, f1.bar is still 0 because JAVA IS PASS BY VALUE!!!
}
static void doSomethingToFoo(Foo f) {
f = new Foo();
f.bar = 99;
}
static class Foo {
int bar = 0;
}
}
The MutableInt class in Apache Commons will do what you want, although it's not pretty.
MutableInt
void sum(MutableInt mx)
{
int x = mx.getValue();
x = ...
mx.setValue(x);
}
...
MutableInt mx = new MutableInt(5);
sum(mx);
int result = mx.getValue();
Additional classes are provided for other primitive types, and also for objects.
There is some overhead involved in creating an additional object simply to provide a reference, so the solution is not optimal, but in most cases you should be ok.
In general, it is always best to find a way to return a result from a method. Unfortunately, Java only allows one value to be returned in this way.