不要使用 public
属性
当您确实需要包装类的内部行为时,请勿使用 public
属性。以 java.io.BufferedReader
为例,它具有以下字段:
private boolean skipLF = false
skipLF
在所有读取方法中都会被读取和写入。如果一个在另一个线程中运行的外部类在读取过程中恶意修改了 skipLF
的状态,BufferedReader
将肯定出现故障。
使用 public
字段
以这个 Point
类为例:
class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return this.x;
}
public double getY() {
return this.y;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
}
这将使得计算两点之间的距离非常繁琐。
Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.getX() - a.getX(), 2) + Math.pow(b.getY() - a.getY(), 2));
这个类除了简单的getter和setter之外没有任何行为。当类仅表示数据结构,并且没有以及永远不会有任何行为时,使用公共字段是可以接受的(这里认为仅存在thin getters和setters不是行为)。可以用以下方式更好地编写:
class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
Point a = new Point(5.0, 4.0);
Point b = new Point(4.0, 9.0);
double distance = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
清理!
但请记住:不仅您的类必须没有行为,而且它将来也不应该有任何行为。
这正是此答案所描述的。引用《Java编程语言代码规范:10. 编程实践》的话:
公共实例变量的一个适当用法示例是,如果类本质上是一个数据结构,没有行为。换句话说,如果Java支持struct
,则使用struct
而不是类是适当的,并且可以将类的实例变量设置为public。
因此,官方文档也接受这种做法。
此外,如果您非常确定上述Point
类的成员应该是不可变的,那么您可以添加final
关键字来强制执行:
public final double x;
public final double y;