Modify an array passed as a method-parameter - java

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.

Related

Trick the private keyword in Java

I am aware that the idea of the keyword private is to enable encapsulation. However, I got confused when I realized that I can modify an Array after retrieving it with a getter, which surprised me. The same didn't work for the plain integer, although I thought java treats all variables as objects.
The example:
public class PrivContainer {
private int[] myIntArray;
private int myInt;
PrivContainer(){
myIntArray=new int[1];
myIntArray[0]=3;
myInt=22;
}
public int[] getIntArray(){
return myIntArray;
}
public int getInt(){
return myInt;
}
public void printInt(){
System.out.println(myIntArray[0]);
System.out.println(myInt);
}
}
public class Main {
public static void main(String[] args){
PrivContainer pc=new PrivContainer();
int[] r=pc.getIntArray();
int q=pc.getInt();
r[0]=5;
q=33;
pc.printInt();
}
}
The Output of printInt() is 5,22
This means that main method could change the entries of the private array but not of the private int.
Could someone explain this phenomena to me?
An array is a mutable Object. Therefore, if you have a reference to that array, you can modify its contents. You can't do the same with primitive members of a class (such as int) and with references to immutable class instances (such as String and Integer).
Your assignment :
q=33;
Would be similar to :
r = new int [5];
Both of those assignments cause the variables to contain new values, but they don't affect the state of the PrivContainer instance from which the original values of those variables were assigned.
Nothing seems strange here. What happen basically as follow.
public class Main {
public static void main(String[] args){
PrivContainer pc=new PrivContainer(); <-- create new `PrivContiner` object which also initialised the private variables
int[] r=pc.getIntArray(); <-- you get the "object" integer array here and assign r to refer to that object
int q=pc.getInt(); <-- you get the "primitive" integer here and assign q to refer the myInt variable here.
r[0]=5; <-- you assign the first value of the array 5. Note that the object reference is still the same here
q=33; <-- you assign the variable q to 33. Note that, this mean, the variable q refer to another primitive here (which is 33)
pc.printInt(); <-- print the content of the object here.
}
}
When you invoke the printInt function. the output will be 5 and 22 as the new integer (33) is assigned to q and its scope is only within the main function.
While you return an array from a getter you return the reference of that object. Since you have the reference you can change its elements. If you want to avoid this behavior you will have to return the clone of your array in that case you wont be able to change the elements of your array
public class Main {
public static void main(String... args) {
Arr arr = new Arr();
int[] y = arr.getX();
y[1] = 5;
System.out.println(arr.getX()[1]);
}
}
class Arr {
private int[] x = {1, 2, 3};
public int[] getX() {
return x.clone();
}
}
Try this code and remove the clone method, like this
class Arr {
private int[] x = {1, 2, 3};
public int[] getX() {
return x;
}
}
Now execute the main method, you will observe that changing value of y will change the value of array x as well.

arrays passing to methods in Java - What is passed here? Value or Reference?

When I passing an object reference (arrays are objects) to a method, the value is passed, right?
In the following code the initial value is: 333. After method passing, the value is changed. Why? Is in this case the reference passed instead the value?
Are arrays "special cases"?
public static void main(String[] args) {
int[] myArray = { 333 };
valueOrRef(myArray); // Value or Reference?
System.out.println(myArray[0]); // 777 (changed)
}
public static void valueOrRef(int[] myArgument) {
myArgument[0] = 777;
}
Another approach: (the logic "pass by value"):
public static void main(String[] args) {
int[] myArray = { 333 };
valueOrRef(myArray[0]); // Value or Reference?
System.out.println(myArray[0]); // 333 (after method still unchanged)
}
public static void valueOrRef(int myArray2) {
myArray2 *= 2;
}
The value is always passed, but keep in mind that for arrays the value is in fact a reference to an array and not the array itself.
The first valueOrRef method changes the content of the array pointed at by myArgument which is why you see the effect on the array after calling the method.

How do I make an array parameter in java?

