1-2-3:Javaのキーワード(予約語)


Javaでは以下の52語がキーワードとして予約されています。 それらをグループに分けて示します。

以上の 50語の他に const, goto の 2語は、使用されませんが予約はされています。 したがってプログラマーが独自の用途に使用することはできません。


基本データ型とその値

Javaには、数値、文字コード値、及び論理値の型と voidの計9種類の基本データ型が用意されています。これらはクラスではありません。

数値および文字コード値の型は以下の7種類です。 意味は C 及び C++ のそれにほぼ対応します。 ただし Javaの場合、short,int,long のサイズはマシンに依存せず常に固定です。 char は2バイトです。 数値は常に符号付き(2の補数表現)です。unsigned の宣言は存在しません。 charは符号なしです。 数値および文字コード値の型とサイズは以下の表のとおりです。
char と short のサイズは同じですが、 プログラム内での取り扱いは区別されます。 ただしこれらの 7種類の型は、 char型も含めて互いにキャスト演算によって型を変換することができます。 なおサイズが大きな型から小さな型への変換については、 数値の情報が失われる恐れがあるのでコンパイル時に警告が出されます。 char と short の間も明示的なキャストが必要です。

Javaの数値および文字コード値の型
byte char short int long float double
1バイト 2バイト 2バイト 4バイト 8バイト 4バイト 8バイト

boolean型は論理値のデータを扱う型です。 値は true もしくは false です。
Javaでは論理値を数値にキャストすることはできません。

void型は実体が存在しない型です。 メソッドの返値が存在しないことを示すために用います。
Javaにはプロトタイプ宣言はありません。 メソッドの引数が存在しないことを void で記述することはありません。

Javaの浮動小数表現はIEEEの規格に準拠していますが、実装によって 拡張されている場合があります。 その値に依存しないで動作を一意に保証する必要がある時には、その範囲を strictfp のキーワードで指定します。


クラス定義のキーワード class と interface

class および interface は、新しいクラス定義を開始するためのキーワードです。
class(または interface )に続く文字列がクラス名、 それに続くブロックがクラス定義と解釈されます。


class NewClass {

      /* メンバーの記述 */
}

インターフェイスは、実装を持たないように制限を受けた特殊なクラスです。 定義の開始には、キーワード class の代わりにキーワード interface を用います。 インターフェイスの定義のブロック内には、 staticなフィールドと abstractメソッドしか存在できません。


interface NewInterface {

      /* メンバーの記述 */
}


クラスの継承のキーワード extends と implements

extends と implements はクラスの継承に関連するキーワードです。
extends は新しいクラス定義のクラス名の後に現れます。 extends の直後の文字列は、スーパークラスとなるクラス名と解釈されます。 新しいクラスは、この指定されたクラスのサブクラスとして定義されます。
キーワード class によって新しいクラスを定義する場合、 extends の後に指定できるクラス名は 1個だけです。 インターフェイスではない すべての Javaのクラスは Object という共通のスーパークラスを持ちます。 extends が存在しない場合もスーパークラスが存在しないという意味ではなく、 extends Objetct を省略したものとして扱われます。 したがってキーワード class による定義の extends の後にインターフェイス名を 指定することは許されません。 インターフェイスは Objectのサブクラスではないからです。


class NewClass extends OldClass {

}

interface で新しいインターフェイスを定義する場合、 extends の後に指定できるインターフェイス名は複数あってかまいません。 インターフェイス名の間は , で区切ります。 もちろん extends の後に通常のクラス名を指定することはできません。


interface NewInterface extends Interface1,Interface2 {

}

implements も新しいクラス定義のクラス名の後に現れます。 implements の後の文字列は、組み込まれるインターフェイス名と解釈されます。 implements の後に指定できるのは、 インターフェイス名に限ります。
implements の後に来るインターフェイス名は複数あってもかまいません。 インターフェイス名の間は , で区切ります。


class NewClass extends OldClass implements Interface1,Interface2 {

}

Javaでは implements の機能を通じて多重継承を実現します。 ただし実装を持つスーパークラスは 1個しか許されません。


this と super

this はクラス定義内で、そのクラスのインスタンス自身を表すための キーワードです。
他のインスタンスのメソッドの引数に自分自身のインスタンスを渡したり、 ローカル変数との名前の衝突を解消する場合などに用いられます。

