From what I understand about Java (which is arguably pretty little =P), Java treats primitive values differently than objects. One example I can think of is that primitives are passed by value, while objects are passed via the value of their references.
Extending this, I have implemented code that creates an array of int, and shallow copied it over to a new array of int:
public class Test {
public static void main(String[] args){
int[] array = {2,3,4,5};
int[] copy = array;
copy[1] = 0;
for (int i : copy){
System.out.print(i);}
System.out.println();
for (int i : array){
System.out.print(i);}
}
}
However, the output is:
2045
2045
So, what puzzles me is why do both arrays change? I thought when we made a copy of the original array, we only copied over the values of the elements (since we are dealing with primitives)?
You didn't copy the array at all. What you did was make the references array and copy point to the same array in memory. Thus, when you change the array via one reference, the other reference will point to the same change.
Arrays are objects. When you set
int[] copy = array;
both copy and array refer to the same object. Your update
copy[1] = 0;
updates "both".
When you made the assignment copy[1] = 0, you told Java to take the array which copy refers to, go to position 1, and assign the value 0. Since you also have the following statement
int[] copy = array;
then copy and array refer to the same array in memory. You never really made a shallow copy, you only assigned another variable to point to the same array.
If you want to make a copy of the array, then you could try:
int[] copy = Arrays.copyOf(array, array.length);
Related
I have really strange problem. In activity I declare two arrays
private String original[] = new String[100];
private String changed[] = new String[100];
Then I assign values to those two arrays in OnCreate:
Bundle extras = getIntent().getExtras();
if (extras != null) {
original = extras.getStringArray("sentArray");
changed = original;
}
Now if I change values of members of changed array, original array will also have that members changed.
For example, after I do
changed[0] = "New value";
value of original[0] is also "New value".
How is something like that possible? Is this a bug?
changed = original;
This line is setting 'changed' to 'original' so they're the same array with the same pointers. You need to copy the array instead of setting changed equal to original.
You can try using System.arraycopy()
Everything in Java are passed-by value.. In case of Array(Which is
nothing but an Object), array reference is passed by value.. (Just
like an object reference is passed by value)..
When you pass an array to other method, actually the reference to that
array is copied..
Any changes in the content of array through that reference will affect
the original array.. But changing the reference to point to a new
array will not change the existing reference in original method..
Use
System.arraycopy()
Check this
When u copy an array like this:
changed = original;
you are copying the reference of the array. if you want to copy all the values from one array to other, you can do this:
for(int i = 0; i < original.size(); i++){
changed[i] = original[i];
}
That`s one way you can do this.
Doing this, if you change anything from the first one or the second one, the other will remain untouchable.
Hope i can help.
When we do Changed = Original, we actually assigning reference of array. Hence if we make any change to one array, it would be reflected in other array as well because both Changed and Original refer to same location.
We can also use System.arraycopy() Method. System is present in java.lang package. Its signature is as :
public static void arraycopy(Object src, int srcPos, Object dest,
int destPos, int length)
This question already has answers here:
What is the difference between a variable, object, and reference? [duplicate]
(5 answers)
Closed 7 years ago.
Consider the following:
array1 contains a list.
int[] unSorted = array1; a new initialized array works as a (duplicate).
Arrays.sort(array1); suppose to sort only the original Array array1.
The problem occurs when I use the sort method Arrays.sort. It sorts all Arrays that are linked to array1, including the (duplicate)!! Why is that? It should change only the array that is declared inside the parentheses! Isn't it?
Your unSorted is not "a new initialized array". It is just a different name for the same array.
Arrays are Objects, not primitives. They are passed around as pointers, not as copies.
If you want a copy, use java.util.Arrays#copyOf.
Consider the following example: array & copy both refer to the same object - which is not the case with store.
import java.util.Arrays;
class Test {
public static void main(String[] args) {
// array & copy both refer to the same Object
double[] array = {5,4,3,2,1};
double[] copy = array;
// the following array is filled up "by hand" - thus it has no reference to the previous object
double[] store = new double[array.length];
for (int i = 0; i < array.length ; i++) {
store[i] = array[i];
}
Arrays.sort(array);
System.out.println("array"); // 1,2,3,4,5
for (double d: array)
System.out.println(d);
System.out.println("copy"); // 1,2,3,4,5
for (double d: copy)
System.out.println(d);
System.out.println("store"); // 5,4,3,2,1
for (double d: store)
System.out.println(d);
// Primitives show a different behaviour
double a = 5;
double b = a;
System.out.println(a + " / " + b); // 5 / 5
a = 10;
System.out.println(a + " / " + b); // 10 / 5
}
}
array1 isn't actually an array: it's a reference to an array. It's a bit like if you give someone a business card with your office address, that card isn't the actual office, but rather something that tells you how to reach the office.
When you do int[] unSorted = array1, you're making a copy of the reference, not the array. Again, it's like someone copying down the info on your business card.
And when you perform an operation on unSorted (like moving its elements to sort then), what you're actually doing is performing an operation on the object it points to. It's like saying, "go to the office specified on the business card called unSorted, and move the chair at desk 1 to desk 2."
If you then went to the office specified on the business card called array1, you would of course expect that the chair has moved there, since it's the same office.
If you want a copy, you have to create one. There are a few ways to do that, but the easiest is to use Arrays.copyOf.
Look at it this way :
You have a controller for a television (the array of course) and manage to duplicate the controller : you still have one television with multiple controllers.
If you change the television channel with one controller, even if you didn't touch the others, the televisions state has changed.
The same logic has to be applied to your problem.
Your unsorted variable is a reference.
Remember references point to an object.
So when you declared and instantiated array1, you may have done the following:
int[] array1 = new int[/*Any positive integer*/]
When declaring your unsorted reference variable, you did not instantiate a new array, you simply created a reference variable which points to the same object as array1.
Consider the image below:
So array1 and unSorted point to the same object, so of course if you call a method on either one of them you will effect the same object.
Because they are all the same array, not 'other arrays'.
You need to think about what you mean by 'all other arrays that are linked'.
I've learnt that for arrays the clone method is well-behaved and we can use it. But I thought that the type of the elemetns the arrays hold should have implemented Cloneable interface. Let me provide some example:
public class test {
public static void main(String[] args){
Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = arr_t.clone();
an_arr[0]= new Test(5);
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test); //10
}
public static class Test{
public int test;
public Test(int test) {
this.test = test;
}
}
}
DEMO
I thought that 5 should have been printed twice. The reason for that is by clonning arrays we're creating new arrays containing references to the objects the first array holded (Because the type of the elemnts does not implement Cloneable). Couldn't you straighten the things out?
It's not clear if it's neccesary the array element's type implements Cloneable.
It's a simple concept, but seems hard to explain. When you clone the array, you will have two district arrays in memory, but with the same values in their indexes.
In your second array an_arr doing an_array[0] = new Test(5) you will put another reference in the slot 0.
But the index 0 of the clone is in a different place from the cloned array.
Your example is valid if you do
Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = arr_t.clone();
an_arr[0].test = 5; // look here, I changed the object
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test); //5
Now both will print the same value because they hold the same reference to the same object, but the place where this reference is stored, is different.
.clone() makes what's called a "shallow copy". That means it copies as little as possible when running the method; instead of copying the contents of the array, it just creates references to the contents of the original array.
If you change the references by calling:
new Test(5)
Then you've overwritten that reference, and get new data.
The alternative is a deep copy of the array. Those can be expensive to do on bigger objects, so they're not the default.
An array's clone() does the same thing regardless of type of array: it creates a new array of the same type and size and then it assigns (=) each element of array to each element of the new array. That's it.
So if you have a 3-element array pointed to by arr, and arr.clone() returns newArr, then after the creation of the new array it simply does this:
newArr[0] = arr[0];
newArr[1] = arr[1];
newArr[2] = arr[2];
That's it. The type of array is not relevant. There is no "cloning" or anything involved in the elements. It doesn't know (or care) if the element has some kind of method to clone (in fact, there is no general API for cloning in Java, anyway, so this would be impossible).
(And by the way, even if it somehow put cloned objects into the new array, the result in your example would still be the same, because you are assigning a new value into the array, so it doesn't matter what was there before.)
So your question is basically why:
Test[] arr_t = new Test[1];
arr_t[0] = new Test(10);
Test[] an_arr = new Test[1];
an_arr[0] = arr_t[0];
an_arr[0] = new Test(5);
System.out.println(an_arr[0].test); //5
System.out.println(arr_t[0].test); //10
and you can figure it out from there.
The "problem" here is that arrays hold references to object, not objects. Further, this has nothing to do with cloning.
When you execute:
an_arr[0] = new Test(5);
You are assigning the new object's reference to the first element.
Also, each array has its own references to Test objects. When you clone the array, only the references are copied (not the objects to which they refer).
I'm having trouble reassigning values in an array.
public static void main(String[] {
int[] arrayOfIntegers = new int[4];
arrayOfIntegers[0] = 11;
arrayOfIntegers[1] = 12;
arrayOfIntegers[2] = 13;
arrayOfIntegers[3] = 14;
arrayOfIntegers = {11,12,15,17};
}
Why am I unable to reassign values in the manner that I've attempted? If I can't do it, why can't I do it?
Why am I unable to reassign values in the manner that I've attempted? If I can't do it, why can't I do it?
Because Java doesn't have destructuring assignment like some other languages do.
Your choices are:
Assign a new array to the array variable as shown by Rohit and Kayaman, but that's not what you asked. You said you wanted to assign to the elements. If you assign a new array to ArrayOfIntegers, anything else that has a reference to the old array in a different variable or member will still refer to the old array.
Use System.arraycopy, but it involves creating a temporary array:
System.arraycopy(new int[]{11,12,15,17},
0,
ArrayOfIntegers,
0,
ArrayOfIntegers.length);
System.arraycopy will copy the elements into the existing array.
You need to provide the type of array. Use this:
arrayOfIntegers = new int[] {11,12,15,17};
From JLS Section 10.6:
An array initializer may be specified in a declaration (§8.3, §9.3, §14.4), or as part of an array creation expression (§15.10), to create an array and provide some initial values.
If you are trying to re-assign array elements in some range, you can't do that with direct assignment. Either you need to assign values at indices individually, or use the way as given by #TJCrowder in his answer.
The correct syntax is:
arrayOfIntegers = new int[]{11,12,15,17};
I need to make a temporary copy of an array of cards that I do not have direct access to because it is in another class named Hand. I am given a method called getHand() which returns the reference to the array I need a copy of in the class RummyHand which is a subclass of Hand. The variable rummyHand is an instance variable in the RummyHand class and is a Hand object. Also I am working in eclipse if that matters.
but neither this:
Card[] temp = new Card[8];
temp = rummyHand.getHand();
or this:
Card[] temp = rummyHand.getHand();
has copied the array like I thought it would.
You can use Arrays.copyOf or System.arrayCopy to copy an array, or, more simply, clone():
Card[] temp = rummyHand.getHand().clone();
Note that using the = operator never copies any data. All = does is make a variable refer to a different thing. This is important to understand because otherwise it will cause you a lot of trouble down the road.
In (hopefully useful) detail:
new Card[8];
creates an array: a new area of memory big enough to hold pointers to 8 cards.
Card[] temp
creates a variable that must point to some kind of array of cards. The
=
in the middle makes the variable point to that area of memory. The expression
rummyHand.getHand();
supplies you with the address of a different area of memory. So the line
temp = rummyHand.getHand();
just makes the temp variable point to that area of memory instead. copyOf, arrayCopy and clone all work by creating a new array and filling it with the references from the original array, then handing you back the new array.
use
Card[] hand = rummyHand.getHand();
Card[] temp = new Card[hand.length()];
System.arraycopy(hand,0,temp,0,hand.length());
Afterwards you have a copy of the array - but keep in mind that the references to the cards in the array are still the same. Therefore if you change a property of a card in temp it will also change the card in hand as both arrays contain the same "card instances".
You can use clone to copy an array:
Card[] temp = rummyHand.getHand().clone();
This will give you an exact copy of the same length as the original. If you want the copy eight elements long regardless of the length of the original, you can use Arrays.copyOf:
Card[] temp = Arrays.copyOf(rummyHand.getHand(), 8);
There are a few ways to copy an array. The most basic is to create an array of the same size as the source array, then loop over the elements of the source array and add each one to your new copy:
Card[] source = rummyHand.getHand();
Card[] temp = new Card[source.length];
// for loop:
for (int i = 0; i < source.length; i++)
temp[i] = source[i];
But there are java utility classes that will do this for you. See Arrays.copyOf:
Card[] temp = Arrays.copyOf(source, source.length);
But note that your new array will contain the same Card references as the source array, meaning that any changes to the objects in the array won't change copies: they'll change the actual object. If you need copies of the contents of the array, then you'll need to use the loop, and make a copy of each Card before adding it to the temp array.
When you're doing: temp = rummyHand.getHand();, you're getting a reference to the original array, not a copy, and so any changes that you make will change the array in the rummyHand object..