Profile

ys2310

Author:ys2310
2008年春にNew York Cityにあるふる〜い大学を卒業。


Categories


new postings


new comments


new trackbacks


monthly archeive


FC2ブログ 転職
DATE: CATEGORY:スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
| BLOG TOP |
DATE: CATEGORY:Java note


 デシマルで加減乗除をしてみる [java.math.Decimal]

 続いて、先ほど紹介したjava.math.BigDecimalクラスについて、四則演算のための典型的なメソッドを中心に、主要なメソッドを解説していきます。

java.math.BigDecimal#add(加算)

 足し算を行いたい場合には addメソッドを利用します。(3)の個所のように、BigDecimalクラスのインスタンスを2つ利用して加算を実現します。加算した後の値がメソッドの返り値として戻されます。 下記のソースコードを実行してみましょう。

DecimalSample.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.math.BigDecimal;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class DecimalSample extends JPanel {

    public DecimalSample() {
        setBackground(Color.white);
    }

    public void paintComponent(final Graphics argGraphics) {
        
        super.paintComponent(argGraphics);
        argGraphics.setFont(new Font("Dialog", Font.PLAIN, 32));
        final BigDecimal value1 = new BigDecimal("152.3");
        final BigDecimal value2 = new BigDecimal("273.42");
        // 加算を実施
        final BigDecimal value3 = value1.add(value2); // (3)
        argGraphics.drawString(value1.toString() + "+"
            + value2.toString() + "=" + value3.toString()
             , 10, 32);
    }

    private static void createAndShowGUI() {
        final JFrame frame = new JFrame("デシマル利用サンプル");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new DecimalSample());
        frame.setLocationRelativeTo(null);
        frame.setSize(400, 400);
        frame.setVisible(true);
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

図3 デシマル利用サンプル(加算)
図3 デシマル利用サンプル(加算)

java.math.BigDecimal#subtract(減算)

 引き算を行いたい場合には、subtractメソッドを利用します。上記DecimalSample.javaのpaintCompenentを下記に書き換えて実行してみましょう。

    public void paintComponent(final Graphics argGraphics) {
        super.paintComponent(argGraphics);
        argGraphics.setFont(new Font("Dialog", Font.PLAIN, 32));
        final BigDecimal value1 = new BigDecimal("152.3");
        final BigDecimal value2 = new BigDecimal("273.42");
        // 減算を実施
        final BigDecimal value3 = value1.subtract(value2); //(4)
        argGraphics.drawString(value1.toString() + "−"
            + value2.toString() + "=" + value3.toString()
            , 10, 32);
    }

図4 デシマル利用サンプル(減算)
図4 デシマル利用サンプル(減算)

 (4)の個所のように、BigDecimalクラスのインスタンスを2つ利用して減算を実現します。減算した後の値がメソッドの返り値として戻されます。

java.math.BigDecimal#multiply(乗算)

 掛け算を行いたい場合には、multiplyメソッドを利用します。上記DecimalSample.javaのpaintCompenentを下記に書き換えて実行してみましょう。

    public void paintComponent(final Graphics argGraphics) {
        super.paintComponent(argGraphics);
        argGraphics.setFont(new Font("Dialog", Font.PLAIN, 30));
        final BigDecimal value1 = new BigDecimal("152.3");
        final BigDecimal value2 = new BigDecimal("273.42");
        // 乗算を実施
        final BigDecimal value3 = value1.multiply(value2); //(5)
        argGraphics.drawString(value1.toString() + "×"
           + value2.toString() + "=" + value3.toString()
           , 10, 32);
    }

図5 デシマル利用サンプル(乗算)
図5 デシマル利用サンプル(乗算)

 (5)の個所のように、BigDecimalクラスのインスタンスを2つ利用して乗算を実現します。乗算した後の値がメソッドの返り値として戻されます。

java.math.BigDecimal#divide(除算)

 割り算を行いたい場合には、divideメソッドを利用します。divideメソッドには、いくつかの注意すべきポイントがあります。

  • 私たちの多くが小学校で習ったような割り算を実行するために、丸めモードとして、java.math.BigDecimal.ROUND_HALF_UPを指定するようにします。
  • スケールを指定するメソッドと、スケールを指定しないメソッドとの2種類がある点に注意が必要です。

スケールを指定しない例

 上記DecimalSample.javaのpaintCompenentを下記に書き換えて実行してみましょう。

    public void paintComponent(final Graphics argGraphics) {
        super.paintComponent(argGraphics);
        argGraphics.setFont(new Font("Dialog", Font.PLAIN, 30));
        final BigDecimal value1 = new BigDecimal("152.3");
        final BigDecimal value2 = new BigDecimal("273.42");
        // 除算を実施

        final BigDecimal value3 = value1.divide(value2,
            BigDecimal.ROUND_HALF_UP);
        argGraphics.drawString(value1.toString() + "÷"
           + value2.toString() + "=" + value3.toString()
           , 10, 32);
    }

 スケールを指定しない場合には、割られる数のスケールを計算結果のスケールに適用します(この例では、小数点以下第1位まで)。

図6 デシマル利用サンプル(除算1けた)
図6 デシマル利用サンプル(除算1けた)


スケールを指定する例

 上記DecimalSample.javaのpaintCompenentを下記に書き換えて実行してみましょう。

    public void paintComponent(final Graphics argGraphics) {
        super.paintComponent(argGraphics);
        argGraphics.setFont(new Font("Dialog", Font.PLAIN, 30));
        final BigDecimal value1 = new BigDecimal("152.3");
        final BigDecimal value2 = new BigDecimal("273.42");
        // 除算を実施
        final BigDecimal value3 = value1.divide(value2, 7,
            BigDecimal.ROUND_HALF_UP);
        argGraphics.drawString(value1.toString() + "÷"
            + value2.toString() + "=" + value3.toString()
            , 10, 32);
    }

図7 デシマル利用サンプル(除算7けた)
図7 デシマル利用サンプル(除算7けた)

 小数点以下第7位まで求めるよう、スケールを指定します。割られる数のスケールに関係なく、指定したスケール(この例では、7けたまで)を計算結果として取得できます。

デシマル型の比較

 デシマル型を使っていてよく間違いに陥りやすいのが、デシマル型の値の比較についてです。java.math.BigDecimalクラスには、値の比較を行うためのメソッドとして、compareToメソッドとequalsメソッドの2つがあります。

java.math.BigDecimal#compareToメソッド

 与えられた2つのBigDecimalオブジェクトの大小比較を行います。注意すべき点は、このメソッドで一致するかどうかを比較した際の判定結果についてです。compareToでは、2つのBigDecimalオブジェクトの値が一致するかをスケールを無視して比較します。例えば、2.0と2.00は等しいものと判断します。この点を特に注意する必要があります。

 それ以外の点については、通常のcompareToメソッドと同様なものとして考えて差し支えないです。

java.math.BigDecimal#equalsメソッド

 与えられた2つのBigDecimalオブジェクトの値が一致するかどうかを比較します。注意すべき点は、このメソッドでは、compareToとは異なり、2つのBigDecimalオブジェクトが値もスケールも同じである場合にだけ等しいと見なすという点です。例えば、このメソッドでは、2.0と2.00は等しくないものと判断します。


[Quote]:http://www.atmarkit.co.jp/fjava/rensai4/programer03/programer03_2.html

| BLOG TOP |
DATE: CATEGORY:Java note

J2SE 5.0 では言語仕様に大きな変更があります。コレクションクラスは、その影響を大きく受ける API です。ここでは、次の三つの追加仕様とからめて、J2SE 5.0 での動作を見てみましょう。

  • Generics
  • Autoboxing/Unboxing
  • Enhanced for Loop

因みに、J2SE は 1.5 (通称 Tiger)の開発中にバージョニング規則が変わり、 5.0 と呼称されるようになりました。また、 J2SE という呼称は 5.0 で最後であり、6.0 (通称 Mustang)では Java SE と呼称されることが決定しています。J2EE の次期リリースは 1.5 でしたが、Java SE と同じく Java EE 5.0 となります。

J2SE 1.4 までの規則

次のメソッドは、Collection インタフェースに従ってコレクションを操作するメソッドです。何れのメソッドも、引数として Collection 型のオブジェクト参照を受け取ります。使っているメソッドは、インタフェース Collection で宣言されたものだけなので、これを実装するクラス型オブジェクトは何でも処理可能です。

	// 要素の追加
public void addElapsedTime(Collection container, int MAX) {
long start = System.currentTimeMillis();
System.out.println(container.getClass().getName());
for (int i = 0; i < MAX; i++) {
// コレクションへの要素の追加
container.add(new Integer(i));
long end = System.currentTimeMillis();
if (i % 100000 == 0) {
System.out.print(end - start + ", ");
} else if (i == MAX - 1) {
System.out.println(end - start);
}
}
}

// イタレーションによる要素の取り出し
public void getElapsedTime(Collection container) {
long start = System.currentTimeMillis();
Integer obj = new Integer(0);
int sum = 0;
// 要素についての繰り返し(イタレータの利用)
for (Iterator itr = container.iterator(); itr.hasNext(); ) {
// Object型からInteger型へキャスト
obj = (Integer)itr.next();
// Integer型からプリミティブ型へ変換
sum += obj.intValue();
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}

というわけで、これらのメソッドを使うメソッドとして次のものを用意します。

import java.util.*;

public class CollectionDemo {
// 要素の追加
public void addElapsedTime(Collection container, int MAX) {
...
}

// イタレーションによる要素の取り出し
public void getElapsedTime(Collection container) {
...
}

// テスト用コントロールメソッド
// 引数はコレクションの要素の個数
// 例# java CollectionDemo 100000
public static void main(String[] args) {
int MAX = Integer.parseInt(args[0]);
CollectionDemo container = new CollectionDemo();

// ArrayList 型オブジェクト
Collection obj = new ArrayList();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// LinkedList 型オブジェクト
obj = new LinkedList();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// HashSet 型オブジェクト
obj = new HashSet();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// TreeSet 型オブジェクト
obj = new TreeSet();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// LinkedHashSet 型オブジェクト
obj = new LinkedHashSet();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// PriorityQueue 型オブジェクト
obj = new PriorityQueue();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);
}
}

これを、JDK 5.0 でコンペア/実行結果すると、次のようになります。

C:\java>javac CollectionDemo.java
注: CollectionDemo.java の操作は、未チェックまたは安全ではありません。
注: 詳細については、-Xlint:unchecked オプションを指定して再コンパイルしてくださ
い。

C:\java>javac -Xlint:unchecked CollectionDemo.java
CollectionDemo.java:10: 警告: [unchecked] raw 型 java.util.Collection のメンバと
しての add(E) への無検査呼び出しです。
container.add(new Integer(i));
^
警告 1 個

C:\java>java CollectionDemo 1000000
java.util.ArrayList
0, 78, 172, 234, 266, 391, 422, 531, 547, 578, 609
47
java.util.LinkedList
0, 63, 110, 157, 188, 235, 407, 485, 532, 578, 813
47
java.util.HashSet
0, 172, 312, 406, 750, 859, 906, 1000, 1187, 1343, 1437
156
java.util.TreeSet
0, 157, 375, 500, 641, 766, 907, 1032, 1204, 1329, 1469
78
java.util.LinkedHashSet
0, 156, 281, 625, 1109, 1234, 1328, 1437, 1750, 2625, 2718
250
java.util.PriorityQueue
0, 47, 78, 109, 125, 141, 281, 297, 344, 359, 406
31

C:\java>

コンパイル時に出されている警告が、J2SE 5.0 での追加仕様の部分です。コレクションフレームワークの API が変更になっているのに、従来の 1.4 の記述方法のままなので、警告が出されているわけです。承知の上であれば、コンパイル時オプションに、1.4 準拠である旨を明示すれば、このエラーは出されません。

C:\java>javac -source 1.4 -target 1.4 CollectionDemo.jav

C:\java>

Generics

早速、警告で指定されている部分を 5.0 準拠に変更してみましょう。

警告で指定されているのは、ソースコードの 10 行目、「container.add(new Integer(i));」です。5.0 に準拠すると、次のように修正すべきです。メソッド引数で受け取るコレクションに、要素は Integer だけであることをパラメタとして指定しておくわけです。

こうすることで、Integer 以外のものを add しようとすると、例外が発生します。

また、要素を取り出したとき、従来は Object 型で取り出されていたので、明示的にダウンキャストが必要でしたが、パラメタで指定してあるので、キャスト不要で目的の型として受け取ることが出来ます。

	// 要素の追加
public void addElapsedTime(Collection<Integer> container, int MAX) {
long start = System.currentTimeMillis();
System.out.println(container.getClass().getName());
for (int i = 0; i < MAX; i++) {
// コレクションへの要素の追加
container.add(new Integer(i));
long end = System.currentTimeMillis();
if (i % 100000 == 0) {
System.out.print(end - start + ", ");
} else if (i == MAX - 1) {
System.out.println(end - start);
}
}
}
C:\java>javac -Xlint:unchecked CollectionDemo2.java

C:\java>java CollectionDemo2 1000000
java.util.ArrayList
0, 78, 172, 250, 266, 391, 422, 516, 547, 578, 609
47
java.util.LinkedList
0, 78, 110, 157, 203, 250, 407, 500, 532, 578, 813
47
java.util.HashSet
0, 156, 297, 390, 734, 859, 906, 1000, 1187, 1328, 1422
171
java.util.TreeSet
0, 157, 375, 500, 625, 766, 891, 1032, 1188, 1329, 1469
63
java.util.LinkedHashSet
0, 141, 282, 610, 1094, 1219, 1313, 1407, 1735, 2578, 2688
203
java.util.PriorityQueue
0, 78, 141, 219, 234, 250, 297, 312, 359, 375, 391
31

C:\java>

Autoboxing/Unboxing

続いて、Autoboxing/Unboxing について見てみましょう。Autoboxing とは、int 型などのプリミティブ型の値を、Integer型などのラッパークラス型へ自動変換することです。Auto-Unboxing はその逆に、ラッパークラス型からプリミティブ型への自動変換です。要するに、次のことが出来るわけです。

String str = "100";
Integer intObj = Integer.parseInt(str);
int x = intObj + 10; // Unboxing
Integer intObj2 = x; // Autoboxing

ただし、 Autoboxing/Unboxing は、ラッパーとプリミティブ型間の変換なので、整数拡張などは施されません。int と自動変換可能なのは Integer のみです。

Autoboxing/Unboxing を用いてコードを書き換えると、次のようになります。

import java.util.*;

public class CollectionDemo2 {
// 要素の追加
public void addElapsedTime(Collection<Integer> container, int MAX) {
long start = System.currentTimeMillis();
System.out.println(container.getClass().getName());
for (int i = 0; i < MAX; i++) {
// コレクションへの要素の追加
// Generics で指定してあるので、
// Integer以外のものを追加しようとすると例外発生

// Autoboxing
container.add(i);

long end = System.currentTimeMillis();
if (i % 100000 == 0) {
System.out.print(end - start + ", ");
} else if (i == MAX - 1) {
System.out.println(end - start);
}
}
}

// イタレーションによる要素の取り出し
public void getElapsedTime(Collection<Integer> container) {
long start = System.currentTimeMillis();
// Auto-Unboxingのため不要
// Integer obj = new Integer(0);

int sum = 0;
// 要素についての繰り返し(イタレータの利用)
for (Iterator itr = container.iterator(); itr.hasNext(); ) {
// メソッド引数に Generics で指定してあるので
// Object型からInteger型へのダウンキャスト不要
// obj = (Integer)itr.next();

// Auto-Unboxing
// Integer型からプリミティブ型へ変換
// sum += obj.intValue();
sum += itr.next();

}
long end = System.currentTimeMillis();
System.out.println(end - start);
}

// テスト用コントロールメソッド
// 引数はコレクションの要素の個数
// 例# java CollectionDemo 100000
public static void main(String[] args) {
int MAX = Integer.parseInt(args[0]);
CollectionDemo container = new CollectionDemo();

// ArrayList 型オブジェクト
Collection obj = new ArrayList();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// LinkedList 型オブジェクト
obj = new LinkedList();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// HashSet 型オブジェクト
obj = new HashSet();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// TreeSet 型オブジェクト
obj = new TreeSet();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// LinkedHashSet 型オブジェクト
obj = new LinkedHashSet();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);

// PriorityQueue 型オブジェクト
obj = new PriorityQueue();
container.addElapsedTime(obj, MAX);
container.getElapsedTime(obj);
}
}

