How to get rid of pointers? - java

To make my question understandable, I'm using the following example code. The output of this code is 5, while I wanted it to be 3. I'm guessing that B is working as a pointer for A, but I want A to be copied in B initially, and subsequent changes in A should not affect B.
import java.io.*;
public class fg
{
public static void main(String args[]) throws Exception
{
int[] A = new int[3];
A[0]=1;
A[1]=3;
A[3]=7;
check(A);
}
public static void check(int[] A)
{
int[] B = A;
A[1] = 5;
System.out.println(B[1]);
}
}

You need to explicitly create a copy,
int[] B = Arrays.copyOf(A, A.length);
since int[] is a reference type, so an assignment just copies the reference (basically, pointer).
If the array elements themselves are not primitive types, you probably will need a deep-copy, so
type B[] = new type[A.length];
for(int i = 0; i < A.length; ++i) {
B[i] = makeCopyOf(A[i]);
}
where makeCopyOf() should create a sensible copy of a type instance. If you don't find anything better, type makeCopyOf(type orig) { return orig.clone(); } could serve as a fallback.

B is a reference, and as such is analogous to a pointer (with various differences - you can't do arithmetic and it's not a direct memory pointer).
As such, you'll have to create a copy of the structure (the array) that you're referring to. Note that if you're copying objects, you may need a deep copy. You would likely have to do this in a copy constructor (see this article as to why clone() is considered broken)

Related

In Java, are fields of array type deep copied or shallow copied?

[Background note: I am a new Java programmer with a C++ background, so is a little confused about how arguments are passed around in Java.]
While reading and writing some code, I came to the following case
public class B{
int[] intArr;
Vector<String> strVec;
void mutator(){
// modifies intArr and strVec
}
}
public class A{
B bOfA;
A(B b){
bOfA = b;
}
void foo(){
bofA.mutator();
}
}
foo() in A definitely modifies bOfA, but what about b, the object that is passed in? Will its fields/data members be modified as well?
Are the fields shallow or deep copied?
Are strVec and intArr treated differently, because strVec is a container and inArr is an array, which might be implemented as some kind of pointers, therefore behave quite differently depending on if it is shallow or deep copied.
Thank you.
A (late) update with real code and somewhat surprising (I was assuming the pass-by-value mechanism interpreted in the C/C++ way) results:
import java.util.Vector;
public class B{
int[] intArr = null;
Vector<String> strVec = null;
int x = 0;
String s = null;
B(int sz){
x = 0;
s = new String("ini");
intArr = new int[sz];
strVec = new Vector<String>(sz);
for (int i=0; i<sz; i++){
intArr[i] = 0;
strVec.add( new String("xx") );
}
}
void mutator(){
x = -1;
s = new String("mute");
int sz = intArr.length;
strVec = new Vector<String>(sz);
for (int i=0; i<sz; i++){
intArr[i] = -1;
strVec.add( new String("aa") );
}
}
}
import java.util.Vector;
public class A{
B bOfA=null;
A(B b){
bOfA = b;
}
void foo(){
bOfA.mutator();
}
}
import java.util.Vector;
public class C{
public static void main(String[] args){
B b = new B(3);
A a = new A(b);
System.out.println("Contents of B before:");
System.out.println(b.x);
System.out.println(b.s);
for(int i=0; i<3; i++){
System.out.println(b.intArr[i]);
System.out.println(b.strVec.elementAt(i));
}
a.foo();
System.out.println("\n\nContents of A:");
System.out.println(a.bOfA.x);
System.out.println(a.bOfA.s);
for(int i=0; i<3; i++){
System.out.println(a.bOfA.intArr[i]);
System.out.println(a.bOfA.strVec.elementAt(i));
}
System.out.println("\n\nContents of B after:");
System.out.println(b.x);
System.out.println(b.s);
for(int i=0; i<3; i++){
System.out.println(b.intArr[i]);
System.out.println(b.strVec.elementAt(i));
}
}
}
And the results by cygwin:
Contents of B before:
0
ini
0
xx
0
xx
0
xx
Contents of A:
-1
mute
-1
aa
-1
aa
-1
aa
Contents of B after:
-1
mute
-1
aa
-1
aa
-1
aa
Java passes everything by value. But, the value of Object(s) are references.
Both the array and the Vector are shallow copies.
Arrays are reference objects. When you assign them, they are not copied at all - what happens there is similar to assigning an array to a pointer in C++.
When you copy an array using System.arraycopy, a shallow copy is performed. Constructing a collection from another collection creates a shallow copy as well.
Note: Unlike C++ libraries, Java class libraries uses immutable classes a lot. For example, String is immutable; so are the wrappers for numbers, such as Integer. Immutability makes the shallow vs. deep copying a lot less relevant.
Another note: Vector<T> should be used when you need a synchronized container; if you do not want synchronization, use ArrayList<T> instead.
what about b, the object that is passed in?
Will its fields/data members be modified as well?
Since java by default is pass-by-value, object that is passed in the contructor is pass-by-value but its internally its fields within that object will have reference, therefore when you call bofA.mutator() the B b field will change as well.
To have deep copy you need to copy each of the field in the b object that was passed and use Arrays.copyOf().

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.

