又是很简单的一节

public类不应该有public属性,必须使用访问方法(accessor methods)

有些情况下,会需要写一些纯粹用作数据存储,而没有任何行为的类,比如:

// Degenerate classes like this should not be public!
class Point {
	public double x;
	public double y;
}

上一节所说,这样做会破坏数据封装,所以Object-Oriented语言的死忠分子们会拒绝接受这样的写法,并要求全面使用访问方法改写它:

// Encapsulation of data by accessor methods and mutators
class Point {
	private double x;
	private double y;

	public Point(double x, double y) {
		this.x = x;
		this.y = y;
	}

	public double getX() { return x; }
	public double getY() { return y; }

	public void setX(double x) { this.x = x; }
	public void setY(double y) { this.y = y; }
}

这样的改写对于public类是必要的:如果一个类在它所在的包以外是可见的,那么它必须提供访问方法,而不能开放数据属性为public但如果类是仅包内可见(package-private),那么这样的数据开放却并没有太严重的后果。对于私有内嵌类,危害会更小。事实上,对于非public类,开放数据属性的确会使数据存取依赖于类的内部实现,但同时使代码更清楚易读。

虽然public类开放数据属性危害明显,但如果被开放的属性是immutable,那么其危害就大大减小。比如下面的代码,不会面临特别严重的问题:

// Public class with exposed immutable fields - questionable
public final class Time {
	private static final int HOURS_PER_DAY = 24;
	private static final int MINUTES_PER_HOUR = 60;
	
	public final int hour;
	public final int minute;
	
	public Time(int hour, int minute) {
		if (hour < 0 || hour >= HOURS_PER_DAY)
			throw new IllegalArgumentException("Hour: " + hour);
		if (minute < 0 || minute >= MINUTES_PER_HOUR)
			throw new IllegalArgumentException("Min: " + minute);
		this.hour = hour;
		this.minute = minute;
	}
	... // Remainder omitted
}