Enhanced For Loop

最後に、イテレーションの部分を拡張 For 文に書き換えてみます。

	// イタレーションによる要素の取り出し
public void getElapsedTime(Collection<Integer> container) {
long start = System.currentTimeMillis();
int sum = 0;
// 要素についての繰り返し(拡張 For 文の利用)
// Auto-UnboxingによりInteger型は顕には記述しない
for (int i: container) {
sum += i;
}

long end = System.currentTimeMillis();
System.out.println(end - start);
}
C:\java>javac CollectionDemo3.java

C:\java>javac -Xlint:unchecked CollectionDemo3.java

C:\java>java CollectionDemo3 1000000
java.util.ArrayList
0, 78, 172, 235, 266, 391, 422, 532, 563, 578, 610
47
java.util.LinkedList
15, 78, 125, 156, 187, 234, 406, 484, 515, 578, 812
47
java.util.HashSet
0, 156, 312, 406, 750, 875, 922, 1016, 1187, 1344, 1437
157
java.util.TreeSet
0, 156, 390, 515, 656, 781, 922, 1047, 1218, 1359, 1500
62
java.util.LinkedHashSet
16, 172, 297, 641, 1125, 1235, 1344, 1438, 1766, 2610, 2719
234
java.util.PriorityQueue
0, 78, 125, 203, 219, 235, 282, 297, 360, 360, 375
47

