えふのへや - 等々力随想

できればもうひとつのブログ http://ameblo.jp/bewise-kwsk/ もご訪問ください

J2SE 5.0

2004-10-10 01:23:20 | モノのこと
J2SE 5.0 (aka Java2 1.5) がリリースされたということで、何が新しくなったか少し読んでみました。

新機能の説明はこちら

まず、言語機能の拡張ですが、Genrics、ループの拡張、ボックス化の自動化、enum 型の導入、vararg、スタティック定義のインポート、アノテーション (メタデータ) の7個が導入されています。

ほとんどがなぜ今までなかったのか、というようなものですが、少し内容を見ていきましょう。

Generic の導入
Generic は C++ のテンプレートのような表記によって、コレクションなどの基盤クラスを指定できるようにするというものです。

たとえば、文字列のリストを作るといった場合、これまではリストから値を取得するたびに String へのキャストが要求されたわけですが、String の Generic を指定しておけば、値の取得でキャストが必要なくなるだけでなく、文字列型以外の値を追加・設定しようとするとコンパイラがエラーを検出してくれるので、コーディングの誤りを検出できる可能性が高くなっています。

ただし、Generic の実装は、コンパイラだけで完結している、つまり Generic が指定されたオブジェクトへのオペレーションでの型検査をコンパイラが行うことと、キャストを暗黙に行うことだけで実現されているようです。

このため、Generic を指定しないコードとの互換性は取れていますが、たとえば Generic を指定したコレクションに不正な型の値を設定しても何のエラーも発生せず、取得時点でコピー先との型互換性がないという例外を受けて、不正な型の値を検出するということになります。

このような限界はありますが、これまでは入出力型を限定するためだけにコレクションをラップするクラスを作ったりしていたのが、Generic によって非常に楽になるので、ありがたい拡張だと思います。

for ループの拡張
C# でいうところの foreach (... in ...) が導入されました。

コレクションの要素を対象にしたループは、整数インデクスでアクセスできる要素であれば、
for (int i = 0; i <list.size(); ++i) { といったコードを書いたり、イテレータを使用して、
for (Iterator i = collection.iterator(); i.hasNext();) {
Object o = i.next(); ... }
などといったコードを書く必要がありました。

このときのインデクス値やイテレータは単にコレクションから要素にアクセスするためだけに使用する中間的な値であり、本質的には不要なものです。

新しい for ループ記法を使用すると、
for (Object o : collection) { ... }
というように、インデクスやイテレータが不要になりますので、より直感的な記述が可能になります。さらに、Generic と組み合わせると、いったん Object 型で受けて、本来の型にキャストするといったことも不要になりますので、とても便利に使えます。

この機能も、プリプロセッサレベルでソースコードを書き換えて従来のループ型に変換することが容易に可能であり、実行系に対する影響は与えないので、従来コードとの互換性を気にする必要はまったくないと思います。

ボックス化の自動化
整数や浮動小数点数などの基本型はクラス型との互換性がない、たとえばクラス型の変数は参照をオブジェクトへの参照を保持しているので、空値 (null) という値を持つことができますが、整数型の変数には空値を設定することはできないといった非互換性が存在します。

このため、Java や C# には基本型に対応するクラスが規定されています。これまで Java では基本型とそれに対応するクラスとの間の変換 (ボックス化) を明示的に実行する必要があったのですが、J2SE 5.0 では自動変換がサポートされるようになりました。

この機能も、基本的にはコンパイラがコードを分析して変換のコードを自動的に挿入するといった実装がされていると予想されますので、ボックス化がコード上で見えなくなったとしても、実行はされていますので、よく考えて設計を行わないとコードに見合う性能が出ないといった問題が発生しそうな気がします。

実際、上記文書にもそのような趣旨の記述があります。

enum の導入
さて、問題の enum です。

数え上げ型が Java にない、ということ自体が、コードの可読性やコンパイル時の型の検査といった点で問題だったわけですが、今回の拡張で導入された enum はいったい何これ、といったような感じです。

enum を実現する場合、二つのやり方が考えられます。一つは enum をコンパイラレベルで整数型に置き換えるという実装で、コンパイル時の型検査だけを目的とした実現方法があります。もう一つは、enum 型に対応した新しいバイトコードや (暗黙の) クラスを導入して、toString() で数え上げ型で指定した文字列を出力できるようにしたりといった構成です。

J2SE 5.0 では、後者を選んだようです。これまで紹介した Generic の導入、for ループの拡張、ボックス化の自動化などは J2SE 5.0 で開発したコードを J2RE 1.4 の環境で実行できる (と思われる) のですが、enum を使った瞬間に、実行には J2RE 5.0 が必須となります。

具体的な実装はまだ理解できていないので、何とも言えないところがありますが、enum の基本クラスを拡張したクラスをコンパイラが自動的に生成して、そのクラスの機能を使用して enum を実現しているように見えます。

C# では、enum の値自体は整数型 (そのため、enum は基本型扱い) で、あとで出てくるアノテーション (C# では属性) で enum の定義文字列の取得をサポートしています。

どちらがいいとは一概には言えませんが、Java の enum を本格的に使いこなすには少しのハードルがありそうです。

と、いうところで続きはそのうちに …
コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 第37節-結果の整理 | トップ | いつものように-国立への長... »
最新の画像もっと見る

コメントを投稿

モノのこと」カテゴリの最新記事