Is Java pass by value Or pass by reference Or both? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 9 years ago.
Consider following case.
List<Integer> listOne = new ArrayList<>();
List<Integer> listTwo = new ArrayList<>();
listOne.add(1);I think this happens due to
listOne.add(2);
listOne.add(3);
Collections.reverse(listOne);
listTwo = listOne; //listTwo has same reference
Collections.reverse(listOne);
System.out.println(listOne); //out put [1, 2, 3]
System.out.println(listTwo); // same out put
Java is pass by value, where values (for non primitive types) happen to be references. I think this provide survival for java for this kind of scenario. To be honest why java try to avoid pass by reference and try to be different from some of other languages? while java still suffering from pass by reference behaviors?
Edit: additionally please some one explain what happen in above code
Java does not suffer from pass by reference behaviors, it enjois them :)
when you write
List listOne = new ArrayList<>();
you have three things to consider:
1) a variable, which is a chunk of memory, and is named listOne
2) an object on the heap, with is an instance of ArrayList, which is a larger chunk of memory, and has no name
3) value of the listOne variable, which is not a memory chunk, but is a set of 0s and 1s placed in the memory of the variable listOne, and that value also has no name.
Now when we talk if listOne is passed by value or by reference, we use imprecise jargon which leads to misunderstanding. listOne (thing 1) is not passed at all, neither by value nor by reference. The value of listOne (thing 3) is passed, and this gives access to the ArrayList object (thing 2). So if we use name "listOne" but mean thing 3, it is passed by value, and if we mean thing 2, it is passed by reference. In both cases, name "listOne" is not correct name for thing 2 or thing 3, but it is used because it is short and convenient.
Java is pass by value.A copy of actual argument is passed to parameters.It is evident in case of primitive data types where changes in formal parameters is not shown in actual arguments.
static void incre(int a)
{
a++;
}
public static void main (String a[])
{
int c=3;
incre(c);
System.out.println(c); //still prints 3
}
Exact thing happens in case of references, but making a copy of reference does not create a new object, they both point to same object now.Hence changes made by references is reflected here.
class Demo {
int c =2;
Demo(int c)
{
this.c=c;
}
void incObject (Demo x)
{
(x.c)++;
}
int show()
{
return c;
}
public static void main (String []args)
{
Demo o = new Demo(1);
o.incObject(o);
System.out.print(o.show()); //prints 2
}
}
Collections.reverse();
modifies the backing array. This is clear from the implementation:
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
Now, listOne and listTwo have the same reference which points to the same backing array. So, no matter which handle(listOne or listTwo) modifies the backing array, the other will reflect the same changes. In your case:
Collections.reverse(listOne); // backing array has [3,2,1]
listTwo = listOne; //listTwo has same reference
Collections.reverse(listOne); // backing array has [1,2,3]
System.out.println(listOne); //out put [1, 2, 3]
System.out.println(listTwo); // same out put
As far as pass by value/reference is concerned. You said it yourself:
Java is pass by value, where values happen to be references.
why java try to avoid pass by reference and try to be different from
some of other languages?
One of the main reasons would be that Java(JVM) manages its own memory.
Collections.reverse(listOne); passes the reference to listOne(the object) by value, which is how one defines "pass by reference". Everything other than primitives is passed this way: by reference. It does not try to avoid it, it is only different from C++ in that it doesn't explicitly use pointers.
EDIT: Okay, I think I see where you're coming from.
private static void changelist(List<Integer> list) {
list.add(4);//This modifies the list object
list = new ArrayList<Integer>();//This modifies the local copy of the reference to the list object
list.add(5);
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);//output is [1,2,3]
//This copies the value of the reference.
//If you modify the object in the underlying
//function, changes will be preserved when you return
//However if you modify what the reference points to,
//the function will only modify the local copy
changelist(list);
System.out.println(list);//output is [1,2,3,4]
}