C:\java>

[Quote]:http://www.nextindex.net/java/collection/Collections50.html

| BLOG TOP |
DATE: CATEGORY:Java note

クラス修飾子

クラスにもここで挙げた全ての修飾子を指定することが出来ます。但し、修飾子ごとに指定できるクラスの形式が異なっているので少々複雑です。

クラスは内部に別のクラスを定義することも可能です。クラスの内部に宣言したクラスを内部クラスと呼び、一番外側のクラスとは異なった扱いを受けます。

一番外側のクラス

一番外側のクラスには public だけが指定可能です。但し、ソースファイル (*.java) の中で public クラスは一つでなければならず、クラス名とソースファイル名を一致させる必要があります。

アクセス修飾子を指定しないクラスは、同じパッケージ内のクラスからしか参照できませんが、 public クラスはあらゆるクラスから参照できます。ですから、アクセスを制限したいクラスに対して他のクラスからの参照を仲介する為の出入り口として public クラスを定義することができます。

次のサンプルでは、アクセス修飾を指定していないクラス Test を、他のパッケージから利用するために、public 修飾子を指定したクラス ACTest を作成しました。ソースファイル名は ACTest.java であることが必要です。

ACTest.java:

// 一番外側のクラス
class Test {
String name;
}
// 一番外側のクラス
public class ACTest extends Test {
// Test クラス型変数をメンバーとして定義
private Test obj;
// obj にインスタンスをセットするメソッド
public void setName(String str) {
// Test クラスをインスタンス化し、
// Test クラス型変数 obj に Test クラス型オブジェクトの参照をセット
obj = new Test();
// Test クラス型オブジェクトの変数 name にメソッド引数 str をセット
obj.name = str;
}
// obj オブジェクトの name 変数を返すメソッド
public String getName(){
// Test クラス型オブジェクトの name 変数を返す
return obj.name;
}
}

