I know java is pass by reference but only for Java Objects. But why it is not applicable for Java Wrapper classes? Are Wrapper classes such as Integer, Float, Double pass by reference or pass by value? Because whenever I pass object of such classes in method and that changes some values, but outside of that method I am not getting updated Value.
On top of pass by value discussion, all wrapper classes in Java are immutable. They replicate the behaviour of primitives. You need to return the latest value back to see the changes.
public static void main(String[] args) {
Integer i = 5;
display(i);
System.out.println(i);
}
private static void display(Integer i) {
i = 10;
}
The reason why i will not be updated because i=10 will use autoboxing here and it will be similar to i = new Integer(10)
Since i is pointing to a new memory address this change will not appear in main method
Related
public class JavaApplication6 {
public static void a(int b)
{
b++;
}
I am calling the function a and passing the variable b with the intention of incrementing it like a C++ reference (&b). Will this work? If not, why?
public static void main(String[] args) {
int b=0;
a(b);
System.out.println(b);
}
}
While you can't really accomplish that with int (the primitive type for integer), you can accomplish something very similar with AtomicInteger. Simply invoke the getAndIncrement method on an instance of the class. Something like this:
public static void a(AtomicInteger b) {
b.getAndIncrement();
}
(Note that you also can't do this with java.lang.Integer, because java.lang.Integer is an immutable class.)
First of all: Java does not allow for pass-by-reference. Further, out-parameters (when a function's calculations/results are placed in one or more of the variables passed to it) are not used; instead, something is returned from a method like so:
b = a(b);
Otherwise, in Java, you pass objects as pointers (which are incorrectly called references). Unfortunately (in your case) most types corresponding to int (Integer, BigInteger, etc.) are immutable, so you cannot change the properties in the object without creating a new one. You can, however, make your own implementation:
public static class MutableInteger {
public int value;
public MutableInteger(int value) {
this.value = value;
}
}
public static void main(String[] args) {
MutableInteger b = new MutableInteger(2);
increment(b);
System.out.println(b.value);
}
public static void increment(MutableInteger mutableInteger) {
mutableInteger.value++;
}
The following will be printed to the console when this code is run:
3
At the end of the day, using the above requires a strong argument on the programmer's part.
You can't do that with primitive types like int, because Java passes primitives by value. Simply wrap b in a mutable container object :
class Holder {
int b;
}
Now you can modify the value by doing :
public static void a(Holder h) {
h.b++;
}
You should, however, consider to work with Immutable Objects, which are generally considered a good thing in Java to avoid side effects and concurrency issues.
You cannot pass a value by reference in Java. If a primitive is passed to a method, the JVM passes it by value. If it is an object that is sent to a method, the JVM creates a copy of the its reference. Since this is a "copy" the modification won't change the initial object. But still, there are workaround such as using the AtomicInteger suggested in the previous posts.
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.
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.
I need to convert C code to Java.
The minimal C code is:
void changeX(int *x)
{
*x=5;
}
changeX is called in function B as:
void B()
{
int k= 2;
changeX((int*) &k);
}
The problem while converting it into Java is that x is not a class member so i cannot use this. How can i convert such code to Java?
Assuming you're really asking, "Can I use pass-by-reference in Java" (which that C code isn't using, but is emulating with pointers, which also aren't supported in Java) the answer is no.
Options:
Pass in a reference to an object which does contain a field you can change
(Ugly, but equivalent to the above in some senses) Pass in an array of size 1 constructed using the local variable, mutate the variable in the method, and then set the local variable again based on the array contents afterwards
Return the new value and assign it that way
Change your design so you don't need this
The last two of these options are the nicest ones. If you could give more information about the bigger picture - why you think you want to do this - that would be helpful.
Use one-element array reference:
void changeX(int[] x) {
// do not forget about checks
x[0] = 5;
}
void test() {
int[] x = {0};
changeX(x);
}
Being a primitive, and not a class member, you cannot pass the reference to another method. Use a class member instead.
You should return the new value of x,the method should as follow:
private int changeX(int x){
return 5;
}
You existing C code is incorrect:
void B()
{
int k= 2;
// you are not passing address of variable k but instead
// you are passing k (which is 2) as the address whose location needs
// to be changed. So you are writing to address 2 which you don't own.
changeX((int*) k);
}
What you need is:
changeX(&k);
Now this is changing the value of a variable by passing it by address. Now such a thing is not possible in Java which always uses pass by value. But you can get similar effect by enclosing the int variable inside an Integer object or an integer array (also an object) and pass the object by value.
Simply put Java has no equivalent to a pointer to a basic type - in order to achieve this you need a reference int type something like
class RefInt {
public int Value;
RefInt(int x) { Value=x; }
}
And you pass this in the same context and it works like so:
RefInt X=new RefInt(3)
ChangeX(X);
Obviously in this context simply changing the return value to type int and assigning it would be better but that doesn't solve your general problem.
Option1:
Put the int variable in a wrapper class. Pass that the method. In the method you can change the value in wrapper instance.
Option2:
Make changeX() return int and replace all changeX(k) with k = changeX(k).
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.