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)
Related
I am confused about how the array was assigned to any data, as the method meant to be a self contain
or I haven't understood a fundamental concept
// Craft stall stock and till program
import java.util.Scanner;
public class revisonTest {
public static void main(String[] args) // where program exicutes
{
final int numOFitems = 50;
String[] item = new String[numOFitems];
int [] broughtItem = new int[numOFitems];
int[] costItem = new int[numOFitems];
int COUNT = getDetail(item,broughtItem,costItem);
System.out.println(item[0]);
}
public static int getDetail(String[] name,int[] quantities,int[]cost)
{
int count =1;
int arrayIndex =0;
String answer = "";
while(!(answer.equals("Exit")))
{
answer = userInput("Item"+count+": ");
if(!(answer.equals("Exit")))
{
name[arrayIndex] = answer;
quantities[arrayIndex] = Integer.parseInt(userInput("How many "+name[arrayIndex]+" have you brought? "));
cost[arrayIndex] = Integer.parseInt(userInput("How much does a "+name[arrayIndex]+" cost? "));
count++;
arrayIndex++;
}
}
return count;
}
public static String userInput(String question)
{
Scanner sc = new Scanner(System.in);
System.out.println(question);
return sc.nextLine();
}
}
String[] item = new String[numOFitems];
This first makes a new treasure map named 'item'.
This makes a new treasurechest capable of containing numOFitems treasuremaps, and buries it in the sand. It is then filled with that many blank maps that lead to no treasure.
This updates your item treasuremap to point at this treasurechest-containing-maps.
getDetail(item,broughtItem,costItem);
This takes your treasuremap to the treasure-of-maps and makes a copy of it, and then hands the copy to the getDetail method. Your copy is unmodified and cannot be modified by getDetail... but that's just your copy of the treasure MAP, not the treasure. Note that getDetail calls this copy name and not item - which it is free to do.
(in getDetail) name[arrayIndex] = answer;
This is getDetail taking its name treasuremap (which is a copy of main's item map), follows the map, gets a shovel out, digs down, finds the treasure, opens it, finds the arrayIndexth map in it, pulls it up, and copies its answer map onto it.
Thus.. when main follows its copy of its map to the same treasure, same thing happens.
Of course, in java we use different jargon.
'treasure' -> 'object'
'treasuremap' -> 'reference'
'follow the map, dig down, open treasure' -> 'dereference'.
'create treasure' -> 'instantiate an object'
There are two different concepts here:
Allocating an array and assigning an array reference to a variable, and
Assigning values to elements in the array
In main, the new operation creates an array of a certain size, and assigns a reference to that array to the variable named item.
The call of getDetail(item,...) makes a copy of that reference (not the array itself) available to the method. Inside getDetail, this reference is stored in what is effectively a local variable, named name.
The loop inside getDetail is collecting answers (which are actually String references) and storing them in successive elements of the array that it knows as name and which the caller knows as item.
name[arrayIndex] = answer;
(Similarly for the other two arrays, of course)
In summary, getDetail is provided with an existing array, into which it writes values.
Incidentally, if the user types too many answers (more than name.length) you'll run off the end of the array, and get an 'index out of bounds' exception.
A String in java is considered a non-primitive data type. So when you created your item array using:
String[] item = new String[numOFitems];
You actually created an empty array of String objects. Based on your code the array has 50 empty spaces where you can store data.
The next part of your code is designed to get input from the user and fill those arrays:
int COUNT = getDetail(item,broughtItem,costItem);
Note: getDetail() never returns the item[] array, so how do you access the data?
When you pass your item array as an argument to the getDetail() method, you are actually passing that array as a reference.
In Java, non-primitive data types are passed as reference. This means that instead of sending the data to the getDetail() method, your actually sending information about where the data is located in memory.
Within your getDetail() method you can manipulate the data and the changes will be reflected on the original array without having to return it.
That is the reason why your print statement shows data in the array:
System.out.println(item[0]);
Any changes made within the getDetail() method, to the array, automatically appear on the original data source.
In my code below, I am storing current array in ArrayList of Arrays and whatever change I make on current array are reflected back in ArrayList at the same time? how is this happening ? But in else block, when I intialize current array with another array, it doesn't change in ArrayList.
List<int[]> res=new ArrayList<>();
int[] current=intervals[0];
res.add(current);
for(int[] interval:intervals){
int first=current[0];
int second=current[1];
int third=interval[0];
int fourth=interval[1];
if(second>=third){
current[1]=Math.max(second,fourth);
}
else{
current=interval;
res.add(current);
}
}
You have to take in account that by assigning intervals[0] to int[] current, you are not actually creating a new object. So your field current points to same object as intervals[0]. So when you call res.add(current), you are actually adding the array stored in intervals[0] to the List and any changes made in the current field will also be done in the array added to the List (because it is the same object). And as far as the code tells, you are not doing any changes on the array in else block, that's maybe why no changes are visible :P. If you do not want the array changes to be reflected in the list, before adding the array to the list, create a new array object and initialize it for example this way:
int[] current = new int[intervals[0].length]
for(int i = 0; i < intervals[0].length; ++i)
current[i] = intervals[0][i]
For your second question, if you have your array initialized like this:
int[][] intervals = new int[size][];
for(int i = 0; i < size; ++i)
intervals[i] = new int[size2];
that means that you created a new array (new object) inside each cell of the array. Now. This code:
int[] current=intervals[0];
Makes your variable current to point on the same object as intervals[0] does. So when you call res.add(current); you add the object current is pointing to to the list. So any changes made on current, or intervals[0] will also be reflected in the object stored in the list because it is the same object. But when you then assign another object to the current, when you call current = interval; you are just saying, that current now points to same object as interval does. That does not change the attributes of the original object current was pointing to (intervals[0]), current will be just pointing to another object.
A complete example of your program could help to answer to second part of your question. The central point is the pointer reference, and the resign of current has an impact to the second part of your question.
The array is a pointer to the memory where the "integers are located". At first when you add the intervals[0] into the res list, actually you are inserting a pointer address to the same memory. When you switch/change the values to the current they're reflected to res, because they points to the same memory. You can think at current[1]=Math.max(second,fourth); as: Get the address memory of the array and change its value at position 1. At this point the previous value in res in updated, because the address is the same. You can think it like an alias, they act like streets that goes to the same target.
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);
Can some one tell me how i would achieve the following. Java is not my strong point and after trying to search i keep getting pages on javas always pass by reference.
void edit(int[] a){
a = new String[]{"q","r","s","t","u"};
}
int[] x = new int[]{"a","b","c"};
edit(x);
System.out.println(x); // ["q","r","s","t","u"]
Im trying to achieve the above so that i can change the pointer of x after i've passed it into a function.
Thanks all for your help
Java is purely pass-by-value. You cannot do anything inside a method that changes the value of a variable used as an argument to the method. It simply isn't possible in Java.
In your example, you can change the content of the array, you just can't change what array x is referring to. You'd do that like this:
void edit(int[] a) {
a[0] = 1;
a[1] = 2;
a[2] = 3;
}
Note the distinction here: You can change the content of the array x refers to, but you can't change x from within edit. So for example, you can't change the length of the array, because the only way to do that is to create a new array and point x at it, and you can't do that within edit.
Other options:
Have edit return a new array, then assign that to x.
Use List, so you can change how many elements there are.
Create a class with mutable properties and pass an instance of that class in.
I'm working with two-dimensional array-values that should be inserted into a ArrayList. But this is done in a for-loop and the value of the two-dimensional array-value gets changed as the loop runs since it is just used as an temp-variable (which makes all of the variables stored in the ArrayList gets changed as this variable changes).
So if I try to print out the content of the ArrayList when the loop is done all the values are the same.
for(int i = 0; i <= Counter; i++)
{
if(Xhavetomove >= i)
arrayvalue[0][0] = this.Xspeed;
else
arrayvalue[0][0] = 0;
if(Yhavetomove >= i)
arrayvalue[0][1] = this.Xspeed;
else
arrayvalue[0][1] = 1;
System.out.println(arrayvalue[0][1]);
Object.movement.add(arrayvalue);
}
Are there anyway I can make it store the value itself?
For example: The first time the loop runs the value is "5,5" but if I print out the ArrayList when the loop is done all the values has turned into "5,1".
The problem is the way Array is added to the Object here. You are not adding the Array to the Object. What is happening is you are adding the address to the location in memory where the Array resides. So every time you add the Array to the Object, you are adding the same address every time. So every Array in the Object is actually the same Array over and over since they all point to a single location in memory. So when you change the Array, it will appear to change all of them inside the Object.
The best thing to do is either create a new Array every time through the loop, essentially creating a new location in memory for the Array to reside, or clone() the Array which will create a new reference.
Example:
String[] houseOfStark = {"Eddard", "Catelyn",
"Robb", "Sansa", "Arya", "Bran", "Rickon"}; // Sorry Jon
String[] copyOfStark = houseOfStark;
String[] cloneOfStark = houseOfStark.clone();
houseOfStark[1] = "Lady Catelyn";
System.out.println(houseOfStark[1]);
System.out.println(copyOfStark[1]);
System.out.println(cloneOfStark[1]);
Will produce:
Lady Catelyn
Lady Catelyn
Catelyn
Good blog post explaining the difference
At the end each add needs to create an own object.
To use clone is one way.
Or to add always the values in pairs, in an other.
A totally different way is to use serialization. This make sense when you do not want to calculate this values but to log it. In this case you need an outputStream
What is best is defined by what you want to do with Object.movement
You need to use array's clone() method to make its copy:
//for example
int[][] copy = (int[][])arraySource.clone();