Imagine that I have this class:
public class Test
{
private String[] arr = new String[]{\"1\",\"2\"};
public String[] getArr()
{
return arr;
The Collections.unmodifiableList
has already been mentioned - the Arrays.asList()
strangely not! My solution would also be to use the list from the outside and wrap the array as follows:
String[] arr = new String[]{"1", "2"};
public List<String> getList() {
return Collections.unmodifiableList(Arrays.asList(arr));
}
The problem with copying the array is: if you're doing it every time you access the code and the array is big, you'll create a lot of work for the garbage collector for sure. So the copy is a simple but really bad approach - I'd say "cheap", but memory-expensive! Especially when you're having more than just 2 elements.
If you look at the source code of Arrays.asList
and Collections.unmodifiableList
there is actually not much created. The first just wraps the array without copying it, the second just wraps the list, making changes to it unavailable.
You could return a copy of the data. The caller who chooses to change the data will only be changing the copy
public class Test {
private static String[] arr = new String[] { "1", "2" };
public String[] getArr() {
String[] b = new String[arr.length];
System.arraycopy(arr, 0, b, 0, arr.length);
return b;
}
}
Yes, you should return a a copy of the array:
public String[] getArr()
{
return Arrays.copyOf(arr);
}
The nub of the problem is that you are returning a pointer to a mutable object. Oops. Either you render the object immutable (the unmodifiable list solution) or you return a copy of the object.
As a general matter, finality of objects does not protect objects from being changed if they are mutable. These two problems are "kissing cousins."
Modifier private
protects only field itself from being accessed from other classes, but not the object references by this field. If you need to protect referenced object, just do not give it out. Change
public String [] getArr ()
{
return arr;
}
to:
public String [] getArr ()
{
return arr.clone ();
}
or to
public int getArrLength ()
{
return arr.length;
}
public String getArrElementAt (int index)
{
return arr [index];
}
If you can use a List instead of an array, Collections provides an unmodifiable list:
public List<String> getList() {
return Collections.unmodifiableList(list);
}