Initialize object A in java equal to another object B [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I copy an object in Java?
How can I initialize an object (say A) in java and set its initial member values equal to a second object (say B). After initialization I want to modify the members of A without modifying the members of B. So at initialization of A I only want to copy the data of B. How is this done in a nice way??
You could implement and use clone
MyClass b = new MyClass();
MyClass a = b.clone();
Note: some classes are not Cloneable, or have broken implementations. e.g. only have a shallow copy when they should be a deep copy.
If the class is Serializable you can serialize it and deserialize it in memory. Not exactly nice but it works.
Or you could create your own "copy" constructor.
One possible solution for that would be implement clone method on your class and use clone as follows:
MyClass a = new MyClass();
MyClass b = a;
You will notice that clone() isn't really a public method, so your will need to expose it. Additionally you need to tell Java that your object is Cloneable (this is done making your class implement Cloneable). The following code ilustrate it:
public class MyClass implements Cloneable {
#Override
protected MyClass clone() throws CloneNotSupportedException {
return (MyClass)super.clone();
}
}
That all depends on the type of the members. I'll give an Example:
class A
{
public float value;
public int[] anArray;
public A(B b)
{
//primitive may be assigned directly.
this.value = b.value;
// other types different approaches:
//copy the contents of the array
this.anArray = new int[b.anArray.length];
System.arraycopy(b.anArray, 0, this.anArray, 0, b.anArray.length);
}
}
class B
{
float value;
int[] anArray;
public B(int size)
{
this.value = 3f;
this.anArray = new int[size];
for (int i = size - 1; i >= 0; i--)
{
this.anArray[i] = i * 10;
}
}
}
B b = new B(5);
A a = new A(b);
Cloning is a straightforward option for copying. If you ever want to do something where you need more control, create your own method that performs your copy exactly how you need it:
public MyType copy()
{
MyType a = new MyType();
// Initialize how you need to here, use the object this was called from if you'd like
a.property = this.property;
// etc.
return a;
}
This gives you more direct control, but takes more time to code. If clone will suit your purposes, stick to that.
EDIT: I am going to give an example based on your comments on this answer.
Let us assume we have the following types:
TypeA: has the following member variables
int number = 5; // Default value built in by constructor.
int letter = 'x'; // Value is 'a' when constructed but has been changed.
ArrayList<TypeB> list = {b1, b2, b3} // All are initialized.
TypeB: has the following member variables
double decimal = 5.32
TypeC someObject = ...
TypeC: has some stuff, but we are going to ignore it.
Now, When we want to copy TypeA, we must do the following:
Copy over the number and character directly as they are value types.
Copy over a reference to the ArrayList which contains a reference to some TypeBs.
Luckily those are easy steps.
int copyNumber = this.number;
char copyChar = this.letter;
ArrayList<TypeB> copyList = this.list;
return new TypeA(copyNumber, copyChar, copyList);
Now that assumes a particular constructor that takes those three arguments, but hopefully you get the idea.
It would get tricky if you wanted to just get values, not references to all of the TypeBs in the ArrayList. You would have to loop through the ArrayList and create new TypeBs that copied all of ITS values (double and TypeC objects as either references or values...)
In short, what you want is an easier copy to perform. Simple assignment operators copy values with primitive types and references with Objects.

Varargs, immutable array, and thread-safety

Hi all I have an immutable array implementation which looks like this:
public static final class FixedArray<T> {
private final T[] array;
public final int Length;
#SafeVarargs
public FixedArray(T... args) {
array = args;
Length = args.length;
}
public T Get(int index) {
return array[index];
}
}
public static final class FixedIntArray {
private final int[] array;
public final int Length;
public FixedIntArray(int... args) {
array = args;
Length = args.length;
}
public int Get(int index) {
return array[index];
}
}
public static final class FixedLongArray {
private final long[] array;
public final int Length;
public FixedLongArray(long... args) {
array = args;
Length = args.length;
}
public long Get(int index) {
return array[index];
}
}
Initially I'd thought that it is guaranteed to be thread-safe. But after reading the discussion regarding immutable arrays and the Java Memory Model, I believe alone, I can't be sure.
I've not used a defensive copy, with the contract that the calling code "does the right thing" (and as usual, if it doesn't follow the contract, the behavior is undefined).
The calling method looks like this:
public static void main(String args[]) {
int[] ints = new int[10000];
FixedIntArray fixed_ints = new FixedIntArray(ints);
SendToThreadA(fixed_ints);
SendToThreadB(fixed_ints);
SendToThreadC(fixed_ints);
SendToThreadD(fixed_ints);
//caller (which is this method) does the right thing, ints goes out of scope without anyone trying to modify it.
}
I was wondering is the code above guaranteed to be thread-safe?
As we don't know what happens to the array (and its values) to which you store a reference, I think your classes would be much safer if the constuctors create a copy of the argument array and set the internal final reference to the copied array.
It's OK. You can require caller to "hand-off" the array to you. Caller can clone one if necessary.
Memory write is usually the most expensive thing in a program (sans external IO).
Not everybody is stupid. You only need to be defensive enough to protect your target user base.
Given that you can pass an array to a varargs method, you'd need to make a copy of the constructor input to ensure it can't be modified outside the class. Having done that, as long as you don't assign the final field until after all the values are assigned in the copy array, you should be fine because the assignment to the final field is guaranteed to happen before any read of that field from another thread.
So a constructor would look like:
array = Arrays.copyOf(args, args.length);
Orrrr you could just use a Guava ImmutableList and get a lot more power.
I'm not sure it's meaningful to examine it for thread-safety, because it's missing even a more basic level of safety. Consider this method:
public static void main(final String... args)
{
final int[] arr = new int[] { 3, 3, 3 };
final FixedIntArray threeThrees = new FixedIntArray(arr);
System.out.println(threeThrees.Get(0)); // prints "3"
System.out.println(threeThrees.Get(1)); // prints "3"
System.out.println(threeThrees.Get(2)); // prints "3"
arr[0] = arr[1] = arr[2] = 4;
System.out.println(threeThrees.Get(0)); // prints "4"
System.out.println(threeThrees.Get(1)); // prints "4"
System.out.println(threeThrees.Get(2)); // prints "4"
}
The problem is that, when a method that takes int... (or Object... or long... or anything else), it can receive either an array that's implicitly constructed by the compiler (as would happen if you typed new FixedIntArray(3,3,3)), or an array that's explicitly passed in by the calling code (as I did above). In the latter case, the calling code can continue to modify the array that it passed in!

Categories