Reading and setting byte[] in function - java

I need to pass a byte[] in a Java method, and inside the method i need to "change" the byte[], but i don`t want to change the local byte[], i want to change the passed byte[] to the method, like a pointer, for example.
byte[] arr = new byte[10];
doSomethingWithByteArr(arr);
// And now, arr would have changed...

Java is pass-by-reference-value when passing non-primitive arguments to methods, and is pass-by-value when passing primitives, meaning that if you have a byte array and you pass it to a modification method, that object will be modified.
Example:
public static void main(String[] args) {
byte[] arr = new byte[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
// arr now contains { 0, 1, 2, 3, ... 9 }
System.out.println(Arrays.toString(arr));
randomize(arr);
// arr now contains (ex.) { 6, 3, 7, 1, 9, 3, 2, 6, 3, 0 }
System.out.println(Arrays.toString(arr));
}
public void randomize(byte[] arr) {
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(10);
}
}

Not sure if i understand your dilemma.
Java passes its parameters by value every time. This meaning if its a primitive it passes the value of it, and if its an object or array, it passes the value of the object referenced by it.
So if you pass an array you can modify it and since its an alias it will be reflected on the array outside of the method. But you wont be able to point the arr variable to a new reference from within the method code, you could return a new byte[] and assigning to it if you want to change it.
To my knowledge, Java doesn't support passing parameters by reference.

In Java only primitive types are copied when passed to a function. That pseudocode should work as you expect.
Although in Java everything is passed by copy, non primitive types are actually references, that's why your byte[] refers to the same instance inside and outside the function.

Related

Beginner Java methods [duplicate]

This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 5 years ago.
public class Test {
int[] a1 = {1, 3, 5, 7, 2};
int[] a2 = new int[a1.length + 10];
public static int[] Array(){
for(int i = 0; i < a1.length; i++){
a2[i] = a1[i];
}
a1 = a2;
}
public static void main(String args[]){
System.out.println(a1.toString);
}
}
I am trying to create a method "Array" that will take in arrays a1 and a2 and add + 10 to the length of a1. My problem is that I don't know how to correctly name the method and how to call it in the main in order to print.
I have tried passing a1 and a2 in the constructor for Array but it doesn't work. I have also tried printing directly in the main() and it doesn't work either. What am I missing?
No idea what are you trying to do but in Java you can't change the size of array once it is declared but if you want to work with array with can change size then you should use arraylist not array and one more thing setting b = awould not work btw here is a code which swaps elements from one array to other but once again you can't change size of array in java: I return b back but you don't need to return an array back because an array variable(name of array) refers to a memory location.
public static int[] extendLength(int [] a, int [] b){
for(int i = 0; i < a.length; i++){
b[i] = a[i];
}
return b;
}
public static void main(String args[]){
int[] a1 = {1, 3, 5, 7, 2};
int[] a2 = new int[a1.length + 10];
int [] res = extendLength(a1,a2);
for(int i = 0; i < a2.length;i++)
System.out.println(a2[i]);
}
Long story short, the way you have your program set up, your variables will also need to be static; otherwise, your static methods will not be able to access them.
Static fields and methods are essentially singular to the class; therefore without a director to which object contains the field, asking a static method to manipulate a non-static field is very ambiguous.
I'm seeing a number of other problems in this program as well; namely, you're treating toString as a field (it's a method), your array method is missing a return statement, and your alignment is all over the place. This probably isn't an appropriate question to bring to Stack Overflow; I would encourage you to look at a tutorial, like the one at Tutorials Point, before bringing your question here.

Why is this void method not working as I would expect? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
Assuming that the Given array is instantiated as follows:
int[] given = {1, 2, 3, 4, 5};
These methods should change the array and show the print results.
public int[] change(int[] given) {
out.println(Arrays.toString(given)); //before-changes
whatIsGoingOn(given); //make changes
out.println(Arrays.toString(given));//after changes
return given; //return the supposedly changed array
}
//Make changes:
public void whatIsGoingOn(int[] given) {
given = new int[5];
given[0] = 200;
}
I BELIVE THE PROBLEM to be with the void method, overriding the original values of the int[] given but the new initialization and declarations never make it out.
I Would expect the array to be:
{200, 0, 0, 0, 0};
But Java prints out:
{1, 2, 3, 4, 5}
{1, 2, 3, 4, 5}
But in the case where I returned a newly changed array in the whatIsGoingOnMethod, I get my wanted results:
{1, 2, 3, 4, 5}
{200, 0, 0, 0, 0}
If the void method just does something and its not really being "applied" as I would like to expect. I'd appreciate an illuminating explanation for this.
This Question is ALREADY ANSWERED THANKS!!!
I need to freeze it.
With given = new int[5]; you are changing what the local variable given points to, not the object that it used to point to. The local is later out of scope. The array is never modified.
Youre creating a whole new array, and assigning the variable that used to refer to the original to the new array. Youre modifying the new array, and never touching the old one.
The appropriate fix would be similar to what follows:
public static void main(String[] args)
{
int[] original = new int[5];//already allocating memory, initializing to default value, etc.
setFirstTo20(original);
System.out.println(original[0]);//still 20!
}
public static void setFirstTo20(int[] given)
{
for (int i : given)
System.out.println(i);//for debugging, before change
given[0] = 20;
for (int i : given)
System.out.println(i);//after change
//heres whats happening to you
given = new int[5];
given[0] = 40;
for (int i : given)
System.out.println(i);//show new changes to NEW array
}
Obviously you should get rid of the extraneous code if you intend for this or similar methods to be used in actual classes.
Because the argument given of function whatIsGoingOn is passed by value.
To change it in a void function, you have to wrap it in an object like this:
class ArrayRef {
public int[] array;
}
public int[] change(int[] given) {
out.println(Arrays.toString(given)); //before-changes
ArrayRef ref = new ArrayRef();
ref.array = given; //set a reference to the given array
whatIsGoingOn(ref); //make changes
given = ref.array; //get the changed array
out.println(Arrays.toString(given));//after changes
return given; //return the supposedly changed array
}
//Make changes:
public void whatIsGoingOn(ArrayRef ref) {
ref.array = new int[5];
ref.array[0] = 200;
}
Arrays such as int[] are reference types. This means that when you do the assignment given = new int[5], you are chainging the array referenced within whatIsGoingOn() and not affecting the array referenced within change().
To do what you want it to, you need to loop though the array and change the individual elements within the array.
for(int i = 0; i < given.length; i++) {
given[i] = 0;
}
given[0] = 200;
change following lines of whatIsGoingOn method from
given = new int[5];
given[0] = 200;
to
Arrays.fill(given,0);
given[0] = 200;
It still holds reference to original array .No need to return anything.
Void quite simply will return nothing. Replace void with int[] to achieve your expected results. Also replace
public void whatIsGoingOn(int[] given) {
given = new int[5];
given[0] = 200;
}
with
public int[] whatIsGoingOn(int[] given) {
given = new int[5];
given[0] = 200;
return given;
}
the final result should be
public int[] change(int[] given) {
out.println(Arrays.toString(given)); //before-changes
given = whatIsGoingOn(given); //make changes
out.println(Arrays.toString(given));//after changes
return given; //return the supposedly changed array
}
//Make changes:
public int[] whatIsGoingOn(int[] given) {
given = new int[5];
given[0] = 200;
return given;
}

What does it mean to return a reference to an array?

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.

Varargs method modifies caller's array instead of its own copy?

I have this simple varargs method which divides each item in the list:
import java.util.*;
class A {
static long f(long... xs) {
Arrays.sort(xs);
long y = 100000000;
for (int i = xs.length - 1; i >= 0; i--)
y /= xs[i];
return y;
}
static {
System.out.println(f(5,2,6,3,9,3,13,4,5));
long[] xs = new long[]{5,2,6,3,9,3,13,4,5};
System.out.println(Arrays.toString(xs));
System.out.println(f(xs));
System.out.println(Arrays.toString(xs));
}
}
I'd expect it to pass a copy of the array, but apparently it's somehow modifying the array I pass in, instead of its own local copy:
$ javac A.java && java A
79
[5, 2, 6, 3, 9, 3, 13, 4, 5]
79
[2, 3, 3, 4, 5, 5, 6, 9, 13]
So I wrote this simple test program:
class B {
static void f(Object... os) {
System.out.println(os);
}
static {
Object os = new Object[]{1,2,3};
System.out.println(os);
f(os);
}
}
And it does what I expect, it clones the object array before passing it into f (hence different object identifiers):
$ javac B.java && java B
[Ljava.lang.Object;#1242719c
[Ljava.lang.Object;#4830c221
So how then is f in A modifying the caller's array instead of its own copy?
It looks like you've tricked yourself here:
Object os = new Object[]{1,2,3};
System.out.println(os);
f(os);
Since os is typed as Object, it gets interpreted as the first element of the varargs array. What gets passed into the method is actually a new Object[] whose single element is your Object[].
If you do the following, it will print the same instance:
Object[] os = new Object[]{1,2,3};
System.out.println(os);
f(os);
The f method will need make a defensive copy of the array itself in order to guarantee that an array passed in by the caller isn't modified. As arshajii points out, varargs are foremost array parameters, with the "bonus" behavior of creating a new array when given an argument list.
Anyway you can use Arrays.copyOf to make the copy, which delegates to (the less type-safe) System.arraycopy.
varargs is an array type, but with syntactic sugar to allow an on-the-fly array creation if elements are passed separately as parameters.
That is, these two signatures are identical:
static long f(long... xs) {
static long f(long[] xs) {
Except that the varargs may be called with separate elements instead of an array
Of course the array will get modified if you bypass the on-the-fly creation and create an array yourself to pass in.
So how then is f in A modifying the caller's array instead of its own copy?
It doesn't have its own copy. It has a reference to the caller's array.
In the end, an array is an object, so you don't modify the array reference itself instead its contents which is allowed.

Generic Method is not working

I'm trying to use this method but I get an error in Eclipse saying the type argument is incorrect and it tells me to change the method signature. Any reason why?
/**Creates an independent copy(clone) of the T array.
* #param array The 2D array to be cloned.
* #return An independent 'deep' structure clone of the array.
*/
public static <T> T[][] clone2DArray(T[][] array) {
int rows=array.length ;
//clone the 'shallow' structure of array
T[][] newArray = array.clone();
//clone the 'deep' structure of array
for(int row=0;row<rows;row++){
newArray[row]=array[row].clone();
}
return newArray;
}
The copy2DArray method you posted appears to work as advertised. Perhaps you are calling the method incorrectly? Also make sure you are not using primitive types instead of objects in the array you are copying. In other words, use Integer instead of int.
Here is an example of the working method:
public class Main {
// ...
// Your copy2DArray method goes here
// ...
public static void main(String[] args) {
// The array to copy
Integer array[][] = {
{0, 1, 2},
{3, 4, 5},
{6, 7, 8}
};
// Create a copy of the array
Integer copy[][] = clone2DArray(array);
// Print the copy of the array
for (int i = 0; i < copy.length; i++) {
for (int j = 0; j < copy[i].length; j++) {
System.out.print(copy[i][j] + " ");
}
System.out.println();
}
}
}
This code will print:
0 1 2
3 4 5
6 7 8
It works with all classes. It doesn't work with primitives (int, long, etc.)
So instead of using primitive arrays use the wrapper classes: use Integer[][] instead of int[][].
You can use commons-lang ArrayUtils.toPrimitive(..) and ArrayUtils.toObject(..) to convert arrays between primitives and their wrappers.
You may be using primitive types, when there's no erasure for primitive types. i.e., int.class is completely impossible, but Integer.class works. Wherever generics are involved, primitive types are a no-go.

Categories