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.
Related
In a class, I have:
private Foo bar;
public Constructor(Foo bar)
{
this.bar = bar;
}
Instead of creating a copy of bar from the object provided in the parameter, is it possible to include a pointer to bar in the constructor such that changing the original bar changes the field in this object?
Another way of putting it:
int x = 7;
int y = x;
x = 9;
System.out.print(y); //Prints 7.
It is possible to set it up so that printing y prints 9 instead of 7?
When a variable is used as argument to a method, it's content is always copied. (Java has only call-by-value.) What's important to understand here, is that you can only refer to objects through references. So what actually happens when you pass a variable referring to an object, is that you pass the reference to the object (by value!).
Someone may tell you "primitives are passed by value" and "non primitives are passed by reference", but that is merely because a variable can never contain an object to begin with, only a reference to an object. When this someone understands this, he will agree that even variables referring to objects are passed by value.
From Is Java "pass-by-reference" or "pass-by-value"?
Java is always pass-by-value. The difficult thing can be to understand that Java passes objects as references passed by value.
From http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.
In Java, there is no counter part to the C++ "reference type" for primitives.
Your last example works that way because int is a primitive, it is copied by value. In the first example, "this.bar" would hold a copy of the reference (sort of pointer) to bar. So if you change the original bar (internally), the change will be reflected in your class. Try it.
To get that behavior you could modify a member of an object:
public class Number{
int value;
Number(int value){
this.value = value;
}
public String toString() {
return "" + value;
}
}
You could then do:
Number x = new Number(7);
Number y = x;
x.value = 9;
System.out.println(y);//prints 9
Java never copies objects. It's easiest to think of in terms of for each "new" you will have one object instance--never more.
People get REALLY CONFUSING when they discuss this in terms of pass by reference/pass by value, if you aren't amazingly familiar with what these terms mean, I suggest you ignore them and just remember that Java never copies objects.
So java works exactly the way you wanted your first example to work, and this is a core part of OO Design--the fact that once you've instantiated an object, it's the same object for everyone using it.
Dealing with primitives and references is a little different--since they aren't objects they are always copied--but the net effect is that java is just about always doing what you want it to do without extra syntax or confusing options.
In order to keep the original value of member bar, you will need to implement Cloneable interface. Then before assigning a new value to the object, you will need to make a clone of it and pass the cloned value and assign new values to the cloned object. Here is a tutorial on how to do it http://www.java-tips.org/java-se-tips/java.lang/how-to-implement-cloneable-interface.html .
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.
So I have an algorithm that forces me to pass in an object as a parameter recursively and on different depths of the recursion it sets the values of the object. The problem is Java isn't allowing me to do this because they pass in by value or something else that is just messing me up. How can you make sure that the object passed in retains the value set?
You never pass an object as an argument in Java. You either pass a reference or a primitive value. The argument is always passed by value. Java doesn't have pass-by-reference at all.
If you're passing in a reference to an object, and you want to make sure the code you call doesn't change the data within that object, your options are:
Create a copy and pass in a reference to that instead
Make your type immutable in the first place.
EDIT: Just to make it clear, if you have:
Foo f = new Foo();
then the value of f is not a Foo object. It's a reference to a Foo object. If you now call:
doSomething(f);
then the value of f is copied as the original value of the parameter within doSomething. That behaviour is basically the definition of pass-by-value. There's nothing doSomething can to do change the value of f - it will still refer to the same object afterwards. The data within that object may have changed, but it won't be a different object.
In a real-world analogy: if I give you a copy of my address, you can go and paint the front door, but you can't change where I live.
As Jon states, all non-primitives are passed by passing a copy of the reference. You don't have a choice. So your recursive method should be able to update the object if it is mutable. HOWEVER, you can't reassign a reference and expect it to propagate back up the call stack. And remember that Strings are not mutable.
In other words, if you do the following, you have not changed the object that was passed:
void myMethod(Object o){
o = new Object();
}
The above changes the local reference to o but does not change the caller's reference to o. If you need to do something like this you would need to return o.
I know this is a dumb question, but its really bugging me.
Take the following:
public <TParseable> LinkedList<TParseable> readAllParseable(
Parseable<TParseable> parseable, boolean close) throws IOException
{
LinkedList<TParseable> list = new LinkedList<TParseable>();
byte[] delim = parseable.getDelimiterValue();
boolean skipNL = parseable.skipNewLines();
while(ready())
{
byte[] data = readTo(delim);
parseable.parse(data);
System.out.println(parseable);
list.add((TParseable)parseable);
}
return list;
}
The println statement outputs the expected toString() value of parseable each time after the call to parseable.parse(data). However, the returned list has the correct number of elements, but they are all equal to the last value of parseable before the loop completed.
Is this because the list.add(xxx) parameter is passed by pointer rather than value?
You only ever have a single instance of parseable in the code you posted. When you call add(parseable) you are adding a reference ("pointer" isn't really correct in Java) to parseable in your list.
By calling it repeatedly, without changing what object parseable refers to, you are simply adding more references to the same object to your list.
New objects are only ever created by the new keyword.
You're putting in the same parseable object into the list each time. Each time parseable parses some data, it is being processed using the same parseable object.
the object parseable is the same through the entire method. I assume that when you call parseable.parse(data) it changes the internal data in parseable. Since you keep putting the same object in the list, you are just operating on the same object every iteration.
I think you conceptual problem is one of terminology. If I change "value" to "state", perhaps it will help clarify things ...
The println statement outputs the
expected toString() state of parseable
each time after the call to
parseable.parse(data).
However, the returned list has the
correct number of elements, but they
are all equal to the last state of
parseable before the loop completed.
In reality, your program is using only one Parseable instance, and the method calls on that instance are changing its state.
Is this because the list.add(xxx)
parameter is passed by pointer rather
than value?
No. It is because the instance's state (as shown by toString()) is changing.
In fact, Java uses pass-by-value semantic for all parameters in method and constructor calls, irrespective of the type. The slightly confusing thing is that the "value" that is passed when you pass an Object / array in Java is a reference.
The three basic parameter passing mechanisms supported by programming languages are:
pass-by-value where you copy the value which might be a primitive value, a pointer / reference value, or (in some languages) a structured value. (In some languages, a value can be copied back on return, but that's just a logical extension of pass-by-value.)
pass-by-reference where you pass the address of a variable in the caller, allowing the callee to change that variable, and/or see the results of something else changing the variable.
pass-by-name which was a "clever" mechanism used in Algol-60 that turned out to be expensive to implement and too difficult for most programmers to use effectively.
I would stay away from using the terminology "pass by pointer". It is really just another way of saying "pass-by-value of a pointer" ... and if you try to think of it as something different, you only end up confused.
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!