クラス、インタフェース、メソッド、コンストラクタ、変数には、下記の 修飾子 を指定することができます。
修飾子 | クラス | インタ フェース | メソッド | コンスト ラクタ | ブロック | 変数 | 説明 |
---|---|---|---|---|---|---|---|
public | ○ | ○ | ○ | ○ | × | ○ | アクセス修飾子 |
protected | ○ | ○ | ○ | ○ | × | ○ | アクセス修飾子 |
private | ○ | ○ | ○ | ○ | × | ○ | アクセス修飾子 |
static | ○ | ○ | ○ | × | × | ○ | スタティック修飾子 |
final | ○ | × | ○ | × | × | ○ | ファイナル修飾子 |
abstract | ○ | ○ | ○ | × | × | × | 抽象修飾子 |
native | × | × | ○ | × | × | × | ネイティブ修飾子 |
synchronized | × | × | ○ | × | ○ | × | 同期修飾子 |
transient | × | × | × | × | × | ○ | 一時的修飾子 |
volatile | × | × | × | × | × | ○ | 揮発性修飾子 |
strictfp | ○ | ○ | ○ | × | × | × | 厳密浮動小数修飾子 |
const | × | × | × | × | × | × | 定数 |
public、protected、private は アクセス修飾子 と呼ばれ、指定した変数やクラスなどを、どの範囲から参照可能かのスコープを制御するのに用いられます。クラス、インタフェース、メソッド、コンストラクタ、メンバ変数の修飾子として利用できます。
アクセス修飾子 | 同パッケージ | 他パッケージ | |||
---|---|---|---|---|---|
自クラス | サブクラス | 他クラス | サブクラス | 他クラス | |
public | ○ | ○ | ○ | ○ | ○ |
protected | ○ | ○ | ○ | ○ | × |
なし | ○ | ○ | ○ | × | × |
private | ○ | × | × | × | × |
下記にサンプルを示します。
myApp Test.java pkgA SamePkgSameClass.java SamePkgSubClass.java SamePkgOtherClass.java pkgB OtherPkgSubClass.java OtherPkgOtherClass.java
class Test { public static void main(String[] args) { pkgA.SamePkgSameClass o1 = new pkgA.SamePkgSameClass(); pkgA.SamePkgSubClass o2 = new pkgA.SamePkgSubClass(); pkgA.SamePkgOtherClass o3 = new pkgA.SamePkgOtherClass(); pkgB.OtherPkgSubClass o4 = new pkgB.OtherPkgSubClass(); pkgB.OtherPkgOtherClass o5 = new pkgB.OtherPkgOtherClass(); o1.test(); o2.test(); o3.test(); o4.test(); o5.test(); } }
package pkgA;
public class SamePkgSameClass {
private String privateValue = "privateValue";
protected String protectedValue = "protectedValue";
/* default */ String defaultValue = "defaultValue";
public String publicValue = "publicValue";
public void test() {
System.out.println("---- SamePkgSameClass ----");
System.out.println(publicValue); // 自クラスからはすべてアクセス可能
System.out.println(defaultValue);
System.out.println(protectedValue);
System.out.println(privateValue);
}
}
package pkgA;
public class SamePkgSubClass extends SamePkgSameClass {
public void test() {
System.out.println("---- SamePkgSubClass ----");
System.out.println(this.publicValue);
System.out.println(this.defaultValue);
System.out.println(this.protectedValue);
// System.out.println(this.privateValue); // アクセス不可
}
}
package pkgA;
public class SamePkgOtherClass {
public void test() {
System.out.println("---- SamePkgOtherClass ----");
SamePkgSameClass o = new SamePkgSameClass();
System.out.println(o.publicValue);
System.out.println(o.defaultValue);
System.out.println(o.protectedValue);
// System.out.println(o.privateValue); // アクセス不可
}
}
package pkgB; public class OtherPkgSubClass extends pkgA.SamePkgSameClass { public void test() { System.out.println("---- OtherPkgSubClass ----"); System.out.println(this.publicValue); System.out.println(this.protectedValue); // System.out.println(this.defaultValue); // アクセス不可 // System.out.println(this.privateValue); // アクセス不可 } }
package pkgB; public class OtherPkgOtherClass { public void test() { System.out.println("---- OtherPkgOtherClass ----"); pkgA.SamePkgSameClass o = new pkgA.SamePkgSameClass(); System.out.println(o.publicValue); // System.out.println(o.protectedValue); // アクセス不可 // System.out.println(o.defaultValue); // アクセス不可 // System.out.println(o.privateValue); // アクセス不可 } }
static はクラスがインスタンス化されていなくても、ClassName.methodName() などで、そのクラス、メソッド、変数などを参照可能であることを示します。これらを スタティッククラス、スタティックメソッド、スタティック変数 と呼びます。
class Test { static class TestClass { } // スタティッククラス static void test() { System.out.println("test"); } // スタティックメソッド static int value = 123; // スタティック変数 } public class Main { public static void main(String[] args) { Test.TestClass o = new Test.TestClass(); Test.test(); System.out.println(Test.value); } }
例えば、java.lang.Math クラスの sin() メソッドは static 宣言されているので、java.lang.Math.sin() として呼び出すことができますが、もし、static 宣言されていなければ、下記のように呼び出す必要があります。
// static 宣言されていれば x = java.lang.Math.sin(y); // 直接呼び出せる // static 宣言されていなければ java.lang.Math m = new java.lang.Math(); // インスタンス化が必要 x = m.sin(y);
final は上書きされないことを意味します。クラスに用いた場合はサブクラスを定義できないことを、メソッドに用いた場合はサブクラスでメソッドをオーバーロードできないことを、変数に用いた場合は誰もその変数を変更できないことを意味します。
final class ClassName { ... } class ClassName { final 型 メソッド名(引数) { ... } public static final double PI = 3.14159265358979323846; }
abstract は、クラス、インタフェース、メソッドが抽象的なものであり、不完全なものであることを示します。メソッド名、引数の型などのみを定義し、サブクラスが必ず実装しなくてはならない機能を明確にしておくのが主な利用目的です。
抽象クラス はそのままではインスタンス化することができず、必ずサブクラスを定義して不完全なメソッドの実体を定義してから使用する必要があります。抽象クラスは通常、ひとつ以上の 抽象メソッド を含みます。抽象メソッドはメソッド名、引数の型のみが定義されていますので、どこかでその中身を定義する必要があります。
abstract class ClassName { abstract void testFunction(int a); }
インタフェースは常に抽象です。以前は下記のように abstract interface と記述していましたが、最近では書かないことが推奨されています。
abstract interface ClassName { abstract void testFunction(int a); }
抽象クラスとインタフェースは用途は似ていますが、抽象クラスは抽象メソッド以外の通常のメソッドも記述できる代わりに、ひとつのクラスが複数の抽象クラスを継承することができません。
native は、メソッドが ネイティブメソッド であることを示します。ネイテブメソッドは型、メソッド名、引数の型といった作法のみを定義するもので、C言語など他の言語を用いてその中身を実装する必要があります。ネイティブメソッドの詳しい作成方法の説明は省略します。
class ClassName { public native void testFunction(int a); }
synchronized 修飾子付きのメソッドがマルチスレッド環境で実行される場合、メソッドのインスタンスを対象として排他制御が行われます。ひとつのインスタンスが複数のスレッドを持つ場合は排他制御が行われますが、スレッドが複数のインスタンスで実行される場合の排他制御は行われませんので注意してください。詳細は「スレッド」の章を参照してください。
class ClassName { synchronized void MethodName() { ... } }
上記は、下記のコードと同等の意味を持ちます。
class ClassName { void メソッド() { synchronized (this) { ... } } }
ディスクに保存したりネットワークで送信するために、オブジェクトの情報をバイトストリームに自動変換することをシリアライズといいますが、transient 修飾子付きの変数は一時的な変数であり、シリアライズの対象から除外されます。
class ClassName { transient String tmp; }
マルチスレッドの場合、それぞれのスレッドは性能向上のために変数のコピーを参照・変更し、その値を元の場所(メモリ)に書き戻さないことがあります。つまり、同じ変数でもスレッドによって値が異なるという現象が発生します。複数のスレッドから参照される可能性のある変数に volatile をつけることにより、この問題を回避することができます。
class ClassName { volatile int nCount; }
strictfp を指定したクラスでは、float や double の浮動小数点演算がプラットフォームに依存しない、厳密な動作をすることになります。strictfp を指定しない場合の浮動小数点演算は、プラットフォームに依存し、高速だけれどもプラットフォームによって若干結果が異なります。
strictfp class ClassName { double x, y; : }
const は、C/C++ 言語などで値を変更することができない変数を示しますが、現在の Java ではキーワードのみが定義されており、実際に使用されるケースはありません。