我想强制将来的类用户也只能通过访问器方法(甚至通过junit或类似的方法)从该类中编写的代码中访问私有成员。
在java中有办法做到吗?有谁能举个例子吗?
您不能强制这样做,但是您可以创建一个方法并在javadoc中记录执行。
private int myMember;
/**
* ATTENTION: use this method instead of setting the member directly.
*/
public void setMyMember(int value) {
this.myMember = value;
}
另外,还有一个可能有效的替代解决方案。使用ThreadLocal,像这样:
private final ThreadLocal<String> member = new ThreadLocal<String>();
public void setMember(final String value) {
member.set(value);
}
成员字段是final,不能修改。因此,客户端将被迫直接调用setter。
只要字段是类的一部分,任何人都可以直接访问它。这可能是一个问题,当我们试图强迫所有(共同)作者通过getter/setter,因为这些方法做一些转换,检查或簿记的东西。像递增的内部计数器。
我想到了一个通用的解决方案:可以通过使用注释来实现。您必须创建一个注释(和注释处理器代码)来确保,如果字段在getter/setter方法之外使用,则会出现编译时错误:
@GetterSetterAccessOnly
private int value;
如果你想防止反射,你可以使用SecurityManager。如果这不是一个选项,你可以使用Thread.currentThread(). getstacktrace()获取调用堆栈,并检查调用者是否来自你的类。
有两个问题是;演出不会很好。您可以在方法中执行的任何操作都可以在外部执行,因此最简单的工作就是复制其内容而不进行检查。;)
使用继承来隐藏字段:
- 用你需要的所有字段和getter/setter来创建你的类。(你可以使它抽象)
- 做一个子类,继承预览类,因为字段是不可访问的,你强制使用getter/setter对。
当你在谈论同一个类中的访问时,它们有直接访问私有成员的所有自由,如果该成员有,也可以通过访问器方法访问。所以基本上你不能阻止他们在同一个类中直接使用成员
恐怕没有这样做的标准方法。如果用户可以访问类实例,尽管private成员被声明为private,但可以在运行时更改权限并以任何方式访问。
你需要一个类加载器来执行权限。您可以创建OSGi Bundle,并对通过接口导出为服务的对象实例实施控制策略。但是,这将把您绑定到OSGi容器来运行应用程序。
如果他们可以访问你的代码,他们可以做任何他们想做的事情。在最坏的情况下,他们会删除你的getter和setter,而只放在一个公共字段;)
但是当然你可以用一个合适的设计来激励他们不直接访问变量:
- 您应该检查其他人是否应该实现子类而不是更改类本身。当然,私有字段只能通过setter和getter来访问。
- 您可以将数据移动到另一个类中,并使用getter和setter来访问另一个类中的数据。这样做只是为了不直接在类中拥有数据,这可能有点违反直觉,但由于您可能有很好的理由说明为什么它们不应该访问这些数据,因此它表明了不同的责任。所以重构以满足SRP是一个好主意。