このソースコードを格納した *.java ファイルの名前は、 ACTest.java であることが必要です。

C:\Java>javac ACTest.java
C:\Java>

クラスのメンバーであるクラス

クラスに属し、クラス/オブジェクトと共に持続し続ける要素を、クラスのメンバーと呼びます。メンバーはサブクラスに継承されえる要素です。 Java 言語仕様でクラスのメンバーとして許される要素は、クラス、インタフェース、フィールド及びメソッドが定義されています。

protected, private はその定義上、クラスには指定できなそうな感じですが、クラスのメンバー としてあらわれるクラス (member class) に対しては指定可能です。

メンバークラスに関しては後で詳しく説明しますが、他のクラス内部に宣言されたクラスのことです。但し、クラスのメソッド内部に書かれた内部クラスはメンバークラスではありません。

次のサンプルは、本節までではまだ扱っていない知識を使っています。

// 一番外側のクラス
class EnclosingClass {
// EnclosingClass のメンバークラス
private class MemberClass {
// MemberClass のメンバークラス
private class InnerClass {
private String name;
public void setName(String str) {
name = str;
}
}

// MemberClass のメソッド
public void setName(String str) {
InnerClass obj = new InnerClass();
obj.setName(str);
}
}

// EnclosingClass のメソッド
public void setName(String str) {
MemberClass obj = new MemberClass();
obj.setName("Tochihara");
}
}
C:\Java>javac EnclosingClass.java
C:\Java>

