Java 修飾子

Java言語は多くの修飾子を提供しており、主に以下の2種類に分けられます:

  • アクセス修飾子
  • 非アクセス修飾子

修飾子はクラス、メソッド、変数を定義するために使用され、通常は文の先頭に置かれます。次の例で説明します:

public class ClassName { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String[] arguments) { //メソッド本体 }

アクセス制御修飾子

Javaでは、アクセス制御修飾子を使用して、クラス、変数、メソッド、コンストラクタへのアクセスを保護できます。Javaは4種類の異なるアクセス権限をサポートしています。

  • default(デフォルト、何も書かない): 同じパッケージ内で可視。修飾子を使用しない。使用対象: クラス、インターフェース、変数、メソッド。

  • private: 同じクラス内で可視。使用対象: 変数、メソッド。注意: クラス(外部クラス)を修飾することはできません。

  • public: すべてのクラスに可視。使用対象: クラス、インターフェース、変数、メソッド

  • protected: 同じパッケージ内のクラスとすべてのサブクラスに可視。使用対象: 変数、メソッド。注意: クラス(外部クラス)を修飾することはできません。。

以下の表でアクセス権限を説明できます:

アクセス制御
修飾子 現在のクラス 同じパッケージ内 サブクラス(同じパッケージ) サブクラス(異なるパッケージ) 他のパッケージ
public Y Y Y Y Y
protected Y Y Y Y/N(説明) N
default Y Y Y N N
private Y N N N N

デフォルトアクセス修飾子 - キーワードを使用しない

クラス、変数、メソッド、コンストラクタの定義でアクセス修飾子を指定しない場合、それらはデフォルトでデフォルトアクセス修飾子を持ちます。

デフォルトアクセス修飾子のアクセスレベルはパッケージレベルであり、同じパッケージ内の他のクラスからのみアクセスできます。

次の例のように、変数とメソッドの宣言では修飾子を使用しなくてもかまいません。

例

// MyClass.java class MyClass { //デフォルトアクセス修飾子 int x = 10; //デフォルトアクセス修飾子 void display() { //デフォルトアクセス修飾子 System.out.println("Value of x is: " + x); } } // MyOtherClass.java class MyOtherClass { public static void main(String[] args) { MyClass obj = new MyClass(); obj.display(); //MyClass 内のデフォルトアクセス修飾子の変数とメソッドにアクセスする } }

上記の例では、MyClass クラスとそのメンバー変数 x およびメソッド display() はすべてデフォルトアクセス修飾子を使用して定義されています。MyOtherClass クラスは同じパッケージ内にあるため、MyClass クラスとそのメンバー変数・メソッドにアクセスできます。

プライベートアクセス修飾子 - private

プライベートアクセス修飾子は最も厳しいアクセスレベルであり、宣言されたprivateメソッド、変数、コンストラクタは所属クラスからのみアクセスでき、クラスとインターフェースは private として宣言できません。private。

private アクセス型として宣言された変数は、クラス内の public ゲッターメソッドを通じてのみ外部クラスからアクセスできます。

private アクセス修飾子の主な用途は、クラスの実装詳細を隠蔽し、クラスのデータを保護することです。

次のクラスはプライベートアクセス修飾子を使用しています:

public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }

例では、Logger クラスの format 変数は private 変数であるため、他のクラスはこの変数の値を直接取得・設定できません。他のクラスがこの変数を操作できるようにするため、2つの public メソッド、getFormat()(format の値を返す)と setFormat(String)(format の値を設定する)を定義しています。

パブリックアクセス修飾子 - public

public として宣言されたクラス、メソッド、コンストラクタ、インターフェースは、他のどのクラスからもアクセスできます。

相互にアクセスする複数の public クラスが異なるパッケージにある場合は、対応する public クラスを含むパッケージをインポートする必要があります。クラスの継承により、クラスのすべての public メソッドと変数はサブクラスに継承されます。

以下のメソッドはパブリックアクセス制御を使用しています:

public static void main(String[] arguments) { // ... }

Java プログラムの main() メソッドは public に設定する必要があります。そうしないと、Java インタプリタはそのクラスを実行できません。

プロテクテッドアクセス修飾子 - protected

protected は以下の2つの観点から分析して説明する必要があります:

  • サブクラスと基底クラスが同じパッケージにある場合: protected として宣言された変数、メソッド、コンストラクタは、同じパッケージ内の他のどのクラスからもアクセスできます。

  • サブクラスと基底クラスが同じパッケージにない場合: サブクラス内では、サブクラスのインスタンスは基底クラスから継承した protected メソッドにアクセスできますが、基底クラスのインスタンスの protected メソッドにはアクセスできません。

protected はデータメンバー、コンストラクタ、メソッドメンバーを修飾できます。クラスを修飾することはできません(内部クラスを除く)。。

インターフェースおよびインターフェースのメンバー変数とメンバーメソッドは protected として宣言できません。次の図を見てください:

サブクラスは protected 修飾子で宣言されたメソッドと変数にアクセスできるため、無関係なクラスがこれらのメソッドと変数を使用するのを防ぎます。

以下の親クラスは protected アクセス修飾子を使用しており、サブクラスは親クラスの openSpeaker() メソッドをオーバーライドしています。

class AudioPlayer { protected boolean openSpeaker(Speaker sp) { //実装の詳細 } } class StreamingAudioPlayer extends AudioPlayer { protected boolean openSpeaker(Speaker sp) { //実装の詳細 } }

openSpeaker() メソッドを private として宣言すると、AudioPlayer 以外のクラスはこのメソッドにアクセスできなくなります。

openSpeaker() を public として宣言すると、すべてのクラスがこのメソッドにアクセスできます。

このメソッドを所属クラスのサブクラスにのみ公開したい場合は、そのメソッドを protected として宣言します。

protected は Java のクラスメンバーアクセス権限修飾子の中で最も理解しにくいものの1つです。詳細については、以下を参照してください:Java protected キーワード詳解。

アクセス制御と継承

以下のメソッド継承のルールに注意してください:

  • 親クラスで public として宣言されたメソッドは、サブクラスでも public でなければなりません。

  • 親クラスで protected として宣言されたメソッドは、サブクラスで protected または public として宣言する必要があり、private として宣言することはできません。

  • 親クラスで private として宣言されたメソッドは、サブクラスに継承されません。


非アクセス修飾子

他の機能を実現するために、Java は多くの非アクセス修飾子も提供しています。

static 修飾子は、クラスメソッドとクラス変数を修飾するために使用されます。

final 修飾子は、クラス、メソッド、変数を修飾するために使用されます。final で修飾されたクラスは継承できず、修飾されたメソッドは継承クラスによって再定義できず、修飾された変数は定数であり、変更できません。

abstract 修飾子は、抽象クラスと抽象メソッドを作成するために使用されます。

synchronized と volatile 修飾子は、主にスレッドプログラミングに使用されます。

static 修飾子

  • 静的変数:

    static キーワードは、オブジェクトから独立した静的変数を宣言するために使用されます。クラスのインスタンスがいくつ生成されても、静的変数のコピーは1つだけです。静的変数はクラス変数とも呼ばれます。ローカル変数は static 変数として宣言できません。

  • 静的メソッド:

    static キーワードは、オブジェクトから独立した静的メソッドを宣言するために使用されます。静的メソッドはクラスの非静的変数を使用できません。静的メソッドはパラメータリストからデータを取得し、それらのデータを計算します。

クラス変数とメソッドへのアクセスは、直接classname.variablenameとclassname.methodnameの方法でアクセスします。

次の例のように、static 修飾子はクラスメソッドとクラス変数を作成するために使用されます。

public class InstanceCounter { private static int numInstances = 0; protected static int getCount() { return numInstances; } private static void addInstance() { numInstances++; } InstanceCounter() { InstanceCounter.addInstance(); } public static void main(String[] arguments) { System.out.println("Starting with " + InstanceCounter.getCount() + " instances"); for (int i = 0; i < 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }

上記の例を実行した結果は次のとおりです:

Starting with 0 instances
Created 500 instances

final 修飾子

final 変数:

final は「最後の、最終的な」という意味を表し、変数は一度代入されると再代入できません。final で修飾されたインスタンス変数は、明示的に初期値を指定する必要があります。

final 修飾子は通常、static 修飾子と一緒に使用してクラス定数を作成します。

例

public class Test{ final int value = 10; //以下は定数を宣言する例です public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //エラーが出力されます } }

final メソッド

親クラスの final メソッドはサブクラスに継承できますが、サブクラスによってオーバーライドすることはできません。

final メソッドを宣言する主な目的は、そのメソッドの内容が変更されるのを防ぐことです。

以下に示すように、final 修飾子を使用してメソッドを宣言します。

public class Test{ public final void changeName(){ //メソッド本体 } }

final クラス

final クラスは継承できません。final クラスの特性を継承できるクラスはありません。

例

public final class Test { //クラス本体 }

abstract 修飾子

抽象クラス:

抽象クラスはオブジェクトのインスタンス化には使用できません。抽象クラスを宣言する唯一の目的は、将来そのクラスを拡張することです。

クラスは abstract と final の両方で同時に修飾することはできません。クラスが抽象メソッドを含む場合、そのクラスは必ず抽象クラスとして宣言する必要があります。そうしないとコンパイルエラーが発生します。

抽象クラスは抽象メソッドと非抽象メソッドを含むことができます。

例

abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //抽象メソッド public abstract void changeColor(); }

抽象メソッド

抽象メソッドは実装を持たないメソッドであり、そのメソッドの具体的な実装はサブクラスによって提供されます。

抽象メソッドは final および static として宣言することはできません。

抽象クラスを継承するすべてのサブクラスは、そのサブクラス自体が抽象クラスでない限り、親クラスのすべての抽象メソッドを実装する必要があります。

クラスが複数の抽象メソッドを含む場合、そのクラスは抽象クラスとして宣言する必要があります。抽象クラスは抽象メソッドを含まなくてもかまいません。

抽象メソッドの宣言はセミコロンで終わります。例:public abstract sample();。

例

public abstract class SuperClass{ abstract void m(); //抽象メソッド } class SubClass extends SuperClass{ //抽象メソッドの実装 void m(){ ......... } }

synchronized 修飾子

synchronized キーワードで宣言されたメソッドは、同時に1つのスレッドからのみアクセスできます。synchronized 修飾子は4つのアクセス修飾子に適用できます。

例

public synchronized void showDetails(){ ....... }

transient 修飾子

シリアル化されたオブジェクトが transient で修飾されたインスタンス変数を含む場合、Java 仮想マシン(JVM)はその特定の変数をスキップします。

この修飾子は変数を定義する文に含まれ、クラスと変数のデータ型を前処理するために使用されます。

例

public transient int limit = 55; //永続化されません public int b; //永続化

volatile 修飾子

volatile で修飾されたメンバー変数は、スレッドがアクセスするたびに、共有メモリからそのメンバー変数の値を強制的に再読み取りします。また、メンバー変数が変更されると、スレッドは変更値を共有メモリに強制的に書き戻します。これにより、どの時点でも、2つの異なるスレッドは常に同じメンバー変数の同じ値を参照します。

volatile オブジェクト参照は null の場合があります。

例

public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) //1行目 { //コード } } public void stop() { active = false; //2行目 } }

通常、あるスレッドが run() メソッドを呼び出し(Runnable で開始されたスレッド)、別のスレッドが stop() メソッドを呼び出します。 もし1行目の中のバッファの active の値が使用される場合、2行目の active の値が false の場合、ループは停止しません。

しかし、上記のコードでは volatile で active を修飾しているため、このループは停止します。

その他の拡張