2

If I do something like

private int[] myPrivateArray;

and have a getter that returns the array, then the array contents can be modified from outside the class, which sort of defeats the purpose of making it private.

Dylanthepiguy
  • 1,621
  • 18
  • 47
  • 1
    if you don't want to change the content from outside return copy of your private array object. use deep cloning or shallow cloning accordingly. – Vishrant Mar 26 '16 at 04:42
  • 3
    "If I ... have a getter that returns the array" - *why do you have that*? You do not need a getter for everything. – user2357112 Mar 26 '16 at 04:47
  • 1
    Defensive copies? Same way any mutable state-if you don't want to expose it you need to return copies or immutable objects. – Dave Newton Mar 26 '16 at 04:54

3 Answers3

6

Yes, there is.

Firstly, don't provide a getter for that array if you don't have to. If you MUST provide a getter, then pass a copy, not the private variable.

Secondly (which has been overlooked so far), make sure the JVM SecurityManager is set up to stop reflection.

Community
  • 1
  • 1
Matt Messersmith
  • 12,939
  • 6
  • 51
  • 52
5

You can provide setters, getters for the specific index elements of the array, much like what List implementations do. As for returning it from a function, you can copy the array, and pass the copy instead. Rather than passing reference to your array, you pass reference to a copy of your array.

Evdzhan Mustafa
  • 3,645
  • 1
  • 24
  • 40
2

As others have said, you can return a copy of the array:

public int[]getMyArray(){
    return myPrivateArray.clone();
}

Alternatively, you can provide a getter to access individual elements of the array:

public int getMyArray(int index){
    return myPrivateArray.get(index);
}

Finally, if you'd like to avoid copying but insist on returning all the elements at once, you can return an unmodifiable list view of your array:

public class MyClass{
    private Object[]myPrivateArray;

    private List<Object>myArrayView=Collections.unmodifiableList(Arrays.asList(myPrivateArray));

    public List<Object>getMyArrayView(){
        return myArrayView;
    }
}

Although this is slightly more complicated with an array of primitives:

public class MyClass{
    private int[]myPrivateArray;

    private List<Integer>myArrayView=new AbstractList<Integer>(){
        @Override public int size(){
            return myPrivateArray.length;
        }
        @Override public Integer get(int index){
            return myPrivateArray[index]
        }
    }
    public List<Integer>getMyArrayView(){
        return myArrayView;
    }
}
Ryan Hilbert
  • 1,805
  • 1
  • 18
  • 31