I have to implement an array that takes its elements from a random generator. Whenever the array reaches it's last element a method resize() will be called to increase the size of the array. In my code every thing goes alight until invoking resize() method, it does not do any effect on the size of the array. It supposed to increase the size of the array to allow more elements to be entered.
for (int j=0; j<arr.length-1; j++) {
random= generator.nextInt(arr.length*4) ;
arr[j]=random;
}
if(arr_size==arr.length){
resize(arr);
for (int h=0; h<(arr.length-1)*2; h++) {
random= generator.nextInt(arr.length*4) ;
arr[h]=random;}
}
Here is resize():
private static void resize(int[] arr) {
int[] tmp = new int[2*arr.length];
System.arraycopy(arr,0,tmp,0,arr.length);
arr = tmp;
}
Setting arr = tmp does not do what you think it does. You're simply pointing the local variable arr in the resize() method to the local variable tmp. What you want to do is return tmp and assign it to arr outside of the method.
if(arr_size==arr.length){
arr = resize(arr);
And change the resize() method signature to
private static int[] resize(int[] arr) {
//Resize
return tmp;
}
The key thing to take away is that: When passing an object reference to a method in Java, you're passing a copy of that object's reference, which can be thought of as a copy of the location in memory of that object. All such manipulations to this REFERENCE in the called method won't take effect outside of the method. However, you CAN manipulate the actual object itself because, as I said, the reference is pointing to the same place in memory with the exact same object.
But changing a copy of a location in memory to point to a new location in memory does not cause the original calling object reference to point to that same location
try this :
private static int[] resize(int[] arr) {
int[] tmp = new int[2*arr.length];
System.arraycopy(tmp,0,arr,0,arr.length);
System.out.println(tmp.length);
return tmp;
}
Either set and return the tmp variable as described by Kon, or you pass in arr by reference to make changes to it persist outside of the resize function:
private static void resize(ref int[] arr) { .... }
and call it like
resize(ref arr);
When you say New int, reference is changed. Java uses Copy by Reference not exactly Pass by reference, if you change reference by new the caller method properties wont have any change, in your case have a return type and assign it back to arr.
Related
I'm having a problem in my code. I have an object that contains a matrix of integers, and I'm using this matrix as the original "model" to create other matrices. But at the end, my original matrix has a different value, but I'm not changing in any way.
public Matrix generateAdjacencyMatrix(Matrix m)
{
int storedValue;
int fitness;
int[][] auxiliar_matrix = mc.matrixStructure.matrix;
int[] original_ordering = mc.matrixStructure.matrixOrder;
for(int i=0;i<mc.matrixStructure.getMatrixSize();i++)
{
if(m.matrixOrder[i] != original_ordering[i]) //Only changes if the columns have changed
{
for(int j=0;j<mc.matrixStructure.getMatrixSize();j++)
{
storedValue = auxiliar_matrix[j][m.matrixOrder[i]];
auxiliar_matrix[j][m.matrixOrder[i]] = auxiliar_matrix[j][original_ordering[i]];
auxiliar_matrix[j][original_ordering[i]] = storedValue;
}
for(int j=0;j<mc.matrixStructure.getMatrixSize();j++)
{
storedValue = auxiliar_matrix[m.matrixOrder[i]][j];
auxiliar_matrix[m.matrixOrder[i]][j] = auxiliar_matrix[original_ordering[i]][j];
auxiliar_matrix[original_ordering[i]][j] = storedValue;
}
}
}
m.matrix = auxiliar_matrix;
m.setFitness(computeFitness(m.matrix));
return m;
}
This is the method that creates the other matrices. The object "mc" contains my original matrix (mc.matrixStructure.matrix), and exactly after the for loop the value is different.
I am instantiating this object on the constructor method:
public GeneticAlgorithm() throws IOException
{
this.r = new Random();
this.matingPool = new ArrayList<>(populationSize);
this.population = new ArrayList<>(populationSize);
this.nextGeneration = new ArrayList<>(populationSize);
this.mc = new MatrixCreator("CS4006_input_file2.txt");
this.mc.check0or1();
this.mc.checkDiagonalLine();
this.mc.checkSymmetry();
this.auxiliarVector = mc.matrixStructure.matrixOrder;
this.auxiliarMatrix = new Matrix(mc.matrixStructure.getMatrixSize());
this.matrixSize = mc.matrixStructure.getMatrixSize();
}
This is it.
When you do this ...
int[][] auxiliar_matrix = mc.matrixStructure.matrix;
int[] original_ordering = mc.matrixStructure.matrixOrder;
... you are making auxiliar_matrix and original_ordering references to the same objects that mc.matrixStructure.matrix and mc.matrixStructure.matrixOrder refer to. Modifying those objects via one set of references is equivalent to modifying them through the other, so contrary to your assertion, you absolutely are changing your original matrix. To avoid this, you need to copy the arrays.
Moreover, you have that problem twofold with auxiliar_matrix because Java 2D arrays are arrays of arrays, and arrays are objects, too. You need to perform a deep copy of that 2D array to avoid modifying the original object.
Something like this should do it:
int[] original_ordering = Arrays.copyOf(mc.matrixStructure.matrixOrder);
int[][] auxiliar_matrix = Arrays.copyOf(mc.matrixStructure.matrix);
int i;
for (i = 0; i < auxiliar_matrix.length; i += 1) {
auxiliar_matrix[i] = Arrays.copyOf(auxiliar_matrix[i]);
}
When you assign an object to a reference variable, you assign its reference. You do not copy it to that reference.
Thus, after an assignment such as
int[][] auxiliar_matrix = mc.matrixStructure.matrix;
Your auxiliar_matrix reference variable now refers to the matrix to which mc.matrixStructure.matrix refers.
It's the same matrix, residing on the heap.
Now you are changing data inside the object referred to by auxiliar_matrix. For example, here:
auxiliar_matrix[j][original_ordering[i]] = storedValue;
This means the value will be changed in the matrix both it and mc.matrixStructure.matrix are referring to.
If you want to work on a separate copy of your original matrix without affecting it, you have to copy it to a new object first, and then assign this copy to auxiliar_matrix. In this case, it's an array of arrays, so you have to create a new array of the same length, and copy over each of the subarrays using Arrays.copyOf. Beware of trying to use Arrays.copyOf on the array of arrays - the copy is shallow and it will just copy references to the subarrays which would give you the same problem.
I was doing some exercises on arrays, and I was prompted to return a reference to an array after copying it element by element. What does this exactly mean?
My code is the following:
public static int[] cloneArray(int array[])
{
int[] arraycopy = new int[array.length];
for(int i = 0; i < array.length; i++)
{
arraycopy[i] = array[i];
}
return arraycopy;
}
I don't know what I should be returning though as a "reference": should I return an array of ints or an int? Whenever I try to print the array, I get a weird combination of characters and numbers (unless I invoke Arrays.toString()).
"Return a reference to an array" just means "return an array".
Java only returns values, which are either primitives or object references (ie for objects, the value is a reference).
Although Java is based on C, it doesn't sully itself with pointers etc like C does.
In Java, arrays and objects do not act like primitive types such as int. Consider the following code:
public class MyClass {
public static int method1(int ar[]) {
int x = ar[1];
ar[1] = 3;
return x;
}
}
Now suppose that somewhere else, the follow code is executed:
int abcd[] = new int[3];
abcd[0] = 0;
abcd[1] = 1;
abcd[2] = 2;
int d = MyClass.method1(abcd);
System.out.println(abcd[1]);
What would be printed? It's not 1, but 3. This is because the method was not given the data in the array, it was told the location of the array. In other words, it was passed a reference. Because it was using a reference, changing the value of an array index changed its value in the code that called it. This would not have happened if method1 had taken an int as an argument.
Basically, in Java, methods do not accept arrays as arguments or return arrays. They only use references to arrays. The same goes for objects (except for Strings, which are passed by value).
In Java, Objects are only accessed by reference. Just return the Array object.
I am having a little trouble understanding the concept of final in Java.
I have a class that follows:
public class MyClass
{
private int[][] myArray; // intended to be changed
private final int[][] MYARRAY_ORIGINAL; // intended to be unchangable
public MyClass(int[][] array)
{
myArray = array;
MYARRAY_ORIGINAL = array;
}
}
I was under the understanding that final would make MYARRAY_ORIGINAL read only. But I have tried editing myArray, and it edits MYARRAY_ORIGINAL as well. My question is, in this context, what exactly does final do? And for extra credit, how can I copy the array passed through the constructor into MYARRAY_ORIGINAL so that I can have 2 arrays, one to edit, and one that will remain preserved?
Your final MYARRAY_ORIGINAL is indeed read only: you can't assign a new value to the MYARRAY_ORIGINAL reference in other side than class constructor or attribute declaration:
public void someMethod() {
//it won't compile
MYARRAY_ORIGINAL = new int[X][];
}
The values inside the array are not final. Those values can change anytime in the code.
public void anotherMethod() {
MYARRAY_ORIGINAL[0][0] = 25;
//later in the code...
MYARRAY_ORIGINAL[0][0] = 30; //it works!
}
If you indeed need a List of final elements, in other words, a List whose elements can't be modified, you can use Collections.unmodifiableList:
List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
The last piece of code was taken from here: Immutable array in Java
In case of Objects, final makes reference can't be changed, but object state can be changed.
That is the reason why you are able to change values of final MYARRAY_ORIGINAL
MYARRAY_ORIGINAL is indeed read only variable. Your array reference can not be assigned a new value nor for their length of the arrays can be changed. A final variables initialization can be deferred till the constructors is called. If one tries to modify the reference of the final variable, compiler will throw an error message. But what is possible is, one can edit the elements of the MYARRAY_ORIGINAL and of the myArray i.e one can change the state of the object assigned to a final variable. For example
Class A {
final int[] array;
public A() {
array = new int[10] // deferred initialization of a final variable
array[0] = 10;
}
public void method() {
array[0] = 3; // it is allowed
array = new int[20] // not allowed and compiler will throw an error
}
}
To understand more on final please take a look at Java Language Specification on final variable.
Final does not mean 'read-only' per se, but more so "safe publication' for other threads than the one to which it is defined. Another aim of 'final' is that it ensures the latest object available in a multi-thread environment.
Secondly, if you define something as "final", for example:
private final int[][] MYARRAY_ORIGINAL;
The reference is "final", but not the object itself. A much better way to understand it would be this:
public static final List myList = new ArrayList();
Now I can access myList from any other threads - I can modify it (add to it); but I cannot
(a) Declare it again - myList = new ArrayList();
(b) Assign it another list - myList = anotherList;
The context for final I would see best, in a multiple-thread scenario.
Bonus: to answer your question, you cannot make a 'readonly' array, you will have to manage that yourself (as final, only maintains 'read-only' to reference not object)
You can use the method System.arraycopy to make a copy of the array as follows -
int[][] source = {{1,2},{3,4}};
int[][] copy = new int[source.length][];
System.arraycopy(source, 0, copy, 0, source.length);
Also, you some problem with your code regarding what you are trying to do. If you look at the constructor
public MyClass(int[][] array) { //something else passes the array
myArray = array;
MYARRAY_ORIGINAL = array; // you are just keeping a reference to it can be modified from outside
}
If you really want nobody to modify the values in that array MYARRAY_ORIGINAL, you should make a copy of the source array that comes comes from outside.
public MyClass(int[][] array) {
myArray = array; //make a copy here also if you don't want to edit the argument array
MYARRAY_ORIGINAL = new int[array.length][];
System.arraycopy(array, 0, MYARRAY_ORIGINAL, 0, array.length);
}
Now you shouldn't have to worry about the array's being modified from outside.
I'm doing a task for a course in Java programming and I'm not sure how the following thing is working? The method below takes the value from an array and a integer. The integer should be added to the array and then be used outside the method in other methods and so on, but how could this work when the method has no return for the new content of the array? There is a void in the method? Have I missed something? Preciate some help? Is there something about pointers?
public static void makeTransaction(int[] trans, int amount);
Arrays in Java are objects. If you modify the trans array inside the method, the changes will be reflected outside of it1. Eg:
public static void modify(int[] arr)
{
arr[0] = 10;
}
public static void main(...)
{
int x = {1, 2, 3};
System.out.println(x[0]); // prints 1
modify(x);
System.out.println(x[0]); // now it prints 10
}
Note that native arrays can't be dynamically resized in Java. You will have to use something like ArrayList if you need to do that. Alternatively you can change the return type to int[] and return a new array with the new element "appended" to the old array:
public static int[] makeTransaction(int[] trans, int amount)
{
int[] new_trans = Arrays.copyOf(trans, trans.length + 1);
new_trans[trans.length] = amount;
return new_trans;
}
1 It is also worth noting that as objects, array references are passed by value, so the following code has no effect whatsoever outside of the method:
public void no_change(int[] arr)
{
arr = new int[arr.length];
}
You can't add anything to an array. Java arrays have a fixed length. So indeed, what you want to do is impossible. You might make the method return an int[] array, but it would be a whole new array, containing all the elements of the initial one + the amount passed as argument.
If you want to add something to an array-like structure, use an ArrayList<Integer>.
Do you have to keep the method signature as is?
Also, can you be a bit more specific. When you say "the integer should be added to the array", are you referring to the amount argument? If so, then how is that amount added? Do we place it somewhere in the array or is it placed at the end, thus extending the array's length?
As far as pointers go, Java's pointers are implicit, so if you don't have a strong enough knowledge of the language, then it might not be so clear to you. Anyways, I believe that Java methods usually will pass objects by reference, and primitives by value. But, even that isn't entirely true. If you were to assign your object argument to new object, when the method terminates, the variable that you passed to the method is the same after the method executed as it was before. But, if you were to change the argument's member attributes, then when the method terminated those attributes values will be the same as they were inside of the method.
Anyways, back to your question, I believe that will work because an array is an object. So, if you were to do the following:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
}
// static int i;
/**
* #param args
*/
public static void main(String[] args)
{
int[] trans = {0,1,3};
makeTransaction(trans, 10);
for(int i = 0; i<trans.length; i++)
{
System.out.println(trans[i]);
}
}
The output of the array will be:
10
1
3
But, watch this. What if I decided to implement makeTransaction like so:
public static void makeTransaction(int[] trans, int amount)
{
trans[0] = amount;
trans = new int[3];
}
What do you think that the output will be? Will it be set to all zero's or will be the same as it was before? The answer is that the output will be the same as it was before. This ties in to what I was saying earlier.
I might've assigned that pointer to a new object in memory, but your copy of the pointer inside of the main method remains the same. It still points to the same place in memory as it did before. When the makeTransaction method terminates, the new int[3] object that I created inside of it is available for garbage collection. The original array remains intact. So, when people say that Java passes objects by reference, it's really more like passing objects' references by value.
Suppose I have an int-array and I want to modify it. I know that I cannot assign a new array to array passed as parameter:
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]); // prints 1
}
public static void method(int[] n)
{
n = new int[]{2};
}
while I can modify it:
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]); // prints 2
}
public static void method(int[] n)
{
n[0] = 2;
}
Then, I tried to assign an arbitrary array to the array passed as parameter using clone():
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]); // prints 1 ?!
}
public static void method(int[] n)
{
int[] temp = new int[]{2};
n = temp.clone();
}
Now, I wonder why it prints 1 in last example while I'm just copying the array with clone() which it's just copying the value not the reference. Could you please explain that for me?
EDIT: Is there a way to copy an array to object without changing the reference? I mean to make last example printing 2.
Your examples 1 and 3 are virtually the same in context of the question - you are trying to assign a new value to n (which is a reference to an array passed by value).
The fact that you cloned temp array doesn't matter - all it did was create a copy of temp and then assign it to n.
In order to copy values into array passed into your method method you might want to look at:System.arraycopy
It all, of course, depends on the sizes of your n array and the one you create inside method method.
Assuming they both have the same length, for example, you would do it like that:
public static void main(String[] args)
{
int[] temp_array = {1};
method(temp_array);
System.out.println(temp_array[0]);
}
public static void method(int[] n)
{
int[] temp = new int[]{2};
System.arraycopy(temp, 0, n, 0, n.length);
// or System.arraycopy(temp, 0, n, 0, temp.length) -
// since we assumed that n and temp are of the same length
}
In your method
public static void method(int[] n)
n is another name for the array that way passed in. It points to the same place in memory as the original, which is an array of ints. If you change one of the values stored in that array, all names that point to it will see the change.
However, in the actual method
public static void method(int[] n) {
int[] temp = new int[]{2};
n = temp.clone();
}
You're creating a new array and then saying "the name 'n' now points at this, other array, not the one that was passed in". In effect, the name 'n' is no longer a name for the array that was passed in.
As you correctly note, you cannot assign to the array reference passed as a parameter. (Or more precisely, the assignment won't have any effect in the caller.)
This is about the best that you can do:
public static void method(int[] n) {
int[] temp = new int[]{2};
for (int i = 0; i < temp.length; i++) {
n[i] = temp[i];
}
// ... or the equivalent using System.arraycopy(...) or some such
}
Of course, this only works properly if the size of the input array is the same as the size of the array you are copying to it. (How you should deal with this will be application specific ...)
For the record Java passes the array reference by value. It doesn't pass the array contents by value. And clone won't help to solve this problem. (At least, not with the method signature as declared.)
In your method method, nothing that you assign to n will ever change the value of the object passed in and assigned to n. At the beginning of method, n points to an array. When you assign n to equal another array, you've simply re-pointed which array n points to, and haven't changed anything about temp_array from the main method.