I tried to make a parameter for an array for a method, but it always comes up with an error.
public void methodExample1() {
int array1[] = new int[4]
}
public void methodExample(Array array1[]) {
System.out.println(array1[0]);
}
But it always says there's an error in my parameter. Is there any way to do this?
Try this:
public void methodExample(int[] array1)
Explanation: The type is the same that you used for declaring a value that will be passed as parameter (for the moment I'm ignoring covariant arrays), for instance if you do this:
int[] array1 = new int[4];
... Then, at the time of passing it as a parameter we'll write it like this:
methodExample(array1)
Also notice that the size of the array must not be passed as parameter, and that by convention the [] part goes right after the type of the array's elements (in fact, int[] is the type of the array), and not after the array's name.
If I understand your question, then you could use Array, and something like
public static void methodExample(Object array1) {
int len = Array.getLength(array1);
for (int i = 0; i < len; i++) {
System.out.printf("array1[%d] = %d%n", i, Array.get(array1, i));
}
}
public static void main(String[] args) {
methodExample(new int[] { 1, 2, 3 });
}
Output is
array1[0] = 1
array1[1] = 2
array1[2] = 3
I assume that you are trying to pass array as a parameter to a method , to initialize it and then call another method to print it?
In java you have to create an object and "allocate" memory space for it by calling to new ...
so you can do like that :
public static void main(String[] args) {
int [] m_array; // creating a array reference
m_array = new int[5]; // allocate "memory" for each of of them or you can consider it as creating a primitive of int in each cell of the array
method(m_array); // passing by value to the method a reference for the array inside the method
}
public void method(int [] arr) // here you are passing a reference by value for the allocated array
{
System.out.println(arr[0]);
}

How to double the size of an array

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.

Correctly input int[] in java method?

This method insert takes as input int[] array, int element, and int index, which inserts element into the index position of array. Since an array is not resizable, the method shifts every element over to the right of the array by one. The element at the end is removed from the array. The method returns void.
public class ShiftElements {
public static void insert(int[] array, int element, int index)
{
for (int i = array.length-1; i > index; i--)
{
array[i] = array[i-1];
}
array[index] = element;
}
}
To test if this method works, I changed the return type to int[] and wrote a main method to print array:
public class ShiftElements {
public static int[] insert(int[] array, int element, int index)
{
for (int i = array.length-1; i > index; i--)
{
array[i] = array[i-1];
}
return array;
}
public static void main(String[] args) {
System.out.print(insert(4,5,3));
}
}
I am having problems, getting this print statement to work. It's probably something simple, but I've been up for two days studying for finals so I'm pretty braindead.
I'm pretty sure I called the insert method just fine, but I think my issue is that I'm not properly inputting the type int[]. I'm not sure how I'm supposed to do this.
1) The first parameter of insert is an array of int, not an int. You must call :
insert(new int[]{4},5,3)
2) you can't print an array : so use :
println(Arrays.toString(insert(...)))
I guess what you are looking for is :
int[] i = new int[5];
System.out.print(java.util.Arrays.toString(insert(i,5,3)));
Apart from the use of java.util.Arrays.toString method Watch out the parameters that you are passing in insert method:
first parameter should be an array of int. But you are passing an int.
System.out.print(insert(4,5,3));
That statement does not pass a array of integers, you only passed and integer 4. You would need to pass, as your function is defined, int[], int, int.
System.out.print(insert(new int[4],5,3));
You made a call to insert(int,int,int) eventhough your signature for insert is insert(int[],int,int). For instance, calling insert with an array literal would be like so:
insert(new int[]{1,2,4,5}, 3, 2);
Additionally, System.arraycopy is a much faster and elegant way to copy arrays. You also seem to have forgotten to set the element at its index within your second example:
public static int[] insert(int[] array, int element, int index)
{
// Use arraycopy to shift all the elements by one, running over the last index
System.arraycopy(array, index, array, index+1, array.length-index-1);
// Set the appropriate index in the array to the specified value
array[index]=element;
return array;
}
If you then run the following, you will get your expected output:
int[] array = {1, 2, 4, 5};
insert(array,3,2); // array is now {1,2,3,4}
System.out.println(java.util.Arrays.toString(array));
If you are looking to print the array then the most laymen procedure is to return the particular array and loop throw it to print its element. eg:
public static void main(String[] args) {
int []solution= insert(new int[4],5,3);
for(int i=0;i<solution.length;i++)
{
System.out.println(solution[i]);
}
}

Categories