This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to write swap method in Java?
Given two values x and y, I want to pass them into another function, swap their value and view the result. Is this possible in Java?
Not with primitive types (int, long, char, etc). Java passes stuff by value, which means the variable your function gets passed is a copy of the original, and any changes you make to the copy won't affect the original.
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
// a and b are copies of the original values.
// The changes we made here won't be visible to the caller.
}
Now, objects are a bit different, in that the "value" of an object variable is actually a reference to an object -- and copying the reference makes it point at the exact same object.
class IntHolder { public int value = 0; }
void swap(IntHolder a, IntHolder b)
{
// Although a and b are copies, they are copies *of a reference*.
// That means they point at the same object as in the caller,
// and changes made to the object will be visible in both places.
int temp = a.value;
a.value = b.value;
b.value = temp;
}
Limitation being, you still can't modify the values of a or b themselves (that is, you can't point them at different objects) in any way that the caller can see. But you can swap the contents of the objects they refer to.
BTW, the above is rather hideous from an OOP perspective. It's just an example. Don't do it.
I'm going to be reallllyyyy annoying and pedantic here because the word "value" has a very specific meaning in Java, which people often don't often understand, especially when the variables hold references to objects.
I am going to assume the question asks for this behavior:
x = initialValueForX;
y = initialValueForY;
swap(x, y);
// x now holds initialValueForY;
// y now holds initialValueForX;
This is not possible because Java passes all arguments to methods by value. You can never change the actual value stored inside of x and y this way.
You can, however, if x and y hold references to objects, change the properties of the two objects in such a way as to make the printed values look like each other's initial values:
x = initialValueForX;
y = initialValueForY;
swap(x, y);
System.out.println(x); prints what looks like initialValueForY
System.out.println(y); prints what looks like initialValueForX
This works if your understanding of value is what the object looks like, rather than what the identity of an object is. Usually, that is acceptable.
(Was going to give a good example here, but cHao already did. Plus others pointed out that this was a duplicate question anyway.)
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
I am checking whether the specified word can be formed on this boggle board with the canForm method. The board has a graph field which indicates adjacent tiles. I do a DFS and set answer to true if the word can be formed.
I understand why the code as it is below doesn't work: answer is a primitive, its value is copied at every recursion and the initial answer (in the public method) stays false.
If I change boolean answer to Set<String> answer = new HashSet<>() for instance, pass the reference to the set in recursion, eventually add the successfully formed word and test for emptiness in the end, it works.
But why does it not work if I simply declare Boolean answer = new Boolean(false) and pass this container? It passes the reference to the object all right, but it mysteriously changes the reference at assignment answer = true (as seen through the debugger), and the initial answer isn't reset. I don't understand.
public boolean canForm(String word) {
boolean answer = false;
int n = M * N;
char initial = word.charAt(0);
// for each tile that is the first letter of word
for (int u = 0; u < n; u++) {
char c = getLetter(u / N, u % N);
if (c == initial) {
boolean[] marked = new boolean[n];
marked[u] = true;
canForm(u, word, 1, marked, answer);
}
}
return !answer;
}
private void canForm(int u, String word, int d, boolean[] marked, boolean answer) {
if (word.length() == d) {
answer = true;
return;
}
for (int v : graph.adj(u)) {
char c = getLetter(v / N, v % N);
if (c == word.charAt(d) && !marked[v]) {
marked[v] = true;
canForm(v, word, d + 1, marked, answer);
}
}
}
Ah, you're using Java. This matters greatly.
Java is, exclusively, a pass by value language. As such, when you call canForm(int, String, int, boolean[], boolean), you are doing two things:
You are creating 5 new variables in the scope of the canForm method
You are initializing them with values from the call site
Altering the values of of the new variables you created will not have any affect on the values of those variables at the call site. Any re-assignments you make will be lost when the method call ends and will have no impact on the values at the call site.
However, in the case of arrays or objects, the "value" being passed is actually a reference to an object. This can be a bit confusing, but it's like the caller and the method each have their own personal key to a shared mailbox. Either could lose their key or replace it with a key to a different mailbox without affecting the other's ability to access the mailbox.
As such, the method can alter the value of the reference (marked = new boolean[]) without altering the caller's reference. However, if the method changes content WITHIN the referenced structure (marked[0] = false) it will be seen by the caller. It's like the method opened the shared mailbox and changed the mail inside. Regardless of which key you use to open it, you'll see the same changed state.
A great analysis: http://javadude.com/articles/passbyvalue.htm
In general:
If you want to return a value from a method, that should be the return value of the method. This makes the code easier to understand, less likely to have side effects and may make it easier for the compiler to optimize.
If you want to return two values, create an object to hold both of them (A general purpose type safe container called a "Tuple" is available in many languages and frameworks).
If you really need to move state between function calls -- and you usually don't -- wrap it with an object to get the equivalent of pass by reference semantics. That's essentially what you're doing when you add your results to a shared Set. Just be aware: programming with side effects, be they shared objects or global state, is defect prone. As you pass a mutable object around, it becomes hard to keep all the potential mechanisms for change in your head. If you can do a job by exclusively through return values, you should try to do so. Some might calls this a "functional [programming] style."
When you give two methods with different intent the same name, it creates confusion, both for readers and in some cases for the compiler. Be specific. We're in no danger of running out of characters.
Finally, you may want to read up on tail recursion. Due to that loop, I believe this implementation may be a stack overflow waiting to happen -- just give it a string that's longer that your stack is deep.
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'm trying to make a 2d game in Java.
In the process I soon noticed that many objects needed bounds (x1, x2, y1, y2) and as a consequence many methods thus had parameters (int x1, int x2, int y1, int y2).
So I thought what the heck, why not make an object IntRectangle with attributes x1, x2, y1, y2 (which I set as public for a performance boost), along with a few helpful methods like getWidth(), getHeight(), etc.
At this point my code is much cleaner and I haven't lost much performance since the variables are public.
I soon noticed, unlike passing primitive values into a method, the values of the passed object changed when I changed them in the method.
For instance, with a primitive value
int x = 10;
subtract5(x);
print(x);
void subtract5(int i) {
i -= 5;
}
this line of code would print 10.
But with an object...
class XY {
public int X;
public int Y;
}
main {
XY xy = new XY();
xy.X = 5;
xy.Y = 10;
changeX(xy);
print xy.X;
}
changeX(XY xy2) {
xy2.X = 7;
}
It prints 7;
The theory I've developed is that an int is not a pointer to an int, it's an int stored in the register. It is pushed when a method is called and then popped back when returned, unchanged. An object is a reference to an object. The object itself isn't pushed onto the stack, just the pointer.
But I've tired this with strings (that I know are objects) and they behave just like ints in this matter, which confuses me. Perhaps they make a copy out of themselves somehow?
Well, I hope someone can shed some light on this matter and tell me where my reasoning is taking a wrong turn and hopefully give me some advice on how to clean up my code, keep performance, but without making it venerable.
A object in java is a block of memory in the heap space. All you pass around are references to this object/memory area. (The references itself are passed by value) So if you have an Object Rectangle with four ints your methos will change the memory of the heap ara which is references by the passed object reference.
Strings are immutable - so the object cannot change and every modifier method returns a new instance.
See http://javadude.com/articles/passbyvalue.htm for more information.
The fact is that Java is always pass-by-value.
In particular Java passes objects as references and those references are passed by value.
In case of primitive type, it is passed directly by value.
Further details in the following question:
Is Java "pass-by-reference" or "pass-by-value"?
Strings are constant; their values cannot be changed after they are created.If you change the value of a String it will create a new String object and return a reference to the new String object i.e a new instance is created .E.g
String str="abc";
str=str+"d";
In this case a new String object is created in the String pool and it is now referred by str.The old string is garbage collected.
Ok, I might have been a bit vague, but the question was not how java passes variables. I just came from that thread. I've figured that out, it was just the String class that was confusing me. And the eventual performance gain of having public attributes. I'll make another attempt, thanks for all your answers!
I'm confused on the concept of "being immutable". Our professor is saying "ints are immutable! Strings are immutable" everyday, what does he mean by that exactly?
A more general question, how do we know if a data structure is immutable or not?
Thanks
Some of the other answers here are confusing mutability/immutability with value/reference semantics, so be careful...
Simply put, an entity is mutable if it may be modified after it's been created. In other words, its value may change over time.
First, a counterexample. A Java String object is immutable; there is no method that you can call on a String object that will change its value:
String a = "foo";
a.concat("bar");
System.out.println(a); // foo
You could do this instead:
String a = "foo";
a = a.concat("bar");
System.out.println(a); // foobar
but that works because concat() is creating a new String object, and the reference a is then repointed at it. There are now two String objects; the original has not changed (it's just lost forever). a is mutable, the underlying object isn't.
As for int variables; in C or Java, we can do this:
int x = 3;
x = 4; // Mutates x
x++; // Mutates x
How do we know these really mutate x, rather than simply creating a new integer "object" and "repointing" x at it? (Other than by the fact that the language assures us that primitive types are distinct from object types.) In C, we can somewhat prove it:
int x = 3;
int *p = x; // Pointer to original entity
x = 4;
printf("%d\n", *p); // 4
AFAIK, there is no equivalent approach in Java. So you could argue that the question of whether integer types are truly mutable in Java is irrelevant.
As for how we know whether a given type is immutable, very often we don't. At least, not without inspecting it, or simply believing a promise we've been told.
In Java, ensuring a user-defined type is immutable involves following a few simple rules (explained here). But it's still just a promise; the language doesn't enforce it.
Immutability (of an object or value, not a variable) usually means there's no way to do an in-place change of the value. (One that would propagate to other references to it.) This means that if you have something like the following:
String a = "foo";
There is no operation that you could perform on a that would change its value. I.e. you can't have a hypothetical method append() that would cause the following behaviour:
String a = "foo";
a.append("bar"); // a is not reassigned
System.out.println(a); // prints "foobar"
You can contrast this with mutable objects like collections:
int[] as = new String[] { "foo" };
as[0] = "bar"; // we're changing `as` in-place - not the Strings stored in it
System.out.println(as[0]); // prints "bar"
Primitive types are not a great choice of example for Java, since you can't have multiple references to them, and there's no way to demonstrate the distinction between a mutation and a reassignment.
It's awkward to talk about immutability of ints, because the idea of mutating something that isn't a container doesn't make sense to most of us. So let's talk about strings.
Here's a string, in Python:
s = "abc"
Strings are containers in the sense that they contain some number of individual characters: here a, b, and c. If I want to change the second character to a d, I might try:
s[1] = 'd'
Which will fail with a TypeError. We say strings are immutable in Python because there is no operation that will alter an existing string. Certainly there are plenty of operations that will perform some operation and create a new string, but existing strings are set in stone.
There are a couple advantages here. One is that it allows interning: sometimes when a string needs allocating (and at the discretion of the interpreter), CPython will notice that an identical string has already been allocated and just reuse the same str object. This is easiest when strings are immutable—otherwise, you'd have to do something about problems like this:
s = "abc"
t = "abc" # this reuses the same memory, as an optimization
s[0] = "x" # oops! now t has changed, too!
Interning is particularly useful in Python and similar languages that support runtime reflection: it has to know the name of every function and method at runtime, and a great many methods have builtin names like __init__ (the name of the constructor method), so reusing the same string object for all those identical names saves a good deal of wasted space.
The other advantage is in semantics: you can safely pass strings to arbitrary functions without worrying that they'll be changed in-place behind your back. Functional programmers appreciate this kind of thing.
The disadvantage, of course, is that doing a lot of work with very large strings requires reallocating and rebuilding those large strings many times over, instead of making small edits in-place.
Now, about ints. This is NOT an example of immutability:
x = 3
x = 4
This doesn't involve the actual objects at all; it only assigns a new value to the variable x.
Consider instead:
x = [1, 2, 3]
y = x
x[:] = [4, 5, 6]
print y # [4, 5, 6]
The x[:] = syntax is "slice notation" for replacing the entire contents of a list. Here, x and y are two names for the same list. So when you replace the contents of x, you also see the same effect in y, because... they both name the same list. (This is different from reference variables in other languages: you can assign a new value to either x or y without affecting the other.)
Consider this with numbers. If you could do some hypothetical operation like the above on plain numbers, this would happen:
x = 3
y = x
x[:] = 4
print y # hypothetically, 4
But you can't do that. You can't change the number an existing int represents. So we call them immutable.
Mutating an int is easy in Smalltalk:
3 become: 4
This would change the 3 to a 4, overwriting the memory that previously contained a 3. If ints are interned (as they can be in Python), this could even mean that everywhere 3 appears in your source code, it acts like the number 4.
In C, these distinctions aren't as meaningful, because variables are fixed blocks of memory rather than the transient labels of Python. So when you do this:
int x = 3;
x = 4;
It's hard to say definitively whether this is "mutating" an int. It does overwrite existing memory, but that's also just how C variable assignment works.
Anyway! Mutability is just about whether you're altering an existing object or replacing it with a new one. In Python and Java, you can't alter existing strings, and you can't "alter" numbers, so we call them immutable. You're free to change the contents of lists and arrays in-place without creating new ones, so they're mutable.
What is immutable is highly language-dependent, but an immutable object is simply an object that cannot be changed after it is created.
What this usually means is that:
int x = 4;
x = 5;//not 'allowed'
This is seen in languages where primitives, such as an int, can be immutable (such as functional languages like Scala).
Most objects in OOP are actually pointers to a place in memory. If that object is immutable that location in memory cannot have its contents changed. In the case of a String in Java, we see this happening:
String a = "Hello"; //points to some memory location, lets say '0x00001'
a = a + " World!"; //points to a new locations, lets say '0x00002'
System.out.println(a);//prints the contents of memory location '0x00002'
In this case, a actually points to an entirely different place in memory after line 2. What this means is that another thread with a different scope that has handed a would not see "Hello World!" but instead "Hello":
String a = "Hello";
startThread(a, " Hello!");//starts some thread and passes a to it
startThread(b, " World!");//starts another thread and passes a to it
...
public void methodInThread(String a, String b) {
a = a + b;
System.out.println(a);
}
These two threads will output the following, regardless of the order they're called in:
"Hello Hello!" //thread 1
"Hello World!" //thread 2
An object is considered immutable if its state cannot change after it is constructed.
source : http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
Typically it means you can't call a method on the type (int or whatever) that will change a
Sometimes people refer to value types as being immutable
//theres no way for this to be mutable but this is an example of a value type
int a = 5
int b = a;
b=9
a does not change unlike class types like
MyClass a = new MyClass
MyClass b = a
b.DoSomething()
//a is now changed
An immutable object is some thing that once instantiated can not be modified. If you have to modify, a new object will be created and pointed to the reference.
And ints are not immutable.
There are some classes in java which are immutable like String, All Wrapper Class ie. Integer, Float, Long etc.
For Example:
Integer i=5;
i=10;
i=15;
When Integer i=5, here a new Integer object is created, then in the 2nd, i=10 rather assigning this value 10 to previously created object, a another new object is created and assign to i, and 3rd i=15 , here again new object is created and again is assigned to i.
Note: don't be confused with int with Integer. int is primitive type and Integer is wrapper class. All primitives are mutable.
The concepts of mutability and immutability are only relevant for things to which code may hold a reference. If one holds a reference to something, and some immutable aspect of that thing's state is observed to have some value (or state), then as long as that reference exists, that aspect of the thing's state may always be observed to have the same value (state).
The String type in Java may reasonably be described as immutable, because code which has a reference to a string and observes that it contains the characters "Hello" may examine it at any time and will always observe that it contain those characters. By contrast, a Char[] might in one moment be observed to contain the letters "Hello" but at some later time be observed to contain the letters "Jello". Thus, a Char[] is considered mutable.
Because it is not possible to hold a direct reference to an int in Java, the concepts of mutability and immutability are not really applicable to that type. One can, however, hold a reference to an Integer, for which they are relevant. Any such reference that is observed to have a particular value will always have that same value. Thus, Integer is immutable. Note that while the concepts of mutability and immutability aren't really applicable to value types like int, they do share a useful aspect of immutable types: the state represented by a storage location (variable, field, or array element) of either a primitive type or an immutable type is guaranteed not to change except by overwriting that location with either a new value or a reference to a different immutable object.
In my Java test was the next question:
there is the next method:
public void changer(int[] x, int y) {
x[y] = x[y] +3;
y = y * 2;
}
We have array named a, with the values:
2,4,0,1,-6,3,8,7,5
if b = 3
what will be a and b values after the next call:
changer(a,b);
My answer was:
b = 6
a = 2,4,0,4,-6,3,8,7,5
I've tested it on BlueJ and got the same answer, but the tester wrote: wrong !
what do you say?
You are right about array values, but wrong about b value.
When you call a method, java passes everything by value, that mean that changing y only changes the value locally, and the change is not reflected on b.
However, when passing arrays and objects, a value representing a pointer to the array is passed. That means that x = new int[8] does not alter a at all, since as it happens for y the change is not reflected to a. However, changing array members or object properties works as you expected, cause a and x both point to the same array in memory.
from the scope where changer is called b doesn't change, because Java is pass by value and b is a primitive. So b would still be 3 after the method call. The statement in changer:
y = y * 2
after changing the value in the array effectively does nothing.
Your answer for a is correct.
b should still be 3. Passing an integer passes it "by value", so it is essentially a copy of b that goes into the changer method.
B won't be changed because it is a primitive passed as a method parameter. In that case a local copy is made, which is in this case multiplied by two. The original b will not be affected by this though. The array is changed because arrays (even arrays of primitives) are Objects in Java, so the reference to the array is passed into the method and changes to the array (via the reference) are reflected in the one and only array - no copy is made in this case.
You're confusing values and references, and thinking of the y value as if it's a reference.
The first line
x[y] = x[y] +3;
sets the value of the yth element of the array. The following line y = y * 2;
changes the value of the parameter but doesn't alter the array setting.