Javaの文法
wait/notifyを用いるとスレッド間での能率的な連携が可能となる。あるスレッドが別スレッドでの処理が終わるのを待ち合わせる必要があるとき、または何らかのイベントが発生するまで待たねばならないとき、スレッドはその実行を一時停止してイベントが発生した際に通知を受け取ることができる。これはポーリングとは対照的である。ポーリングにおいては、スレッドは一定時間スリープしてはフラグや他の状態表示をチェックする処理を繰り返す。ポーリングはスレッドがチェックを繰り返さねばならないという点でより計算コストが掛かる上に、実際にチェックしてみるまでイベント発生を検知できないという意味で鈍感でもある。
waitメソッドには三つのオーバーロード版があり、タイムアウト値の指定方法がそれぞれ異なる:wait()、wait(long timeout)、wait(long timeout, int nanos)の三つである。一つ目のメソッドはタイムアウト値が0であり、これはタイムアウトが発生しないことを意味する。二つ目のメソッドはミリ秒単位のタイムアウト値を取る。三つ目のメソッドはナノ秒単位のタイムアウト値を取り、これは1000000 * timeout + nanosとして計算される。
waitを呼んだスレッドは待機状態となり、そのオブジェクトの待ちリストに追加される。そのスレッドは以下の三つのイベントのいずれか一つが起きるまで、オブジェクトの待ちリスト上に留まる:
別のスレッドがそのオブジェクトのnotifyまたはnotifyAllメソッドを呼ぶ (詳細はnotifyメソッド参照)
別のスレッドがそのスレッドのinterrupt()メソッドを呼ぶ
waitにて指定した0でないタイムアウト値が満了する
waitメソッドは、そのオブジェクトについての同期(synchronized)ブロックまたは同期(synchronized)メソッドの内部からのみ呼ばねばならない。これはwaitとnotifyとの間で競合を起こさないためである。スレッドが待ちリストに入るとき、そのスレッドはそのオブジェクトのミューテックス排他を解除する。そのスレッドが待ちリストから削除され実行可能スレッドとなった際に、そのスレッドは走行を再開するのに先立ってそのオブジェクトのミューテックスを改めて排他しなければならない。
Object.notify() と Object.notifyAll() メソッドはオブジェクトの待ちリストから一つ以上のスレッドを削除し、それらを実行可能スレッドとする。notifyは待ちリストから1スレッドのみ削除し、notifyAllは待ちリストから全てのスレッドを削除する。notifyがどのスレッドをリストから削除するかは規定されておらず、JVMの実装に依存する。
notifyとnotifyAllメソッドは、そのオブジェクトについての同期(synchronized)ブロックまたは同期(synchronized)メソッドの内部からのみ呼ばねばならない。これはwaitとnotifyとの間で競合を起こさないためである。
Javaのアノテーションはクラスやインタフェース、メソッドやフィールド、パッケージなどに対してメタデータとして付加情報を記入する機能で、Java SE 5 で追加された。
アノテーションはjava.lang.annotationインタフェースを実装することで自作することもできる。
Javaのアノテーションは三つに分けることができる。
マーカー・アノテーション – データが無く名前だけを持つアノテーション。
単一値アノテーション – データを一つだけ持つアノテーション。見かけはメソッド呼び出しに似ている。
フル・アノテーション – 複数のデータを持つアノテーション。
@Deprecated – 対象となるクラスやメソッドが非推奨であることを情報として付加する。
@Override – そのメソッドがスーパークラスのメソッドをオーバーライドしていることを示す。
@SuppressWarnings – 引数で指定した特定の警告メッセージをJavaコンパイラに与えず無視する。
@Target – 定義したいアノテーションがどこに適用されるべきかを指し示すメタアノテーション。
@Retention – アノテーションの配置方法を設定するメタアノテーション。
@Test:そのメソッドがテストメソッドであることを示す。このメソッドにテストを記述する。従来のJUnitでメソッド名がtestで始まるメソッドと同じ。
@Before:このアノテーションが付加されたメソッドは、@Test アノテーションが付いたメソッドを実行するたびに事前に実行されることを意味する。
@After:このアノテーションが付加されたメソッドは、@Test アノテーションが付いたメソッドを実行するたびに、必ず後から実行されることを意味する。
@BeforeClass:このアノテーションが付加されたメソッドは、そのテストクラスを呼び出す前に実行される。
@AfterClass:このアノテーションが付加されたメソッドは、そのテストクラスを呼び出した後に実行される。
クラスやメソッドにマーカーアノテーションを付加するには以下のようクラスやメソッドの接頭辞に最低一つ以上のスペースまたは改行コードを入れて修飾子のように記述する。
この例は、クラスに非推奨、メソッドに、スーパークラスからのメソッドをオーバーライドしていることを意味するマーカーアノテーションを付加している例である。
単一値アノテーションを付加するには以下のようにする。
この例は、java/ioインタフェースを実装したクラスのフィールドにstatic finalなserialVersionUIDが宣言されていないという警告を無視するアノテーションを付加していることを意味する。
これは、以下のような書き方もできる。これは単一値アノテーション@SuppressWarningsがvalue()メソッドを一つしか持たないことがわかっているためvalue = を省略できることを意味する。
このアノテーションは、戻り値の型がString[]になっているため同じvalue値であっても以下のように複数指定することができる。以下のように指定することで、シリアルバージョンIDが設定されていない警告と、コレクションで総称型による型チェックを行われていないことによって生ずる警告を無視することができる。 "unchecked"はメソッドに対してのみ設定することもできる。
このアノテーションは正確に記述すると以下のようにString[]配列の初期化宣言のようになる。
フルアノテーションは、複数のデータ型を持つアノテーションである。ここでは自作したアノテーション @MyAnnotation があるとき、以下のように、変数名 = 値の形をカンマで区切って記述する。各値の記法は、各アノテーションで定義されているメソッドの戻り値の型で決まる。たとえばこの場合valueという変数名はStringを戻り型にとる value() というメソッドと、int を戻り型にとる version() というメソッドを持つ。フルアノテーションの場合は、default によりデフォルト値が設定されているアノテーション以外は、value = や version = を省略することはできない。
アノテーションを定義するには、interfaceキーワードの接頭辞に@をつけて定義する。
マーカーアノテーションは以下のように定義する。メソッドやフィールドが一切ないマーカーインタフェースのアノテーション版ともいえる。@Overrideや@Deprecatedがこれらのアノテーションに相当する。
単一値アノテーションは以下のように定義する。このアノテーションには少なくともメソッドがひとつだけ定義されている。単一値アノテーションのメソッド名にはvalueという名前をつけるのが儀礼である。
フルアノテーションは以下のように定義する。以下のように二つ以上のメソッドを定義する。
メタアノテーションとは、定義しているアノテーションのみにつけられるアノテーションのことである。メタアノテーションの例としては@Targetや@Retention、@Documented、@Inheritedがあり、これらはクラスやメソッドなどには使うことができず、アノテーションのみに使うことができる。アノテーションを定義するために使われるアノテーションということから、メタアノテーションと呼ばれる。
メタアノテーションを使ってアノテーションを定義するには、以下のように記述する。
このとき、@Retentionは、新たにアノテーション NewAnnotation を作るとき、このアノテーション情報はソースコードのみにしか保存されないことを意味する。@Targetはこのアノテーションをどの型に使うことができるかを指定している。この場合、ANNOTATION_TYPE と METHOD を指定しているのでこのアノテーションはアノテーション型とメソッドにしか使うことができない。つまり、この NewAnnotation もまた、メソッドだけでなくアノテーションにも保存できるため、メタアノテーションとしても使えることを示している。
メタアノテーション@Retentionには以下のjava/lang/annotation列挙型を設定することができる。
メタアノテーション@Targetには以下のjava/lang/annotation列挙型を設定することができる。これは配列を使って
と複数指定することができる。ただし、同じ値を { … } 内で複数使用するとエラーとなる。これによって型を指定することで、そのアノテーションが、どの型に対して使うことができるのかを指定できる。
関連項目: Java Platform, Standard Edition#java.io と New I/O
J2SE1.4よりも前のバージョンのJavaはストリーム・ベースのブロッキングI/Oのみをサポートしていた。これは1ストリームにつき1スレッドを必要とした。何故ならストリームの入力または出力を行おうとすると、それが完了するまでそのスレッドは完全に待ちに入ってしまい、他の処理がいっさい行えなくなったからである。これは、Javaを用いたネットワークサービスを構築する上で、スケーラビリティと性能双方の面で大きな問題となっていた。J2SE1.4以降では非ブロッキングI/OフレームワークとしてNIO (New I/O) が導入され、このスケーラビリティ問題は修正された (ただし、サンによるNIO APIの実装にはまだ多くの問題点がある)。
非ブロッキングIOフレームワークは、以前のブロッキングIOフレームワークより遥かに複雑ではあるが、一つのスレッドで任意の数の"チャネル"を扱うことができる。このフレームワークはReactorパターンをベースとしている。
(ウェブブラウザではなく) スタンドアロン仮想マシンで実行されるJavaコード
mainメソッドは以下のように定義されなければならない:
ウェブブラウザで明示された表示領域上で実行されるJavaコード。
initとdestroyは一度だけ呼ばれるが、startとstopはユーザがウェブページを訪問するたびに何回も呼ばれる。
HTMLのappletタグをアプレットのソースコードに埋め込むことができる。
appletタグを書くと、そのアプレットは.htmlファイル無しでも、簡易アプレットビューアによって直接実行可能となる。
典型的には、appletタグはimport文の直後に書かれる。
appletタグは/* */コメントによって囲まれていなければならない。
Webサーバ上で実行されるJavaコードであり、その出力 (一般的にHTMLやXML) は典型的にはウェブブラウザに対して送信される。
ウェブページにJavaコードを埋め込む形態。
JSPタグはウェブサーバで処理され、出力結果 (一般的にHTMLやXML) はクライアントに送信される。
JSPコードは実行される前にJava Servletにコンパイルされる。
JSPはJava Servletの拡張である。
JSPタグの使用法はPHPやASPのタグの使用方法と類似する。
Javaはケースセンシティブ (大文字小文字を区別する) である。
コメントの文法はC++と同じである。
なお、ドキュメンテーションコメントとしてJavadoc方式をサポートする。
James Gosling, Bill Joy, Guy Steele, and Gilad Bracha, The Java language specification, third edition. Addison-Wesley, 2005. ISBN 0-321-24678-0.
Patrick Naughton, Herbert Schildt. Java 2: The Complete Reference, third edition. The McGraw-Hill Companies, 1999. ISBN 0-07-211976-4
Vermeulen, Ambler, Bumgardner, Metz, Misfeldt, Shur, Thompson. The Elements of Java Style. Cambridge University Press, 2000. ISBN 0-521-77768-2