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.
Related
I know the question of Java being pass-by-reference or pass-by-value is beating a dead horse but I do have a question regarding memory usage.
The way I understand Java now is that:
public class MyInt{
int value;
}
MyInt x;
MyInt y;
x = new MyInt(3); // value of x is now 3
y = x; // y now points to same object that x points to
y.setValue(1); // value of said object is now 1
x.getValue(); // should return 1 instead of 3
But my question is how memory intensive is it to set this new y? Ex: if the value of MyInt were some very very large image instead of an integer,
x = new MyImage("very large image"); // eats memory depending on size of image
Would naturally take a lot of memory to have that image loaded if it were very large. I just want to make sure that when I call
y = x; // y now points to same image that x does
y is just a reference to the object that x is already pointing at right? So when I call y = x; it would not be memory intensive no matter how large the image as long as that image had already been loaded via initializing x.
Is this correct? What pitfalls should I avoid to keep the same very large image from being loaded into memory multiple times?
Yes you're right, any non primitive instance assignment to a non primitive reference variable is just reference assignment.
So if there's a memory location for x say mem1 then y=x will make y to point to mem1. Now even if x were to point to a new memory location mem2, y will still be pointing to mem1. So that's a pitfall to be avoided.
You almost will never be able to load a very large object multiple times without noticing it first, as you would either be creating new object calling the constructor or using some form of clone() method.
One pitfall unrelated to large objects but related to pass by reference in Java is that a reference variable passed to a method can not be dereferenced.
So suppose there's a method dereferenceMe(MyInt x) {x = new MyInt();} it won't change the actual reference of x in the caller method. As Java will pass the reference by value, meaning it creates a copy of reference variable and that copy is passed to the methods.
You are right, when you call y=x it would simply set y to refer the location of "very large image". There still would be only 1 object in memory which would be referenced by both x and y.
To avoid the very large image from loading again and again in memory, just don't create a new object with that image again. Avoid deep copy of the object as well.
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 .
THERE ARE ISSUES WTIH AN UNDERSTANDING OF Java IN THIS QUESTION. AS THE AUTHOR, I HAVE KEPT THE ORIGINAL QUESTION INTACT AS THE ANSWERS DO AN EXCELLENT JOB OF CLEARING UP THOSE ISSUES
Please, feel free to make changes to below question in order to improve its quality as a pedagogical tool
I have a JAVA class containing one method, the method receives an array object of integers (as you can see in the code); however, in JAVA, everything is pass[ed]-by-value - a well established fact, i.e. overwriting an object or primitive type passed as an argument cannot happen using a local scope object or p. type.
In other words, in order to change an object (primitive or reference) in Java, one must access the data member (or "attribute") directly or indirectly via a member function (or "method") that has the authority to change the attribute. Simply, the method must have an effect.
The other method for changing the value of an object is to return a value via a function and set the original object to the returned value.
Here is my code (and question to follow):
CODE FRAG. I:
public class BlockSort
{
public static void sort(Block [] blocks)
{
boolean sorted = false;
int length = blocks.length;
while(!sorted)
{
sorted = true;
for (int i = 1; i < length; i++)
{
if (blocks[i - 1].width > array[i].width)
{
Block tempBlock = blocks[i - 1];
blocks[i - 1] = blocks[i];
blocks[i] = tempBlock;
}
else if ((blocks[i - 1].width == array[i].width) && (blocks[i - 1].length > array[i].length))
{
Block tempBlock = blocks[i - 1];
blocks[i - 1] = blocks[i];
blocks[i] = tempBlock;
}
}
length = length - 1;
}
}
Essentially, in a very minimalistic sense, the above code functions the same way as this [NOTE: this statement is not true, see answers):
CODE FRAG. 2:
public myClass
{
public void doesNothing(int someParameter)
{
someParameter = someParameter - 1;
}
}
So, here is my question: without a return type, any value passed to above code will not really do anything, correct? In other words, it has no way of modifying what's passed to it with any real clout (because any modifications are function scope).
I am maintaining that the fragment is not testable
You are absolutely right: changes to parameters of primitive and immutable types cannot be detected from the outside; nor should they be.
[the second code fragment] has no way of modifying what's passed to it
That is also true. Moreover, it may not be possible at all - consider this call:
mc.doesNothing(2*a*a + 3*b + c);
The value passed in to doesNothing is computed from three variables, so there is nothing in the caller that could be modified,
In your original code fragment int someParameter is local to the implementation of doesNothing method - in the same sense that local variables are invisible from outside of the method. Testing it does not make any more sense than "testing" changes to any other local variable of a method.
The other code fragment (CODE FRAG. I), however, is different, because Java arrays are neither primitive nor immutable:
public static void sort(Block [] blocks) {
// Any change to the content of blocks will be visible to the caller
}
Therefore, the changes performed to the blocks array inside the method will be visible to the caller, in the same way that the callers would see changes to any other mutable object.
Java is pass-by-value, but objects and arrays are reference types. The array you pass into sort will be the same array you get out (that is, it'll be in the same place in memory), but the things inside the array may be different.
The BlockSort.sort method does have an effect. It gets passed a reference to a Block [] by value. This does not mean it cannot change the array contents.
If you call it for example with BlockSort.sort(myArray) the variable myArray will on return point to the same array instance. But the content of the array may be changed.
what I am asking ultimately is whether or not the above code is testable
Yes, it is. The code you've posted moves elements around inside the blocks array, and you can certainly test whether the items are sorted once the method returns
Block[] blocks = createBlocks();
BlockSort.sort(blocks);
for(int i = 1; i < blocks.length; i++) {
assert blocks[i].width < blocks[i-1].width;
}
Okay, so, I am going to amalgamate the answers written in response to the original question (because there are a lot of good fragments of information in all of the responses that need to be put together).
THREE ISSUES ARE PRESENT
ISSUE no. 1 Pass-by-value or Pass-by-Reference
Essentially, the above question stems from a - seemingly pervasive - lack of understanding or confusion surrounding how Java's pass-by-value works. Objects in Java are indeed pass[ed]-by-value; however, what is passed by value is the reference to the object, i.e. the value behaves somewhat like a pointer in C++ (that may be untrue, but it seems that way). So, the argument received by the parameter is in fact a value, but the value contains - in thought - a reference to the object:
public static void sort(Block [] blocks)
{
// CODE
}
This is not the case for primitive types. Primitive types pass a copy of their value to the parameter, so they are pass-by-value:
public void doesNothing(int someParameter)
{
// CODE
}
ISSUE no. 2: Arrays Are a Reference Type
An array is a reference type object in Java (as it is in other languages); therefore, when an array is passed, no return statement is need to modify its content. Integers - int are primitive type.
ISSUE no. 3: The Two Code Fragments In the Initial Questions (re-posted)
The two code fragments are indeed behaving differently. The first fragment is passing around values referring to a reference type. The second fragment is passing around values (or copies of values) of primitive type.
Therefore, the first code fragment has an effect, while the second does not
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 8 years ago.
class Util{
public static void F(Point p, Point q) {
p.x = 42;
p = q;
}
}
…
Point a = new Point(10,20);
Point b = new Point(30,40);
Util.F(a,b);
System.out.println(a.x + " " + b.x);
if someone can please explain me why the output is 42 30
thank in advance!
References are passed by values: http://javadude.com/articles/passbyvalue.htm
Let explain by a metaphore:
Suppose a red button.
When I click on the red button, a ball appears.
Now, in order to have quickly more balls, a new button is assigned the same function: the same ball appears when clicked.
Then, a person comes and alters this new button, to make an other ball appear!
What do you expect about the first button? To make appear the original one or the new one?
The original one of course! Since, although buttons pointed to the same ball, they are totally independent, explaining why change applying on the second button does not alter the objective of the first one.
Only if the second button MUTATED the first ball (without changing it!), for instance painting it in blue instead of red, then yes, the first button would point to the same ball blue, since it's..the same!
Replace original button by your a or b references and the ball by the x value of the created Point.
p.x = 42 is the assignment of the second ball.
p method parameter is the second button (since passed by value/copy).
Don't forget: MUTATIONS (p.x = 42 for instance) are visible to the caller environment but not the case of REPLACEMENTS (assignment)
I hope you understand now why the output is 42 30 and not 30 30 as you surely expected ;)
when you do p = q that does not change the value of Point a, it just change the reference of the temporary variable p, to be q.
but p.x=42 references to a value inside p, so that actually change it
p and q are value copies of references. Within F, assigning p = q just changes what p is pointing to, not the actual object itself, or any value in the caller.
p.x = 42 changes the field x to have the value 42 in the object referenced by p.
Putting it all together, a will have its x field changed by Util.F, but b is not changed in any way.
Method F changes value of field x in object passed as 1st argument to 42, while it doesn't change any state of fields in object passed as 2nd argument.
So, what you have done: you create object a, it doesn't matter what values you have passed inside its constructor: method F changed a.x to 42 <- this is the first part of your output.
Also you have created object b with x state equals to 30. Method F didn't change its values, so this is the second part of your output.
What about string code line p = q - it doesn't do anything worth. It just changes reference for variable p to be reference to object on which references variable q. It doesn't change object's state itself.
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.)