Java中的Getters - 我正在安全吗?

时间:2011-10-19 18:24:37

标签: java

我有一个私有内部类,它封装了一些功能。它填充了两个ArrayLists。我有ArrayLists的getter只返回私有变量。需要吸气剂吗?我可以只生成ArrayLists公共实例变量吗?什么是最佳做法?

public class OuterClass {
    //Stuff the OuterClass does

    private class InnerClass {
        private ArrayList<String> array1;
        private ArrayList<String> array2;

        public InnerClass() {
            //Init and do stuff w/ arrays
        }

        public ArrayList<String> getArray1() {
            return array1;
        }

        public ArrayList<String> getArray2() {
            return array2;
        }
    }
}

7 个答案:

答案 0 :(得分:2)

是的,可以使Arraylist 公开,尽管最佳做法是使用getter。这允许您构建副作用,如

  • 执行计算
  • 检查约束
  • 延迟初始化
  • 提供可能的继承方法

它还允许您在将来修改班级内部而不违反合同。

答案 1 :(得分:2)

最佳做法是提供吸气剂。这样可以避免某些人设置列表本身,将用户与基础代码更改隔离开来等等。

它们是否应该是一个不可修改的列表是一个单独的问题,只是取决于。

答案 2 :(得分:1)

您不会公开变量的原因是您要隐藏实现。如果从路径上的ArrayList切换到实际阵列会发生什么?你的所有代码都会中断。所以你写接口。

您可能还希望避免返回对数组的引用,而是提供以对类有意义的方式修改数组的方法。否则,使用您班级的人可能会进行您班级不期望的修改。

例如:

Foo foo = new Foo();
List list = foo.getArray();
list.add( new Object() );

此时,对象已被添加到您的Foo对象的内容中,并且您的foo对象没有任何机会检查该添加的有效性,拒绝添加,或以其他方式知道它在那里。如果您因性能原因决定延迟创建数组,那么您一直在访问null。吊杆。

答案 3 :(得分:0)

最佳做法是既不提供getter也不提供setter,而是您的对象不应公开其实现细节。

标准Java实践是拥有私有数据成员(a.k.a. fields)并提供getter和setter。

答案 4 :(得分:0)

这是一种方法,可以防止客户端通过getter提供的ArrayLists。请注意,尝试通过getter getResultsArray()返回的引用修改ArrayList应该引发异常:

package testCode;

import java.util.ArrayList;
import java.util.List;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

public class TestClass {

    private ArrayList<String> resultsArray = Lists.newArrayList();

    public void calculateResults(){
        resultsArray.add("1");
        resultsArray.add("2");
        resultsArray.add("3");
    }

    public List<String> getResultsArray() {
        return new ImmutableList.Builder<String>().addAll(resultsArray).build();
    }

}

还有一个测试驱动程序:

package testCode;

public class TestMain {

    public static void main(String[] args) {
        TestClass testClass = new TestClass();

        testClass.calculateResults();

        for (String result : testClass.getResultsArray()) {
            System.out.println(result);
        }

        try {
            testClass.getResultsArray().add("fake result");
        } catch (Exception e) {
            System.out.println(e);
        }

    }
}

输出:

1
2
3
java.lang.UnsupportedOperationException

ImmutableList来自Google的Guava库。在这种情况下,ImmutableList实现List接口,但任何会立即更改列表的方法都会抛出UnsupportedOperationException。请注意,因为ImmutableList永远不会改变,所以实现的代码非常小,因为调整列表的普通List实现中的任何内容都不会在此处写入。非常有用,在这种情况下,我使用它来实现防御性编程,以防止我的TestClass用户调整我返回给他们的测试结果。

答案 5 :(得分:0)

假设外部类(定义内部类的内部)不是很大(如K行代码),那么定义getter是没有意义的。

理由:

内部类是私有的。 Getters将允许您对内部类进行(非常有限的)更改,而不会影响外部类。如果外部类足够小,那么受到getter可以防止泄漏的更改影响的代码范围也非常小。因此,先验地引入它们是没有意义的。如果需要 - 介绍它们,但在那之前 - 只需坚持使用更简单的代码。

当然,如果您重构代码并将内部类更改为(独立的)顶级类,那么您需要引入getter(或者 - 甚至更好 - 将设计更改为tell-not-问方案)

答案 6 :(得分:0)

最好通过Getters / Setters公开您的API以进行封装,通过接口类型声明对象也是一种很好的做法。

private List<E> list; // = new ArrayList<E>(); or initialize elsewhere

public List<E> getList() {
    return list;
}

public void setList(List<E> list) {
    this.list = list;
}