有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何防止修改类中的私有字段?

假设我有一门课:

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

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

现在,我有另一个类使用上述类:

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

这就是问题所在:我从外部访问了一个类的私有字段! 我怎样才能防止这种情况?我的意思是如何使这个数组不可变?这是否意味着使用每一种getter方法都可以访问私有字段?(我不想要任何像番石榴这样的图书馆,我只需要知道正确的方法)


共 (6) 个答案

  1. # 1 楼答案

    您还可以使用^{},它应该比标准unmodifiableList更好。该类是由Google创建的Guava库的一部分

    以下是描述:

    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

    下面是如何使用它的一个简单示例:

    public class Test
    {
      private String[] arr = new String[]{"1","2"};    
    
      public ImmutableList<String> getArr() 
      {
        return ImmutableList.copyOf(arr);
      }
    }
    
  2. # 2 楼答案

    已经提到了Collections.unmodifiableList,奇怪的是Arrays.asList()没有!我的解决方案也是从外部使用列表,并按如下方式包装数组:

    String[] arr = new String[]{"1", "2"}; 
    public List<String> getList() {
        return Collections.unmodifiableList(Arrays.asList(arr));
    }
    

    复制数组的问题是:如果每次访问代码时都要复制,而且数组很大,那么肯定会为垃圾收集器创建大量工作。因此,复制是一种简单但非常糟糕的方法——我会说“便宜”,但内存昂贵!尤其是当你有两个以上的元素时

    如果您查看Arrays.asListCollections.unmodifiableList的源代码,实际上创建的代码并不多。第一个只包装数组而不复制它,第二个只包装列表,使对它的更改不可用

  3. # 4 楼答案

    修饰符private只保护字段本身不被其他类访问,而不保护该字段的对象引用。如果您需要保护引用的对象,请不要给出它。改变

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

    致:

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

    public int getArrLength ()
    {
        return arr.length;
    }
    
    public String getArrElementAt (int index)
    {
        return arr [index];
    }
    
  4. # 5 楼答案

    您必须返回数组的副本

    public String[] getArr() {
      return arr == null ? null : Arrays.copyOf(arr, arr.length);
    }
    
  5. # 6 楼答案

    从这个角度来看,您应该使用系统阵列副本:

    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;
       }
    }