Java Advisor 丘 om Performance Computing Ann Wollrath をな , リフレクション JDK 1.1 から、 Java 言語は java. lang. reflect という ンの機能を放する簡単な例だ。 あるクラスやインターフェイスに関する↑帯にをみつける 興未深いノヾッケージを含むようになった。このパッケー ジは、 Java のコードがコードに関する情報をみつけ出す ためにはまず、そのクラスの java. lang. Class オプジェ クトを使って、求める情報を検索する必要がある。この ことを可能にするクラスから構成される。プログラマーが 作成したクラスやインターフェイスのフィールドやコンス CI s オプジェクトは、以下のものを入手するメソッドを トラクタ、メソッドについての情報である。コードには直 備えている。 接書かれていないが、夫行時に発見されて呼び出されるメ クラスのスー / ヾークラス ソッドも呼び出すことができる。このテクニックはリフレ そのクラスカ躾装するインターフェイス クション (Reflection) と呼ばれる。 クラスのフィールド どのような仕組みでこれが可能になるのだろうか ? コンストラクタ Java はこれまでにもクラスに関するメタデータを表現す メソッド るためにいくつかの新しい抽象概念を ( フィールドやメソ その他 ッドに対して ) 導入してきた。そして、フィールド、コン リスト 1 では、クラスに関する詳細な情報をみつけて ストラクタ、メソッドなどに関する情報を入手するために 出力するために、 CIass オプジェクトに含まれる多くのメ java. lang ℃ lass に多くのメソッドを追加してきた。 ソッドを利用している。 Java において、メソッドは一人前のオプジェクトとな CIassInfo クラスの ma ⅲメソッドが、あるクラス ( コ った。いまでは、メソッドはコードのなかで指定しなくて マンドラインの最初の引数て指定する ) の田を出力する も、 Method オプジェクトを介して呼び出すことができ ための具イ勺な処理をおこなう。クラスもしくはインター る。コンストラクタも、同様のガ去で Constructor オプ フェイスのヘッダを出力し、そのあとで該当するクラスの ジェクトを介して呼び出すことかできる。 フィールド、コンストラクタ、メソッドを出力する。 今回は、リフレクションの使い方の基本とそれカ彳殳に立 main メソッドは、 Class. forName メソッドを使って つ場面について説明する。 クラスをロードする。したがって、クラスはクラスパスに 含まれていなければならない。 ClassInfo クラスは、起動 クラスに関する情報の入手 時に引数が与えられないと ArrayIndexOutOfBounds- Exception という薄清な例外を throw する。また、要 リフレクションのもっとも基本的な使い方は、クラスの 求したクラスがクラスパス上にない場合にも ClassNot- フィールド、コンストラクタ、メソッドを出力する javap FoundException となる。プログラムを簡単にするため のようなツールを書くといった用法である。末尾のリスト に、 main メソッドでは例外に対する特別な処置をおこな 1 は、あるクラスの private と protected な構成要素を っていない。このプログラムをより元成度の高いものにす すべて出力する、 javap コマンドの -protected オプショ 49 UNIX MAGAZINE 2000.4
連載 Java Advisor— コンストラクタの newlnstance メソッドは、に一の引 数として引数の酉改受け取る。プリミティフ型 (int や float など ) はオプジェクトではない。そこで、引数のリス トにおいてそのような型の値を指定するときは、対応する java. lang. Object を引数の型として使う。たとえは、 int に対しては java. lang. lnteger が、 float に対しては java. lang. Float かイ吏われる。 ッシュテープルを作成するだけなら、 HashtabIe h = new HashtabIe(IO) ; という 1 行のコードで同しことができるのに、わざわざ面 倒なことをしていると思うかもしれない。しかし、こうす れば、コンパイル時に実際のオプジェクト型が分からなく ともコンストラクタを呼び出せる。 コンストラクタの場合と同様のやり方で、リフレクショ ンを使ってメソッドをみつけ出し、呼び出すこともでき る。ー信己の例に続けて、ハッシュテープルにエントリを追 加する put メソッドを呼び出してみよう。 types new C1ass ロ { Object . class, Object . class } ; Meth0d m = c1. getMeth0d("put" , types) ; new Object ロ { "key' "value" } ; args B001ean b = (B001ean) m. invoke ( , args) ; put に対する Method オプジェクトは、 getMethod を使って作られる。 getMethod は、メソッド名、、 put" とパラメータ型を示す型の配列という 2 つの引数をとる。 put メソッドは、 m という Meth 。 d オプジェクトを介し て ( さきはど作った ) ハッシュテープル h に対して呼び 出される。引数のリストには、 put メソッドが必要とする key オプジェクトと value オプジェクトが含まれる。 の ( 列では、 key と value はたんなる文字列である。 リフレクションを使えは、コンパイル時に型をチェック することなしににれには、よい面も悪い面もある ) オプ ジェクトを生成し、メソッドを呼び出すことができる。そ のため、リフレクションでは慎重なプログラミングか要求 される。リフレクション使用時の危険としては、メソッド を探すときに間違ったパラメータ型のリストを指定してし まうとか、メソッドを呼び出すときに間違った引数リス トを指定してしまうことなどが考えられる。それぞれの場 合において、エラーを示す適切な例外が throw される。 リフレクションを使うと、プログラミングの際にエラーを UNIX MAGAZINE 2000.4 犯しやすくなる。なぜなら、引数のリストで引数の数や型 を誤って対応づけても、コンパイラは助けてくれないから だ。 Java の素晴らしい点の 1 つは、型のチェックに関 する強力な機能である。型に関するほとんどのエラーは、 javac コンパイラによって発見される。しかし、リフレク ションはこの安全弁を取り払ってしまう。 リフレクションを使う理由 JDK ではさまざまな部分でリフレクションが使われて いる。 java. i 。パッケージに含まれるオプジェクト・シリア ライゼーションは、リフレクションを使って、ストリー ムにシリアライズするオプジェクトのフィールドにアク セスする。バージョン 1.2 では、シリアライゼーション は、 java. lang. reflect. AccessibleObject という新しい クラスを使い、 Java によって強制されるアクセス制限を 無効にして、オプジェクトの private なフィールドを取 り込む。ノヾージョン 1.1 では、シリアライゼーションで オプジェクトのフィールドを取り込むには、ネイテイプ のコードが必要である。しかし、 JDK 1.2 の Accessi- bIeObject を使えは、この目的でネイテイプコードを使 う必要はない。 AccessibleObject の利用は十分慎重におこなうべきで ある。なせなら、プログラムがすべてのアクセス制限を 破壊する可能生があるからだ。さいわいにも、 Accessi- bleObject はイ頁できるコードによってのみ使える。 Ac- cessibleObject の使用には特別な許可が必要であり、 の許可をもたないコードがアクセス制限に違反しようとす ると IIlegalAccessException が発生する。 リフレクションを使うもう 1 つのコンポーネントとして JavaBeans がある。 JavaBeans において、リフレクショ ンは、ある bean のすべての get メソッドと set メソッ ドをみつけ、クライアントがそれらのメソッドを呼び出し て bean の国生を取り込むことを可能にする。 JavaBeans はリフレクションの必要性カ蒴した 1 つの要因である。 自分の書いたアプリケーションがリフレクションを必 要とすることなどないと考えるかもしれない。はとんどの 場合、リフレクションはいわゆるシステムコードやミドル ウェアに使われる。しかし、特殊な応用例として、オプ ジェクトがどのように生成されるかを特定することができ 51
このメソッドの実行結果が false の場合は、ネ川月状態か停 止のどちらかです。 スレッドの軈と例外 されます。両者の違いは、 Java VM の終了時の挙動だけ とデーモンスレッド (daemon thread) の 2 不鶤頁に分類 Java スレッドは、ユーサースレッド (user thread) ユーサースレッドとテーモンスレッド 宣言する必要はありません。 ラスのサプクラスなので、メソッドの throws 節でとくに Sec urity Except ion クラスは Runt imeExcept ion ク させることがないように配慮されています。 プラウサで実行したとき、ほかのアプレットを勝手に停止 ますが、第三者の作った信用できないアプレットを Web たとえは、アプレットでは個々にスレッドが作成され るわけです。 に対して実行しても安全かどうかをつねにチェックしてい マネージャーを使って、 Thread クラスの多くのメソッド セキュリティ的に危険な操作てす。そこで、セキュリティ・ ほかのスレッドの状態を調べたり、実行を制御するのは ジャーか許可しなかった場合に発生します。 スタンスです。メソッドの実行をセキュリティ・マネー これは、 java. lang. SecurityException クラスのイン SecurityException 例外 ドの throws 節でとくに宣言する必要はありません。 Exception クラスのサプクラスです。したがって、メソッ IllegalThreadStateException クラスは、 Runtime- 状態に移行するのかを正しく把屋する必喫があります。 レッドやスレッドグループがどの状態にあり、どのような したがって、スレッドを用いたプログラミングでは、ス 誤って呼び出した場合にします。 プか特定の状態にあるときしか実行できないメソッドを、 ラスのインスタンスです。スレッドまたはスレッドグルー これは、 java. lang. IllegalThreadStateException ク IllegaIThreadStateException 例外 境によって例外が発生することがあります。 あるメソッドを実行したとき、スレッドの状態や実行環 UNIX MAGAZINE 2000.4 です。 Java フログラミング・ノート 45 判別するには、 isDaemon() メソッドを使います。 スレッドがユーザースレッドかデーモンスレッドかを デーモン状態の判別 か許可しない場合は、 SecurityException が発生します。 Exception が発生します。セキュリティ・マネージャー す。それ汐 ) 状態で実行すると、 IIIegalThreadState- このメソッドを実行できるのは、ネ川月状態のときだけで ります。 ると、 JavaVM カ鮗了しないという問題カ起きやすくな す。なお、デーモンスレッドでユーサースレッドを作成す を実行するのは異なるスレッドを作成する場合に限られま レッドになります。したがって、 setDaemon() メソッド ドに、デーモンスレッドが作成したスレッドはデーモンス ューサースレッドが作成したスレッドはユーザースレッ るとユーサースレッドになります。 true を指定するとデーモンスレッドに、 false を指定す void setDaemon(b001ean フラグ ) setDaemon() メソッドを使います。 ューサースレッドとデーモンスレッドの切替えには、 デーモン状態の変更 で、注意が必要です。 なのに Java VM カ鮗了しないといった問題か起きるの なお、正しく設定しないと、プログラムは終了したはす なります。 スレッドか動いているかは、 Java VM の実装によって異 ドとして利用されています。ただし、どのようなデーモン ライズ処理をおこなう、、 FinaIizer" などがデーモンスレッ オプジェクトを扱う、 Reference HandIer" 、ファイナ リファレンス・ ナルを処理する、、 Signal dispatcher を使うとよいでしよう。たとえば、 Java VM では、シグ バックグラウンド処理をおこなうためにデーモンスレッド グラムから直接アクセスできないスレッドを作成したり、 この特徴を活かして、ライプラリ内部でユーサー・プロ 了時に自重加勺に終了するスレッドといえます。 了します。つまり、デーモンスレッドは、 Java VM の終 ほかにデーモンスレッドか残っていても Java VM は終 ん。しかし、すべてのユーサースレッドカ鮗了した場合は、 ューサースレッドの動作中は Java VM は終了しませ
連載 . /Java Advisor— る。 Java では、インターフェイスは、メソッドだけでコン ストラクタを含まない。特別なガ去で特定のインターフェ イスを実装するオプジェクトを生成したいなら、特別な引 数の組合ぜをとるコンストラクタを含むインターフェイス を実装するクラスが必要になるかもしれない。 java ・ lang ・ Class と java. lang. reflect ノヾッケージのクラスを利用す れば、正しいパラメータ型をもった Constructor オプジ ェクトか得られる。このコンストラクタ・オプジェクトを 使って新しいインスタンスを作成すればよい。 リフレクションは、朱なコンストラクタを呼び出すこ とから、特別なフィールドやメソッドを探し出すことま で、きわめて ) 2 危な可能性をなえてくれる。しかし、リフ レクションの利用は慎重におこなうべきである。リフレク ションは、プログラムにおける単純明快で直接的なイン リスト 1 import Java. lang. reflect . * ; public class C1assInf0 { ターフェイスとクラスの代用にすべきではない。リフレク ションはコードを分かりにくくする可能性があり、不幸に も、オプジェクトとメソッド・パラメータの型のチェック がおこなわれなくなる。リフレクションは、一イ財生か要求 される場面で、ほかによいガ去がないときにのみ使うよう にしよう。 Sun Microsystems の上級工ンジニアで、 Java Remote Method lnvocation システム・プロジェクトを率いている。 Sun Microsystems 研究所と MITRE では、信頼生の高い大規模な 分散処理システムと並列コンピューティングに関する研究をおこ なつな 「 Java's New Reflection 」 Performance Computing 1998 年 10 月号より ◎ 1998 , Performance Computing (). S. A. ) ・ Ann Wollrath public static void main(String ロ args) throws Exception { String name = args [ 0 ] ; CIass cI = CIass . forName(name) ; printModifiers(c1. getM0difiers() ) ; if ( ! c1. islnterface()) System. out . print("class " ) ; System. out . print()l . getName() + ” " if ()I ! = Object. class) { cl ・ getSuperc1ass ( ) ; CIass supercl if (supercl ! = null Ⅱ ! cl. islnterface() ) { System ・ out ・ print ( " ” + i[n] . getName()); 1 ; n く i . length; Ⅱ + + ) System. out . print ( " implements " + i[O] . getName()); 0 ) { cl . getlnterfaces() ; Java ・ lang. Object") + ” supercl. getName ( ) System. out . print( ( (supercl ! = Ⅱ u11 ) ? System. out . print("extends " ) ; 52 for (int Ⅱ if (i . length > C1ass ロ i UNIX MAGAZINE 2000.4
CAFE BABE リスト 3 Thread クラスの class Samp1e1 extends Thread { public static VOid main(String Samp1e1 t = new Samp1e1 ( ) ; args ロ ) t . start(); public void run() { for (int i 0 ; i く 3 ; System. out. println(" 十十 ) 1 : リスト 4 Runnable インターフェイスの実装 class Samp1e2 implements Runnab1e { public static void main(String args ロ ) Thread t = new Thread(new Samp1e2() ) ; t . start ( ) ; public void run() { fO て (int i 0 ; i く 3 ; System. out ・ println(" 十十 ) 1 : Thread クラスを継承する利点は、 Thread クラスの提 供するメソッドをオーバーライドして機能を拡張できるこ Runnable インターフェイスの実装 Runnable インターフェイスを実装したクラスを定義 し、そのインスタンスを生成してから実行する簡単な例を リスト 4 に示します。 このガ去の 1 つ目の利点は、 run() を定義するオプジェ クトと、 run() を実行するオプジェクトをう隹できること です。 Java 言語では実装の多重継承はできませんが、イ ンターフェイスを使えは複数の仕様を継承することかでき ます。 Thread クラスのメソッドをオーバーライドする 必要がなく、 run() メソッドが並行して実行できればよ い場合、つまり run() メソッドだけしか言当しない場合 は、 Thread クラスを継承する代わりに Runnable イン ターフェイスを実装すれは、ほかのクラスを継承できます ( そのほうがよい言気 t になることもあります ) 。 Thread ク ラスのメソッドをオーバーライドして機能を拡張する場合 でも、この機能拡張された Thread サプクラスを使って、 RunnabIe を実装したオプジェクトの run() メソッドを 実行させることができます。 48 2 つ目の利点は、スレッドカ躾行する処理をカプセル化 し、オプジェクトとして独立に扱えることです。たとえ は、 Runnable インターフェイスを実装したオプジェク トをキューイングし、そのキューを操作することができ ます。 3 つ目の利点は、スレッドとは独立に状態尉寺できる ことです。 Thread オプジェクトは 1 回しか並行実行で きないという制約があるため、 Thread クラスを継承した ときは、実行のたびに Thread オプジェクトを作成しな けれはなりません。このような場合には、 RunnabIe イン ターフェイスを実装したオプジェクトリ用す川ま状態 を保つことができます。 ☆ 今回は、スレッドの作成と実行、そしてスレッドの状態 について角得見しました。次回は、同期について解説する予 定です。 ( かざま・かすひろ NTT 未来ねっと研究所 ) [ 赭文献 ] [1]James Gosling, Bill Joy and Guy L. Steele, The ノ砒ん佖れ屮田 ge S 〃 ec c 佖 0 れ , 1996 (http://java ・ sun. com/docs/books/jls/index.html) [ 2 ] Tim Lindholm, Frank YelIin, ノ協いれ Machine S 〃 ec ca 厖 0 れ Second E 市 0 れ , 1999 (http://java ・ sun. com/docs/books/vmspec/2nd-edition/htmI/VM- SpecTOC. doc. html) [ 3 ] Sun Microsystems 「 Java プラットフォーム 1.2 API 仕 様」、 JDK 1.2 ドキュメント、 1998 年 (http://java ・ sun ・ com/products/jdk/l.2/ja/docs/ja/api/) [ 4 ] Sun Microsystems 「 Thread. stop 、 Thread. suspend および Thread. resume カ甘隹奨されない理山」、 JDK 1.2 ド キュメント、 1998 年 (http://java.sun ・ com/products/ jdk/l. 2/ja/docs/ja/guide/misc/threadPrimitive- Deprecation. html) [ 5 ] Mary Compione, Kathy Walrath, 〃 0 9 T ? 〃 0 07 、 ん Tasks At Once: T ん 7 ℃み , The Java TutoriaI Second Edition, 1999 (http://java.sun.com/docs/ books/tutorial/essential/threads/index. html) [ 6 ] CaIvin Austin, れんな 0 市尾 0 れ to . / 砒 , 佖 Stack Traces, Java Developer Connection, 2000 (http:// developer.Java.sun.com/developer/technicalArticles /Programming/Stacktrace/index. html) UNIX MAGAZINE 2000.4
CAFE BABE Java プログラミング・ノート スレッド・プログラミング ( 2 ) 風間一洋 0 Thread(Runnab1e ターケット , String 名前 ) 図 1 Thread オプジェクトと制流れ スレッドの作成と実行 UNIX MAGAZIN E 2000.4 以下のいすれかのコンストラクタを実行してインスタンス Java スレッドを利用するには、ま $Thread クラスの Thread オフジェクトの作成 に区男枻すにたんに、、スレッド " と呼ぶことにします。 ただし、説明を簡単にするために、以降では両者をとく 在します。 て制御を分岐し、 t3 で run() メソッドカ鮗了するまで存 流れとしてのスレッド 2 は t2 で start() メソッドによっ 流れを分岐しています。たとえば、図 1 において、制御の ルスレッドやユーサーレベル・スレッドを生成して制御の しかし、実際には、 start() メソッドの実彳にカーネ くなっていなけれは・いけません。 ドか終了し、かっそのオプジェクトへのリファレンスがな ジェクトがファイナライズされるためには、 run() メソッ 成さなでファイナライズされるまで存在します。オプ ジェクトとしてのスレッド 2 は、 tl でインスタンスが生 ださい。簡単な例を図 1 に示します。この図では、オプ 義のスレッド ) のライフサイクルは異なる点に注意してく ます、厳密には Thread オプジェクトと制御の流れ ( 狭 Thread オプジェクトと制御の流れ について解説し、簡単なプログラミンクイ列を紹介します。 今回は、スレッドの作成と実行、そしてスレッドの状態 きるようにするためのクラスです。 プジェクトとして抽象化し、さらにプログラムから操作で を使います。 Thread は、匍脚の流れであるスレッドをオ スレッドを利用するときは java. lang. Thread クラス new Thread() start() スレッド 2 ー : ←•run ( ) ー→ finalize() スレッド 1 を作成します。 Thread() Thread(RunnabIe ターゲット ) Thread(String 名前 ) Thread(ThreadGroup RunnabIe ターケット ) Thread(ThreadGroup Runnab1e ターケット , String 名前 ) Thread(ThreadGroup グループ , String 名前 ) グループ , グループ , ド名を指定するか、あるいは Thread オプジェクトに対 スレッド名を設定するときは、コンストラクタでスレッ スレッド名 機会をあらためて説明します ) 。 が、 Java ではスレッドのグルーフイヒが可能です信田は プを指定します。クラス名から擱則できるかもしれません タンスで、 Thread オプジェクトカ嘱するスレッドグルー グループは、 java. lang. ThreadGroup クラスのインス ジェクトを指定します。 スを実装したインスタンスで、 run() メソッドをもつオプ ターゲットは、 java. lang. Runnable インターフェイ void setName(String 名前 ) して setName() メソッドを実行します。 43
CAFE BABE 、、名前 " を省略した場合には、、、 Thread-1234" のように 、、 Thread-" の後ろに数字を付加した名前になります。 の数ネはユニークであり、 Thread オプジェクトを作成す スタックサイズ おこなうことができます。 スレッド名の言殳定と取得は、スレッドのすべての状態で string getName ( ) スレッド名は、 getName() メソッドで町 ( 得します。 るたびにインクリメントされます。 44 です。 レッドが生成されているが、実行権は得ていない状態 2. 実行可能 (runnable) : start() メソッドを実行し、ス しても、 start() メソッドを実行していない状態です。 1. 初期状態 (initial state) : Thread オプジェクトを生成 ます。 Java スレッドは、次の 6 つのいすれかの状態にあり スレッドの状態 します。 ドを 1 , 000 ミリ秒間停止させる簡単な例をリスト 1 に示 的にスリープさせるような場合に使います。現在のスレッ currentThread() メソッドは、現在のスレッドを一時 static Thread currentThread( ) Thread() メソッドをイ」します。 プジェクトを取得する場合は、 Thread クラスの current- 現在実行中のスレッド ( つまり自分自身 ) の Thread オ 実行中の Thread オプジェクトの取得 れば、とくに指定する必要はありません。 ただし、実彳にスタックか不足するようなことがなけ スタックサイズを、、一 xss サイス ' で指定します。 SoIaris のリファレンス・インプリメンテーションでは、 クサイズは、、一 xss サイズ ' オプションて指定します。 スレッドカ吶部で生成するネイテイプ・スレッドのスタッ ドのスタックサイズは、、一 xoss サイズ ' オプション、 Java SoIaris のフロダクション・リリースでは、 Java スレッ が、 Java VM の起重加こコマンド行引数で指定できます。 では、プログラムからはスタックサイズを決められません スレッドは、それぞれスタックをもっています。 Java リスト 1 currentThread() の実彳デ列 class SIeepTest { public static void main(String args ロ ) { } catch (InterruptedException e) { } ; Thread. currentThread ( ) . sleep( 1000 ) ; try { System. out . println("before") ; 図 2 System. out . println("after") ; スレッドの犹態多図 初期状態 (initial state) 生存中 (alive) 実行中→ー実行可能 (running) ← (runnable) 、 マ、 待機中 (waiting) 、△ 一時停止 (suspending): 停止 (stopped) 3. 実行中 (running) : 実行可能なスレッドが実行権を得 た状態です。 4. 待機中 (waiting) : スレッドのスリープ中、モニターの ロック待ち、条件変数待ち、プロッキング I / O の場合 です。 5. ー亭止 (suspending) : 実行可能、または実行中、待 機中の Java スレッドを一時停止状態にすることがで きます。ただし、待機中のスレッドを一時停止すると プログラム全体がデッドロックする可能性があるため、 JDK 1.2 以降では推奨されていません。 6. 停止 (stopped) : スレッドの実行を終了した状態です。 この状態遷移を図 2 に示します ( 矢印付きの点線て示し た部分は、推奨されない状崟移です ) 。 スレッドの状崟移については、今回およひ今後の連載 で詳しく角見します。 isAlive() メソッド スレッドが実行可能、実行中、待機中、一時停止のい すれかの状態にある場合を生存中 (alive) と呼びます。生 存中かどうかは、 isAlive() メソッドを用いて判定します。 UNIX MAGAZINE 2000.4
連載 Java Advisor— るなら、多くのエラーをチェックし、「クラス名を指定して ください。あなたの心は読めません」といった親切なメッ セージを返すようにすべきだろう。 クラスをロードしたあと、修飾子、クラス名、適切な extends 節や implements 節からなるクラスへッダを出 力するよう、 Class オプジェクトに問い合わせる。 print- Modifiers というメソッドは、該当するクラスの修飾子 を出力するのに使われる。手市子には、 public 、 private 、 protected といったアクセス修飾子や、 static 、 tran- sient 、 synchronized 、 abstract 、 final といったその他 の手市子か含まれる。インターフェイスの名称も 1 つの修 飾子として扱わ printModifiers メソッドによって出 力される。 class というキーワードではなく、 interface と いうキーワードが printModifiers によって出力されるた め、コマンドラインの引数がクラスを示しているかどうか がチェックされる。もしそうであオ L ば、 class というキー ワードか直接出力される。 次もクラスへッダである。クラス ( もしくはインターフ ェイス ) 名を出力し、それが他のクラスを継承 (extend) するかどうか、インターフェイスを実装 ( impleme Ⅱ t ) す るかどうかを調べる。 extends 節は、 implements 節の 前に出力される。スーパークラスをもたないクラスなら、 java. lang. Object がデフォルトのスーノヾークラスとして 使われる。 次の部分は見てのとおりだ。 public と protected の フィールド、コンストラクタ、メソッドをそれぞれ出力す る。フィールドに関しては、イ市子、型名、フィールド 名を出力する。コンストラクタに関しては、手箚市子、コン ストラクタ名 ( パッケージに登録されたクラス名 ) 、パラ メータ、 throw 節を出力する。そして最後に、それぞれの メソッドの市子、リターン型、メソッド名、パラメータ 型、 thr 。 w 節を出力する。 おもしろいことに、 Class. getName メソッドカ芍区す型 名では、配列型はかなり読みにくい形式になる。たとえは、 3 次元の配列である、、 lnteger[ ⅡⅡ ] " を宣言したとする と、 getName カ区す型名は、 [[[Ljava. lang ・ lnteger;" と なる。この表記は、スラッシュがすべてピリオドで置き換 えられていることを除くと、この型のイ瓦想マシン内部での 表現に近い。 このようなユーザーに不親切な表現のため、配列型は 50 出力する前に整形しておかなけれはならない。 getType- Name がそれをおこなう。酉リに対しては、その酉改」のコ ンポーネント型を調べて、その型の最後に、、 [ ] " を付け足 す。コンポーネント型は同時に配列型にもなりうるので、 多次 ) 顔己列を扱うために再帰を使っている。 このプログラムでは、それぞれのフィールド、コンス トラクタ、メソッドに対する適切な宣言を入手するのに toString を使って手抜きすることもできた。しかし、そ れは例を示すという目的にはそぐわない。また、 Method オプジェクト用の t 。 Str ⅲ g メソッドはパッケージに登録 されたメソッド名を含む。これは、クラスの言田の言当と してはやや冗長である。今回の目的のために toString メ ソッドを使わない重丿饑としては十分だ。 コンストラクタとメソッドの呼出し java. lang. Class はまた、あるクラスの特定のコンスト ラクタやメソッドを入手するためのメソッドをいくっか備 えている。いったん特定のコンストラクタ・オプジェク トを入手したら、そのコンストラクタの newlnstance メ ソッドを呼び出して、そのクラスのインスタンスを作りだ すことができる。 newlnstance メソッドは、引数の配列 を受け取って実際のコンストラクタに渡す。デフォルトの サイズを 11 として、新しい java. utiI.HashtabIe を作成 する例を以下に示す。 CIass cI = CIass. forName("java. util . HashtabIe") ; C1ass ロ types = new C1ass ロ { int . class } ; Constructor c = c1. getConstructor(types) ; Object ロ args new Object ロ { new lnteger(ll) } ; c . newlnstance(args) ; Obj ect h getConstructor は、引数としてパラメータ型の配列 をとり、そのパラメータに対するコンストラクタを返す。 Java では、、 . class" と略記すると、 Class リテラルカ甘旨定 される。そのため、 int. class はプリミテイプ型 int の Class オプジェクトを表す。 Class. forName の代わりに . class" という表言去を使って、 java. util. Hashtable の クラス・オプジェクトを参照することもできる。しかし、 ソースコードに実際の型を書かなくてもオプジェクトのコ ンストラクタを呼び出せることを強調しておきたかったの こでは、型は文字列となり、コンパイラによって パースされることさえない。 UNIX MAGAZINE 2000.4
Java フログラミング・ノート 1. Thread クラスのサプクラスを定義し、 run() メソッド をオ→ヾーライドした場合→サプクラスの run() メソ ッドが実行されます。 2. Thread クラスのサプクラスは定義せす、 Thread オプ ジェクトを作成するときに RunnabIe インターフェイ スを実装したクラスのインスタンスを指定した場合→ Thread クラスの run() メソッドから、さらにそのク ラスの run() メソッドか呼び出され実行されます。 3. Thread クラスのサプクラスも定義せす、 Runnable イ ンターフェイスを実装したクラスのインスタンスも指定 しなかった場合→ Thread クラスの run() メソッド を呼び出し、即座に終了します。 3 の場合は何もしないスレッドなので、実際のプログラ 2 3 4 5 (running) 。← (runnable) 、、、 実行中→実行可能 図 5 スレッドの終了ß$Ø状態多 初期状態 (initial state) 生存中 (alive) 待機中 ()a iti ng) 、△ 一時停止 1 -> (suspending)• 停止 (stopped) ムでは 1 ~ 2 の去が使われます。 スレッドの終了 3. run ( ) メソッド内で st 叩 ( ) メソッドを実行し、セキュ 2. run() メソッド内て例外またはエラーが発生し、実行を 1. run() メソッドカ症常に終了した。 スレッドは、以下の条ついすれかが成立したときに終 中断した。 了します。 リティ・マネージャーか許可した。 UNIX MAGAZINE 2000.4 つかのほかのデーモンスレッドか起動されています。 ません。 main スレッドを実行するときには、すでにいく を実行します。このスレッドはデーモンスレッドではあり FEST ファイルて指定されたクラスの main() メソッド が生成さ起重加の引数や JAR ファイル中の MANI- JavaVM か起動すると ma ⅲ ' という名前のスレッド Java VM の起動と終了 図 5 に、停止条件と状崟移の関係を示します。 すると、通常は牛 1 、 2 、 5 のいすれかになります。 stop() メソッドの使用力離奨されないこと [ 4 ] を考慮 実行し、セキュリティ・マネージャーか許可した。 5. あるスレッドが Runtime クラスの exit() メソッドを ティ・マネージャーか許可した。 4. 別のスレッドが stop() メソッドを実行し、セキュリ また、次のどちらかの条ー物ゞ成立した場合に Java VM は終了します。 1. java. lang. Runtime クラスの exit() メソッドを実行 し、セキュリティ・マネージャーか滸午可した。 2. デーモンスレッド以外のすべてのスレッドの実行カ鮗了 main メソッドの実行を終了したときに、デーモンスレ ッド以、タ V ) スレッドカ種カ作している場合は、 Java VM の 実行は終了しません。 スレッドの利用 スレッドの利用には、次の 2 つのガ去があります。 1. Thread クラスを継承するサプクラスを定義して run() メソッドをオーバーライドする。 2. Runnable インターフェイスを実装して run() メソッ ドをする。 これらの去ではほは同等のプログラムか第当できます が、どちらが適しているかはプログラムの設計によって 異なります。それぞれについて実装方法と特徴を説明し ます。 Thread クラスの Thread クラスを継承したサプクラスを定義し、そのイ ンスタンスを生成してから実行する簡単列をリスト 3 に 示します。このプログラムでは、スレッドを作成し、 i を 0 から 1 すつインクリメントして 3 回出力させています。 、一 0 47
JAPAN COMPUTER CO 日 P. SPARC シリーズ way ミッノジサーバ serles バ 0 二 外イ・ロ ワー & ラックマウントモテル JCC ワークグループサーバ 危 250 50 シリース ・ UltraSPARC-II 300 / 360 / 400 / 450MHz ( 最大 2CPU/4CPU) 高い信頼性と優れた価格性能比が、データベース、 グループウェア、 web サービスなどのサーバとして各々 のフィールドで最適な能力を発揮いたします。 Ja a2 搭載ターミナル JBox! Thin C ⅱ a 猷の効果を最大限に生かして オフィスて、生産現場で、研究室て 必要とされる最新ステーション機能が 今、「 JBox 」に集約 Java2Æ載 Java ターミナル ーこコ こ : コ に三 : コ ■ JBox 主な仕様 PowerPC 搭載・ Java2 (JREI .2.1 ) ・ 32 ~ 128MB ・ X11R6 ・ CD - ROM ドライフ、キーポード、マウス Windows NT Linux JVS シリーズ導入後 東京・大阪・パロアルト ( シリコンバレー ) ・ニューヨーク SO ⅱ & http://www.jcc. CO. jp/ 本社営業部 / 03 ー 3864 ー 551 1 本社 / 〒 101-0031 東京都千代田区東神田 2-6-9TEL.03-3864-8111 ( 大代 ) 関西営業所 / 〒 550-0014 大阪府大阪市西区北堀江 1 -20-15 佐野ビル 4F 関西営業所 / 06 ー 6539 ー 8441 資料請求 No. 001 日爪電機式谷社