Shaheen Ahamed S
Shaheen Ahamed S

Reputation: 176

Passing only value for private members

I am creating a class with one array as its private member and getter,setter method for that. I want set a value to that array using an array in main function. When I manipulate the array in main function, it should not affect the array present in that class.

I tried this code, but here the array is manipulated

class ClassB {

    private int[] a;

    ClassB() { }

    ClassB(int[] a) {
        this.a=a;
    }

    int[] geta() {
        return this.a;
    }

    void seta(int a[]) {
        this.a = a;
    }
}

public class ClassA{

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        System.out.println("Enter size : ");
        int n = sc.nextInt();
        int[] d = new int[n];
        System.out.println("Enter array elements : ");
        for (int i=0 ; i<n ; i++) {
            d[i] = sc.nextInt();
        }
        final ClassB cb2 = new ClassB(d);
        d[3] = 15;
        System.out.println("After changing array d : \n Values of array d :");
        for (int i=0 ; i<n ; i++) {
            System.out.println(d[i]);
        }
        System.out.println("Values of array a of cb2 :");
        int[] b = cb2.geta();
        for (int i=0 ; i<n ; i++) {
            System.out.println(b[i]);
        }
    }
}

I expect :

Enter size :

5

Enter array elements :
1
2
3
4
5
After changing array d :

 Values of array d :

1
2
3
15
5

Values of array a of cb2 :
1
2
3
4
5

But the actual output was :

Enter size :

5

Enter array elements :

1
2
3
4
5

After changing array d :

 Values of array d :

1
2
3
15
5

Values of array a of cb2 :

1
2
3
15
5

Upvotes: 3

Views: 99

Answers (2)

lealceldeiro
lealceldeiro

Reputation: 14968

You can make defensive copies in ClassB every time you set the array or need to return its values. Like this:

class ClassB {
    // ... code omitted for brevity

    ClassB(int[] a) {
        seta(a);
    }

    int[] geta() {
        int[] copy = new int[a.length];
        System.arraycopy(a, 0, copy, 0, a.length);
        return copy;
    }

    void seta(int a[]) {
        this.a = new int[a.length];
        System.arraycopy(a, 0, this.a, 0, a.length);
    }
}

Side notes:

  • If you really want to make ClassB immutable, you shouldn't have a setter for its values.
  • The utility System.arraycopy was used to create a copy of the arrays. Feel free to use here whatever fits better your needs (you may want to consider using a.clone()... this is a good topic about it: Why clone() is the best way for copying arrays?).

Additional readings:

Upvotes: 4

Pankaj Singhal
Pankaj Singhal

Reputation: 16053

When you are doing final ClassB cb2 = new ClassB(d);, you are essentially passing the reference of the array b to ClassB. Since both the references are same, the array inside ClassB is changing.

Must read - Is Java “pass-by-reference” or “pass-by-value”?

You will have to make a copy of the array, if you want the changes done to d not affect the array inside ClassB. Change your constructor to the following:

ClassB(int[] a) {
    this.a = a.clone();
}

Note:

Also, making ClassB object final (final ClassB cb2) makes its object cb2 as immutable. Not the objects inside it.

Hence, you cannot change cb2 but can definitely change cb2.a, when you do the following :

final ClassB cb2 = new ClassB(d);

Upvotes: 1

Related Questions