public
フィールドを使用しない
public
クラスの内部動作を本当にラップしたい場合は、フィールドを使用しないでください。例を挙げてみましょうjava.io.BufferedReader
。次のフィールドがあります。
private boolean skipLF = false; // If the next character is a line feed, skip it
skipLF
すべての read メソッドで読み書きされます。別のスレッドで実行されている外部クラス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;
}
}
これにより、2 点間の距離の計算を書くのが非常に困難になります。
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));
このクラスには、プレーンなゲッターとセッター以外の動作はありません。クラスが単なるデータ構造を表し、動作を持たず、今後も持たない場合は、パブリック フィールドを使用することは許容されます(ここでは、シン ゲッターとセッターは動作とは見なされません)。これは次のように書くとより良くなります:
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.プログラミングの実践」を引用するには:
適切なパブリック インスタンス変数の 1 つの例は、クラスが本質的に動作のないデータ構造である場合です。つまり、struct
クラスの代わりに を使用する場合 (Java が をサポートしている場合struct
) は、クラスのインスタンス変数を public にするのが適切です。
したがって、公式ドキュメントもこの慣行を受け入れています。)
Point
また、上記のクラスのメンバーが不変であることを確信している場合は、それfinal
を強制するキーワードを追加できます。
public final double x;
public final double y;