public / private / protected / static / final
| 対応: | Java 1.0(1996) |
|---|
クラス・フィールド・メソッドへのアクセス範囲を制御する修飾子です。『public』『private』『protected』でアクセス可能な範囲を指定し、『static』でインスタンスに依存しないメンバーを定義し、『final』で変更不可の定数を宣言します。
構文
// アクセス修飾子付きのフィールド定義
public String name;
private int age;
protected double score;
// staticフィールド(クラス変数)の定義
static int count = 0;
// 定数の定義(staticとfinalを組み合わせる)
static final double PI = 3.14159;
// staticメソッドの定義
static void printCount() {
System.out.println(count);
}
// privateフィールドへのアクセサメソッド(getter / setter)
public int getAge() { return age; }
public void setAge(int age) {
if (age >= 0) this.age = age;
}
修飾子一覧
| 修飾子 | 概要 |
|---|---|
| public | すべてのクラスからアクセスできます。 |
| private | 同じクラス内からのみアクセスできます。フィールドは通常『private』にしてカプセル化します。 |
| protected | 同じパッケージ内と、サブクラスからアクセスできます。 |
| (なし) | パッケージプライベートです。同じパッケージ内のクラスからのみアクセスできます。 |
| static | インスタンスではなくクラスに属するメンバーです。インスタンスを生成せずにアクセスできます。 |
| final(フィールド) | 一度代入したら変更できない定数です。『static final』でクラス定数を定義します。 |
| final(クラス) | 継承できないクラスを定義します(例:『String』クラス)。 |
| final(メソッド) | サブクラスでオーバーライドできないメソッドを定義します。 |
サンプルコード
AccessModifiers.java
class Counter {
private int count = 0;
static int total = 0;
static final int MAX = 100;
public void increment() {
if (count < MAX) {
count++;
total++;
}
}
public int getCount() { return count; }
}
class MathHelper {
static int square(int n) { return n * n; }
}
class AccessModifiers {
public static void main(String[] args) {
Counter c1 = new Counter();
Counter c2 = new Counter();
c1.increment();
c1.increment();
c2.increment();
System.out.println(c1.getCount());
System.out.println(c2.getCount());
System.out.println(Counter.total);
System.out.println(Counter.MAX);
System.out.println(MathHelper.square(5));
}
}
コンパイルして実行すると次のようになります。
javac AccessModifiers.java java AccessModifiers 2 1 3 100 25
よくあるミス
よくあるミス1: privateフィールドに外部から直接アクセスしてコンパイルエラー
『private』なフィールドはクラスの外部から直接アクセスできません。外部から値を読み書きするにはゲッター・セッターを使う必要があります。
AccessNg.java
class Fighter {
private String name = "八神庵";
private int power = 95;
}
class AccessNg {
public static void main(String[] args) {
Fighter f = new Fighter();
System.out.println(f.name);
f.power = 100;
}
}
コンパイルして実行すると次のようになります。
javac AccessNg.java
java AccessNg
AccessNg.java:10: error: name has private access in Fighter
System.out.println(f.name);
^
AccessNg.java:11: error: power has private access in Fighter
f.power = 100;
^
2 errors
『private』フィールドには、同じクラス内で定義したゲッター・セッターを通じてアクセスします。
AccessOk.java
class Fighter {
private String name = "八神庵";
private int power = 95;
public String getName() { return name; }
public int getPower() { return power; }
public void setPower(int power) {
if (power >= 0) this.power = power;
}
}
class AccessOk {
public static void main(String[] args) {
Fighter f = new Fighter();
System.out.println(f.getName());
f.setPower(100);
System.out.println(f.getPower());
}
}
コンパイルして実行すると次のようになります。
javac AccessOk.java java AccessOk 八神庵 100
よくあるミス2: staticフィールドをインスタンス変数と混同する
『static』フィールドはクラス全体で1つしか存在せず、すべてのインスタンスで値が共有されます。インスタンスごとに異なる値を持たせたい場合は『static』を付けてはいけません。
StaticNg.java
class Player {
static int score = 0;
public void addScore(int points) {
score += points;
}
}
class StaticNg {
public static void main(String[] args) {
Player iori = new Player();
Player kyo = new Player();
iori.addScore(50);
kyo.addScore(30);
System.out.println(iori.score);
System.out.println(kyo.score);
}
}
コンパイルして実行すると次のようになります。
javac StaticNg.java java StaticNg 80 80
インスタンスごとに異なる値を持たせるには、『static』を付けずにインスタンスフィールドとして宣言します。
StaticOk.java
class Player {
int score = 0;
public void addScore(int points) {
score += points;
}
}
class StaticOk {
public static void main(String[] args) {
Player iori = new Player();
Player kyo = new Player();
iori.addScore(50);
kyo.addScore(30);
System.out.println(iori.score);
System.out.println(kyo.score);
}
}
コンパイルして実行すると次のようになります。
javac StaticOk.java java StaticOk 50 30
概要
カプセル化の原則として、フィールドは『private』にしてゲッター・セッターでアクセスするのが一般的です。これにより、値の検証ロジックを集約できます。
『static』メンバーはクラスに属するためインスタンスを生成せずに使え、すべてのインスタンスで値が共有されます。カウンターや定数、ユーティリティメソッドによく使われます。定数は慣例として『UPPER_SNAKE_CASE』(大文字スネークケース)で命名します。
クラスの定義とインスタンス生成については『class / new / コンストラクタ / this』を、継承については『extends / super / @Override』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。