[Quote]:http://www.nextindex.net/java/permitmod.html

| BLOG TOP |
DATE: CATEGORY:Java note

以上見てきたとおり、コーディング時に想定されていない状況で実行されたときには例外が発生します。この例外はオブジェクトですから、元になる例外クラスを明示的にインスタンス化して例外オブジェクトを作ることができます。

全ての例外は java.lang.Exception のサブクラスであり、各々のパッケージで利用されているクラスに応じて継承されています。そして、インタフェースで例外が発生すると定義されている場合などに、プログラマが例外クラスを明示的にインスタンス化してオブジェクトを throw することがあります。

Exception クラスのコンストラクタ

Exception()
Exception(String s)

二つ目のコンストラクタでは、メッセージを指定することが出来ます。

ExcepTest.java:

class Msg {
private String msg;
void setMsg(String arg) throws Exception {
if (!arg.equals("こんにちは")) {
Exception excepObj = new Exception("挨拶がなっていない!");
throw excepObj;

} else {
msg = arg;
}
}
String getMsg() {
return msg;
}
}
class ExcepTest {
public static void main(String[] args) {
Msg obj = new Msg();
try {
obj.setMsg("こんにちは");
System.out.println(obj.getMsg());
} catch (Exception e) {
System.out.println(e);
}
try {
obj.setMsg("さようなら");
System.out.println(obj.getMsg());
} catch (Exception e) {
System.out.println(e);
}
}
}

Msg クラスに定義した setMsg() は、メソッド引数が「こんにちは」ではない場合には例外を返します。

このクラスを ExcepTest クラスの main() メソッドでインスタンス化しています。

C:\Java\Excep>javac ExcepTest.java
C:\Java\Excep>java ExcepTest
こんにちは
java.lang.Exception: 挨拶がなっていない!

[Quote]:http://www.nextindex.net/java/exceptObj.html

| BLOG TOP |

copyright © Manhattan life all rights reserved.Powered by FC2ブログ