【コラム】
Java SE 7にJavaの新機能として追加される多くのJSRの中で、一風変わったJSRに「JSR 275: Units Specification」というものがある。JSR 275はJavaプログラムにおいて数量や単位を扱うための強力な機能を提供する拡張APIである。このAPIを使えば、同じint型やdouble型の値でも、その単位がメートルなのかマイルなのか、グラムなのかポンドなのかといったことを区別して扱うことができるようになる。また、メートルでの距離からマイルへの距離へ変換するなどといった単位変換のための機能も用意される。
JSR 275で提供される予定の主な機能を以下に挙げる。
たとえば長さを表すdouble型のプロパティを持っているクラスを考えてみよう。通常のJavaプログラムでは、このdouble値がどの単位の長さを表すのか区別することができない。それどころか、誤って長さ以外の値を設定してしまったとしても、それを検出する有効な手段もない。JSR 275を使用することで、実世界で使用される単位を正確にモデリングすることができるようになる。
また、単位に関連する主要な値があらかじめ設定されている点も見逃せない。たとえば1マイルが何メートルなのかといった情報が保持されているため、単位変換も容易に行うことができる。
JSR 275の詳細な仕様はまだ公開されていないが、科学技術に関連したJavaライブラリの開発を目指すJScienceプロジェクトによって、すでにその参照実装が公開されている。まだ仕様が決まっていないため今後も大きな変更が加えられる可能性はあるが、今回は現時点での実装を用いてUnit Specificationの使用例を紹介しよう。
JSR 275の参照実装はJScienceの公式サイトからダウンロードすることができる。配布ファイルはJScienceで開発されている各種ライブラリがセットになった「jscience-3.3.Beta-bin.zip」で、これに含まれている「jscience.jar」をにクラスパスに含めて使用する。
JSR 275は大きく3つのパートに分かれており、それぞれ次に挙げるパッケージでまとめられている。
単位の基本となるのはjava.measure.units.Unitクラスで、このクラスのインスタンスとしてさまざまな単位がjava.measure.units.SIおよびjava.measure.units.NonSIクラスに定義されている。
Unitのクラス定義は「Unit<Q extends Quantity>」となっている。このjavax.measure.quantities.Quantityというのは数量を表すための基底インタフェースで、このインタフェースを継承して長さや重さなどを表すさまざまなインタフェースが多数用意されている。Quantityの定義は「Quantity<Q extends Quantity>」となっているため、自身のサブインタフェースでパラメータ化されることになる。
たとえば、このAPIを利用して単位の変換を行うにはリスト1のようにする。まずSIクラスにはメートル単位を表すSI.METERという定数が用意されており、これをSI.METER()メソッドでキロ単位に変換している。長さの単位を表す型はUnit<Length>となる。続いてgetConverterTo()メソッドでマイル単位であるNonSI.MILEへのコンバータを取得し、convert()メソッドで変換を行っている。
package apisample;
import javax.measure.quantities.Mass;
import javax.measure.quantities.Scalar;
import javax.measure.units.NonSI;
import javax.measure.units.SI;
public class PersonSample {
public static void main(String[] args) {
Person person = new Person();
// 体重をキログラムでセット
Scalar weight = new Scalar(60, SI.KILOGRAM);
person.setWeight(weight);
Scalar returnWeight = (Scalar)person.getWeight();
System.out.println(weight.doubleValue(SI.KILOGRAM) + "キログラム");
System.out.println(weight.doubleValue(NonSI.POUND) + "ポンド");
// 体重をポンドでセット
weight = new Scalar(140, NonSI.POUND);
person.setWeight(weight);
returnWeight = (Scalar)person.getWeight();
System.out.println(weight.doubleValue(SI.KILOGRAM) + "キログラム");
System.out.println(weight.doubleValue(NonSI.POUND) + "ポンド");
// System.out.println(weight.doubleValue(SI.METER) + "メートル"); // コンパイルエラー
}
}
このプログラムの実行結果はプロンプト2のようになる。
> java [PATH_TO_JSCIENCE] UnitSample
100キロ = 62.1371192237334マイル
JSR 275をリスト2のように使うと、オブジェクトのプロパティに入れる値の単位を明確にすることができる。Personクラスの場合、weightプロパティは体重を表すようにしたいので、javax.measure.quantities.Massを利用してQuantity<Mass>型にしてある。
package apisample;
import javax.measure.quantities.Mass;
import javax.measure.quantities.Quantity;
public class Person {
private Quantity weight;
public void setWeight(Quantity weight) {
this.weight = weight;
}
public Quantity getWeight() {
return this.weight;
}
}
Personクラスはリスト3のようにして使う。Quantityを実装したクラスは、スカラー値を表すjavax.measure.quantities.Scalarクラスのみ用意されている。今回は、数値と単位(SI.KILOGRAM)を指定して体重のスカラー値(Scalar<Mass>)を作成して、それをPersonオブジェクトにセットしている。
Quantityインタフェースに宣言されているdoubleValue()およびlongValue()メソッドは、引数に任意のUnitを指定すれば、数値をその単位に自動的に変換して返してくれる。したがって今回はweight.doubleValue(SI.KILOGRAM)のようにすればキログラム単位の値が得られ、weight.doubleValue(NonSI.POUND)とすればポンド単位の値が得られる。変換に対応していないUnitが指定された場合は当然コンパイルできない。
package apisample;
import javax.measure.quantities.Mass;
import javax.measure.quantities.Scalar;
import javax.measure.units.NonSI;
import javax.measure.units.SI;
public class PersonSample {
public static void main(String[] args) {
Person person = new Person();
// 体重をキログラムでセット
Scalar weight = new Scalar(60, SI.KILOGRAM);
person.setWeight(weight);
Scalar returnWeight = (Scalar)person.getWeight();
System.out.println(weight.doubleValue(SI.KILOGRAM) + "キログラム");
System.out.println(weight.doubleValue(NonSI.POUND) + "ポンド");
// 体重をポンドでセット
weight = new Scalar(140, NonSI.POUND);
person.setWeight(weight);
returnWeight = (Scalar)person.getWeight();
System.out.println(weight.doubleValue(SI.KILOGRAM) + "キログラム");
System.out.println(weight.doubleValue(NonSI.POUND) + "ポンド");
// System.out.println(weight.doubleValue(SI.METER) + "メートル"); // コンパイルエラー
}
}
> java [PATH_TO_JSCIENCE] PersonSample
60.0キログラム
132.27735731092656ポンド
63.5029318キログラム
140.0ポンド
JSR 275には今回紹介した以外にも、各Unitの表記を取得する機能や、単位の次元を取得する機能、次元の互換性を判定する機能などを備えている。また、各Unitどうしの演算を行うこともできる。JSR 275は決して目を見張るような派手な機能を提供してくれるAPIではないが、これまで曖昧だった数値の扱いをより明確にすることで、プログラムの可読性や安全性を向上させてくれることだろう。
提供:マイナビ
大学・大学院・短大・専門学生向けの就職情報サイト「マイナビ2010」「マイナビ2009」に今すぐ登録しよう! 大手企業からベンチャー企業までの約13,000社の企業情報を公開、エントリーが可能です。2010年卒予定の方は「マイナビ2010」に、2009年卒予定の方は「マイナビ2009」に登録してください。
毎日コミュニケーションズはプライバシーマークを取得しています。
| マイナビ、3月より書籍連動型のクリエイティブ・デザイン系セミナー開講 [12:00 2/10] |
| Linux Mint 12 KDE登場 [10:26 2/10] |
| Dell、重複排除により最大98%のデータ削減が可能なバックアップストレージを発売 [09:44 2/10] |
| 北大、「ポジトロン断層撮影法」による脳腫瘍の性質を診断する手法を開発 [09:40 2/10] |
| NICTなど、手術支援ロボット「da Vinci」の3D裸眼映像伝送実証実験を計画 [09:36 2/10] |
|
ストーム、BTOもできるLinux PC「Storm Power Speed Mini LS Linux Edition」 [14:40 2/10] パソコン |
|
富士通、王子製紙グループにクラウドベースのIFRS対応会計システム導入 [14:39 2/10] 経営 |
|
NECと米CA、スマホ/タブレットにも対応した認証クラウドサービスを提供 [14:32 2/10] 経営 |
|
ストーム、4画面マルチモニター出力対応のQuadro NVS 450搭載のデスクトップPC [14:32 2/10] パソコン |
|
東芝、世界最軽量のUltrabook新モデル「dynabook R631/28E」 [14:25 2/10] パソコン |