super はクラス定義内で、 そのクラスのスーパークラスの機能を呼び出すために用いるキーワードです。 super.init() のようにして、スーパークラスで定義されたメソッドを 呼び出すことを可能にします。 super() はスーパークラスのコンストラクタを呼び出します。


インスタンスの生成と参照 new と null

new は新しいインスタンスを生成するためのキーワードです。 new の後には生成したいインスタンスのクラスのコンストラクタが来ます。


Color color = new Color( 255, 0, 0 );  // 赤色のインスタンスを生成

Javaでは配列のサイズを指定する時にも new を用います。 配列とクラスの取り扱いは非常に似ています。


Color colors[] = new Color[12];  // 12個の要素を持つ Colorの配列を生成

Color colors[]; は Color[] colors; と記述しても同じ意味になります。 配列のサイズの指定は、配列が必要になった時点で行ってかまいません。 またサイズの指定を定数ではなく変数や計算式によって行うことも許されます。 なお、配列を生成しても個々の要素のインスタンスはまだ生成されていません。 それは改めて個々のインスタンスごとにコンストラクタを呼び出すことになります。
配列のサイズはどの配列のクラスでも length という一種の publicなフィールドに 格納されています。 したがって、上で定義した配列のサイズは次のようにして いつでも知ることができます。 (配列の要素をループの中で取り扱う時に便利です。)


int count = colors.length;  // 値 12 が返る

null は「インスタンスが存在しない」ことを表す特別な値です。 どの参照型のインスタンスにも代入することができます。 (ただし基本データ型のデータには代入できません。) 宣言だけで生成されていない変数の値は null に初期化されます。 Javaではメモリの解放は明示的に行われません。 不用になったインスタンスは、 デストラクタに相当するメソッドを呼び出して処理する必要はありません。 単に null を代入するだけでインスタンスと変数の間の繋がりはなくなります。 どの変数とも繋がりを持たなくなったインスタンスは、 自動的にガーベッジ・コレクションの対象となります。

インスタンスを参照する変数はクラスの型を指定して宣言し、 クラスのコンストラクタを用いて生成します。 したがって通常は、インスタンスが何という名前のクラスなのかは自明です。 しかし外から引数で渡されてきたインスタンスのような場合には、 それが何というクラスのインスタンスであるか チェックしたい場合も生じます。
instanceof はそのような時に使用するキーワードです。 instanceof は boolean 型の値を返す2項演算子です。 次のような使い方をします。


if( 変数名 instanceof クラス名 )

先頭の項の変数が参照するインスタンスが 後の項のクラスに所属するインスタンスであれば true, そうでなければ false が返ります。


package文 と import文

package と import はクラス定義の外で用いられるキーワードです。 Javaのプログラムでクラス定義の外に記述されるのは、 コメント文を除けば package文と import文のみです。

packageはソースファイル内のクラスが所属するパッケージ名を指定するのに用います。 パッケージを定義することでクラスをグループ化して管理することが可能になります。 またクラス間でのメンバーに対するアクセス制御を行ったり、 クラス名の衝突などを避けることができます。 大規模なアプリケーションを開発する場合には重要となります。 package文は 1個のソースファイルに 1つしか存在できません。 (同じソースファイル内に記述されたクラスは必然的に同一のパッケージとなる。) パッケージの階層構造の区切りは記号 " . " によって表します。
package文は、コメント文以外の他のすべての記述よりも先に置かなくてはいけません。 クラスのドキュメントのコメント文とクラス定義の間に package文および import文 が入るのは許されます。


