【新・言語進化論】プロの言語仕様の読み方
第2回:nullは何型? 型、値、変数を読み解く!
著者:オープンストリーム 松下 雅和
監修者:オープンストリーム 高安 厚思
公開日:2007/11/13(火)
言語仕様をさらに深堀り!
前述した通り、言語仕様には仕様の説明や内部の仕組みについて詳細な説明が記述されています。しかし、言語仕様をさらに読み進めていくと、それぞれの仕様の説明だけでなく、その仕様をどのように利用すべきか、なぜその仕様が生まれたかまで説明されていることに気づくでしょう。
前ページで説明したヒープ汚染について、言語仕様には「Assignment from a value of a raw type to a variable of a parameterized type should only be used when combining legacy code which does not make use of parameterized types with more modern code that does.(訳:パラメータ化型の変数に対する未加工型の値の代入は、パラメータ化型を利用していない既存コードとパラメータ化型を利用している最新コードを連携させる場合にのみ使用すべきである)」とあります。
また言語仕様の「4.8 Raw Types(未加工型)」には「The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of genericity into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.(訳:未加工型の使用は、既存コードとの互換性を確保するための譲歩手段としてのみ許されている。プログラミング言語Javaに対するジェネリック導入以降に作成するコードでは、未加工型の使用はまったく推奨されない。プログラミング言語Javaの将来のバージョンでは、未加工型の使用が禁止される可能性もある)」とあります。
このように未加工型の使用は言語仕様として推奨してはいません。Java 5以降では、既存コードとの互換性を確保する必要がなければ、パラメータ化型を積極的に利用するべきでしょう。
また言語仕様の「5.1.9 Unchecked Conversion(未チェック変換)」の考察(Discussion)では、「Unchecked conversion is used to enable a smooth interoperation of legacy code, written before the introduction of generic types, with libraries that have undergone a conversion to use genericity (a process we call generification).(訳:未チェック変換は、既存コード、すなわちジェネリック型が導入される前のコードとジェネリックを使用したライブラリをスムーズに連携させるために用いられるものである)」
「In such circumstances (most notably, clients of the collections framework in java.util), legacy code uses raw types (e.g., Collection instead of Collection<String>). Expressions of raw types are passed as arguments to library methods that use parameterized versions of those same types as the types of their corresponding formal parameters.(訳:こういった状況(その代表として、java.utilのコレクション・フレームワークを使用するコード)では、既存コードは未加工型(たとえばCollection<String>の代わりにCollection)を使用することになる。未加工型の式は、対応する形式的パラメータの型と同じ型になる、パラメータ化されたバージョンのライブラリメソッドに対する引数として引き渡される)」
Such calls cannot be shown to be statically safe under the type system using generics. Rejecting such calls would invalidate large bodies of existing code, and prevent them from using newer versions of the libraries. This in turn, would discourage library vendors from taking advantage of genericity.(訳:この呼び出しによって、ジェネリックを使用している型システムの元での安全性を静的に保証することはできなくなる。ただ、この呼出を禁止してしまうと、既存コードの大部分が切り捨てられ、そういったコードからライブラリの新バージョンを使用することができなくなるのである。このことはまた、ジェネリックの利点を活かしたライブラリの作成意欲をベンダからそぐことにもなる)」
「To prevent such an unwelcome turn of events, a raw type may be converted to an arbitrary invocation of the generic type declaration the raw type refers to. While the conversion is unsound, it is tolerated as a concession to practicality. A warning (known as an unchecked warning) is issued in such cases.(訳:こういった好ましくない事態を避けるため、未加工型はその未加工型が参照しているジェネリック型宣言に対する恣意的な起動に変換できるようになっているわけである。このような変換は健全であるとは言えないものの、現実を考慮した上での妥当な譲歩と言えよう。なお、この際には警告(未チェック警告(unchecked warning)と呼ぶ)が発行される)」と説明されています。
ジェネリックの導入により言語仕様が拡張されましたが、既存コードとの連携を考慮する必要があったため、未加工型や未チェック変換などの概念も同時に生まれたのです。さらに未チェック変換が行われた場合は、コンパイル時に未チェック警告が発生します。
未チェック警告を抑制するためには、Java 5から追加されたアノテーション機能によるSuppressWarningsアノテーションを利用します。よって、SuppressWarningsアノテーションもジェネリックに紐付いた仕様の1つといえるでしょう。
ただし、SuppressWarningsアノテーションはあくまで既存コードとの互換性を確保する際に利用すべきであり、通常はパラメータ化型を利用して未チェック警告が発生しないように対応するべきです。安易にSuppressWarningsアノテーションを利用しないことをお勧めします。
(画像をクリックすると別ウィンドウに拡大図を表示します)
このように、言語仕様を読み解くことでそれぞれの仕様の利用方法だけでなく、何のために存在する仕様なのか、それぞれの仕様の関連性(今回の例では未加工型、未チェック警告、SuppressWarningsアノテーションの関係)、内部でどのような処理が行われているのかまで理解することができます。そしてこのような仕様の読み方ができるようになると、今度はその技術が進もうとしている方向性までがみえてくるのです。
言語仕様に限らず、様々なドキュメントについても同じような読み方ができれば、今まで以上にその技術に対する理解も深まっていくことでしょう。
さて次回は、Linuxなどプラットフォームに詳しい鍋倉氏が、OSと密接にかかわりあうスレッドについて解説していきます。
参考文献
本連載の英語の訳は、下記の書籍を参考としております。
Java言語仕様 第3版(The Java Series)
ジェームズ・ゴスリン、ビル・ジョイ、ガイ・スティール、ギッラード・ブラーハ著
村上 雅章訳
ピアソンエデュケーションジャパン刊
タイトルへ戻る