How do I prevent the modification of a private fie

2019-01-29 18:10发布

Imagine that I have this class:

public class Test
{
  private String[] arr = new String[]{"1","2"};    

  public String[] getArr() 
  {
    return arr;
  }
}

Now, I have another class that uses the above class:

Test test = new Test();
test.getArr()[0] ="some value!"; //!!!

So this is the problem: I have accessed a private field of a class from outside! How can I prevent this? I mean how can I make this array immutable? Does this mean that with every getter method you can work your way up to access the private field? (I don't want any libraries such as Guava. I just need to know the right way to do this).

10条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-01-29 18:32

You must return a copy of your array.

public String[] getArr() {
  return arr == null ? null : Arrays.copyOf(arr, arr.length);
}
查看更多
甜甜的少女心
3楼-- · 2019-01-29 18:32

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];
}
查看更多
乱世女痞
4楼-- · 2019-01-29 18:35

You can also use ImmutableList which should be better than the standard unmodifiableList. The class is part of Guava libraries that was create by Google.

Here is the description:

Unlike Collections.unmodifiableList(java.util.List), which is a view of a separate collection that can still change, an instance of ImmutableList contains its own private data and will never change

Here is a simple example of how to use it:

public class Test
{
  private String[] arr = new String[]{"1","2"};    

  public ImmutableList<String> getArr() 
  {
    return ImmutableList.copyOf(arr);
  }
}
查看更多
时光不老,我们不散
5楼-- · 2019-01-29 18:35

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;
    }
}
查看更多
萌系小妹纸
6楼-- · 2019-01-29 18:37

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.

查看更多
做个烂人
7楼-- · 2019-01-29 18:40

at this point of view you should use system array copy:

public String[] getArr() {
   if (arr != null) {
      String[] arrcpy = new String[arr.length];
      System.arraycopy(arr, 0, arrcpy, 0, arr.length);
      return arrcpy;
   } else
      return null;
   }
}
查看更多
登录 后发表回答