/** パッケージ mytool.network に含まれるクラスの定義 */
package  mytool.network;
public class NewClass {
                :

package文は省略することもできます。 その場合にはクラスは「名前なしのパッケージ」に所属します。 したがって package文を省略したクラスどおしは、 共通のパッケージに所属していると見なされるわけです。

importは バイトコードをクラスライブラリ内で探索するための パッケージの情報を与えます。 パッケージの階層構造の区切りは記号 " . " によって表します。 package文と異なるのは、パッケージ名だけでなく最後にクラス名も指定する点です。 クラスの探索の出発点はクラスパスとして指定されたディレクトリです。 (デフォルトは、カレント・ディレクトリと JDKの標準のクラスライブラリが 置かれたディレクトリ)
import文はクラスのロードを実行させる命令ではありません。 探索の情報を提供するだけです。 import文を使用する代わりにプログラムの中で パス名を直接指定してもかまいません。次の2つの例は同じ意味です。


/** import を使った場合 */
import java.applet.Applet;
public class NewClass extends Applet {
                :

/** import を使わない場合 */
pulic class NewClass extends java.applet.Applet {
                :

java.langパッケージに所属するクラスはクラス名のみで常に参照できます。 したがって String や Thread などのクラスのために import文を記述する必要はありません。
同じパッケージに含まれる多数のクラスを利用したい場合は、 記号 " * " を用いて「すべてのクラス」を指定することもできます。


import  java.awt.*;   // java.awtパッケージのすべてのクラス


アクセス制御の修飾子 public, private, protected

クラス自身、 クラス内のメンバー(フィールド、メソッド、コンストラクタ、innerクラス)は、 必ずいずれかのレベルのアクセス制御を設定しなければなりません。 アクセス制御のためのキーワードは C++ と同じです。 public, protected, private の3つがあります。 この他に「デフォルトのアクセス制御」という概念があります。 アクセス制御の修飾子を明示的に記述しなかった場合は、 このデフォルトのアクセス制御と見なされます。 つまり Javaには全部で4種類のアクセス制御の状態があるわけです。 それぞれのアクセスの許可のルールを下表にまとめておきましょう。

アクセス制御のキーワードとその許可の範囲
publicproteced指定なしprivate
クラスの内部
同一のパッケージ×
サブクラス××
無関係なクラス×××

上の表からわかるように、 アクセス制御にはパッケージの指定も深く関係しています。 パッケージ文を省略した場合には、 private以外のアクセス制御は public と同じ意味になります。
クラスの外部からメンバーにアクセスする場合、 private や protected で制限を受けるのは、object.x という形式のアクセスです。 たとえば次のような例を考えてみましょう。


public class NewClass {

  private int x;
  public int getX(){ return x; }
}

object.x は許されませんが、getX() メソッドが public なので、 このメソッドを通して値を取り出すことは許されます。 同様に値を設定するメソッドを public で提供することもできます。 あるいは敢えてそれを行わないことで、データ x を「読み出し専用」のデータとして 扱うことも可能となります。


修飾子 static と final

Javaではアクセス制御以外にも フィールド及びメソッドの性質を指定する修飾子が何種類か存在します。 static と final は、それらの中でも最も頻繁に用いられるキーワードです。

static として宣言されたフィールドはインスタンスごとに生成されません。 そのクラスのインスタンスすべてに共通して利用されます。 static なフィールドは、 static でないフィールドよりも先に初期化されていることになります。 (このためフィールドの初期化の順番が、プログラムの見かけとは 異なって見える場合があるので注意してください。) クラスの中の staticフィールドしか対象として取り扱わないメソッドは、 staticメソッドとして宣言することができます。 (他のクラスのインスタンスを生成したり、取り扱ったりすることはかまわない。) staticメソッドの中で、そのクラスの staticでないフィールドや staticでない他のメソッドを利用しようとすると、 コンパイル時にチェックされエラーとなります。
クラス定義の内部には通常のメソッドとは別に、 staticな名前のないメソッドの手続きを記述することができます。 この手続きはインスタンスが生成される時ではなく、 クラスのバイトコードが VMに読み込まれた時点で実行されます。 主に staticフィールドの初期化などの処理に用います。 その処理は main()メソッドよりも先に実行されます。


/** static修飾子のテストのクラス */
public class StaticTest {

  /** staticなフィールド */
     static int x;

  /** staticな手続き */
     static {
         x = 100; // xの値を初期化
     }   

  /** 処理の開始のメソッド */
     static public void main( String argv[] ) {

           System.out.println("x = " + x );  // x = 100 を表示する
     }   
}

クラス定義、コンストラクタに static修飾子を付けるのは意味がないので、 できません。 ローカル変数に対しても static修飾子を付けることは意味がありません。
staticなフィールドおよびメソッドは、インスタンスを生成しなくても利用できます。 アクセスするには次のようにクラス名を直接使います。 (インスタンスを生成した場合は、そのインスタンス名で指定してもよい。)


  Color.red;  // 赤色を表す staticなデータ

final はローカル変数、フィールドに対しては値の変更を許さないこと、 メソッドであれば再定義を許さないこと、 クラスであればサブクラスの定義を許さないことを示します。
ローカル変数、フィールドに対する finalの修飾子は、 C 及び C++ の const 宣言と同じ機能を提供します。 ただし final のフィールドをサブクラスの中で再定義することは許されます。

static と final の概念は互いに独立です。 しかし、クラス固有の定数を定義する目的で static かつ final な フィールドがしばしば用いられます。 これらのフィールドの名前はすべて大文字で記述するのが習慣です。


public static final int BUFSIZE=1024;


修飾子 abstract と native

abstract と native は、 いずれもクラス内に実装を持たないメソッドを宣言するためのキーワードです。 これらの修飾子が付いたメソッドは、名前のみで定義のブロックが存在しません。


abstract public void addSomething();
native public void callSomething();

abstract は、 サブクラスでメソッドが再定義され実装される予定であることを示します。
native は システムに依存する Java以外の言語のモジュール内にメソッドの実装が存在することを示します。
abstractメソッドを1つでも含む(もしくは再定義せずにそのまま継承した) クラスは、やはり abstract として宣言しなくてはいけません。 abstractなクラスはインスタンスを生成することはできません。
インターフェイスの定義内のメソッドは必ず abstract です。 したがって、そのことを修飾子 abstract によって明示する必要はありません。 省略することも許されています。


修飾子 synchronized

sysnchronized は、 複数のスレッドによって同一のデータが非同期にアクセスされ 処理に混乱や矛盾が生じるのを防ぎます。
sysnchronized は、 メソッドもしくは特定のインスタンスとともに指定されたブロックを対象とします。 ブロックの場合は synchronized の指定を持つ処理が終わるまで 指定されたインスタンスにロックがかかります。 synchronized の指定を持つメソッドは、そのメソッドを定義したインスタンス自身に ロックをかけ、メソッドの処理が終わるまで他のスレッドから 内部のデータに同時にアクセスされることを防ぎます。


修飾子 transient と volatile

transient修飾子は、 フィールドを Sirializationの対象とするかどうかを指定します。 transientを宣言されたフィールドは、 インスタンスが Sirialization された時に情報として含まれません。
volatile修飾子が指定されたフィールドおよび変数は最適化の対象からはずされます。


ブロックとローカル変数の寿命

Javaの制御構造とそのキーワードは、C 及び C++ とほとんど同じです。 プログラムは完全に構造化されています。 処理の単位は 《{》 と 《}》 で囲まれた、 クラス定義、innerクラス、メソッド、ブロックです。 ブロックは何重にも階層構造を作ることができます。 ブロックは制御構造のキーワード for, while, do, if, else, switch 、 例外処理のキーワード try, catch と結びつきます。 これらのキーワードの後のブロックが単独の文もしくは 単独の他のブロックからなる場合は、 《{》 《}》 を省略することができます。 またキーワードなしで単にブロックを作ることもできます。
メソッドおよびブロック内で宣言されたローカルな変数は、 その内部のみでアクセスが可能です。 処理がメソッドおよびブロックから抜けると、 ローカル変数は消滅します。 ブロックの外の変数とローカル変数の名前が衝突した場合は、 ローカル変数の方が優先されて解釈されます。

繰り返しの処理の対象となるブロックを作るキーワードは、 for, while, do の3つです。
for はそれに続く《(》 と 《)》 の中に 《;》 で区切られた3つの文を持ちます。


for( int i=0; i<100; i++ ) {
    /* 繰り返しの処理の内容 */
}

それぞれの意味は、初期化の処理、繰り返しを続けるかどうかの判定条件、 繰り返しのたびに行われる処理です。 上の例のように、初期化の式の中でブロック内でのみ有効なローカル変数を 宣言することができます。

while はそれに続く《(》 と 《)》 の中に、 繰り返しを行うかどうかの判定条件を持ちます。


while( i<100  ) {
    /* 繰り返しの処理の内容 */
}

do の判定条件の文はその直後には来ません。 ブロックの後に置かれた while の文で条件を判定します。


  do {
    /* 繰り返しの処理の内容 */
  }
  while( i<100  );

do で始まる繰り返しのブロックは、最低1回は必ず呼び出されます。

continue 文はブロック内の処理を途中で中断し、 次の繰り返しの処理に移ることを意味します。
繰り返しのブロックから強制的に抜け出すには break 文を使います。 break によって処理は1つ外側のブロックに抜け出します。 多重のブロックを一度に抜け出すためには、 ブロックにラベル付けをし、そのラベル名を指定する break文を使います。 (Javaでは goto文は使用できません。)


  maketable: for( int i=0; i<100; i++ ) {
                for( int j=0; j<100; j++ ) {
                          :
                     break  maketable;
                          :
                }
             }

条件分岐を作るキーワードは if と switch です。 if は対応する else を持つことができます。else if をつなげることで、 複数の処理の分岐を行うことも可能です。


if( i<100 ){
}

if( i<100 ){
}
else {
}

if( i<100 ){
}
else if( i<50 ){
}
else{
}

switch は、その後の《(》 《)》 内の値によって複数の処理に分岐を行います。 switch のブロック内には case の後に指定された値ごとに処理を置くことができます。 該当する値の処理が存在しない場合の処理は、default: の後に置きます。


switch( value ){
        case 1:      break
        case 2:      break
        default:     break
} 

switch のブロックは単独のブロックです。 それぞれの分岐した処理を終えるには break 文でブロックから抜け出す必要が あります。
break 文は if のブロックは対象としません。 その外側のブロックに対しての break と解釈されます。 (そうしないと break するかどうかの条件判定ができなくなってしまうからです。)

if と switch の他に、記号≪ ? ≫による条件判定も使用できます。 ≪ ? ≫の前にある boolean型の値を判定条件とし、 true ならば≪ ? ≫直後の値として、false ならば≪ : ≫で区切られた 後の値として評価されます。


 System.out.println( ( i >= 0 ) ? i : (-i) ); // iの絶対値を表示 


例外の検出と処理 try と catch, finally

例外を検出するためのキーワードが try です。 try はブロック内の処理で発生した例外をすべて検出し、 後に続く catch のブロックのうちの該当する処理を呼び出します。
例外発生に対応したエラー処理を記述するためのキーワードが catch です。 catch の後の《(》 《)》 内には検出された例外のインスタンスが渡されます。 例外はクラス名によって処理を選択するのに持ちいられるのと同時に、 そのインスタンスは例外処理内でデータとして利用される引数でもあります。 例外のクラスとは Exception またはそのサブクラスです。
try と catch はブロック単位である点は if と else の関係と似ています。 場合分けのスタイルはむしろ switch と case の関係に似ています。 try に対して最低1つは catch が必要です。
キーワード finally のブロックは、 try ブロックの処理に伴って必ず呼び出されます。 該当する例外のクラスが見つからなかった 場合の処理を書けるのは、 switch case における default に似ています。ただし、 finally の内容は catch の処理が実行された場合でも必ず呼び出される点が違います。 また、try のブロックの処理が return, break, continue によって 途中で中断された場合にも呼び出されます。


try {
}
catch( Exception1 e ){
}
catch( Exception2 e ){
}
catch( Exception3 e ){
}
finally{
}

catch で指定される Exception のクラスのチェックは、 上から下に記述された順番に行われます。 したがって、ある Exception のクラスのサブクラスは、必ず上の位置に記述 しなくてはいけません。(これはコンパイル時にチェックされます。) 互いに継承関係がない Exceptionのサブクラスどおしの順番は任意でかまいません。
例外処理を細かく処理する必要が無い場合は、 共通のスーパークラスを指定した catchで処理してもかまいません。 極端な場合は、Exceptionクラスの単独の catch で処理することも可能です。

例外の発生 throw, throws

例外が発生したことを知らせるためのキーワードが throw です。 throw は try の中の処理から呼び出される側のメソッドに記述されます。 throw を行うメソッドは、 その宣言部分でどんな例外を渡すのかキーワード throws によって宣言します。


public method() throws SpecialExeption {

       throw new SpecialException("Error message");
}

throw文が呼び出されると、 処理はメソッドを呼び出している側の対応する catchのブロックにジャンプし、 throw文以降に記述されている処理は行われません。
throw で渡されるのは例外クラスのインスタンスです。(クラスではありません。) 上の例のように throw の前にコンストラクタを呼び出して 例外のインスタンスを生成する必要があります。


アサーション機能の提供 assert

このキーワードはJ2SDK1.4から追加された新しいものです。 デバッグの作業の効率を良くするためのアサーション(変数の値の評価) の機能を提供します。
それ以前のバージョンとの互換性を保つため、このキーワードをアサーションの 目的で使用するためには、コンパイル時にオプション指定が必要となります。