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 基礎
JREJDK はどう違うのですか?

JRE, JDK はそれぞれ Java Runtime Environment, Java Development Kit の略で、
前者は、JDK をベースに作られた Java のプログラムを実行する際に必要になる JVMと
クラスライブラリのパッケージで、後者は、開発者向けのコンパイラなどのツールと
クラスライブラリのパッケージです。
Java 2以降では、JDKをSDK(Software Development Kit)と呼ぶようになりました。
SDKにはJREが含まれているので、SDKを導入した開発者は別途JREを入手して導入する
必要はありません。
また、JRE は自分の作成したアプリケーションと共に再配布することが可能です。

[Quote]:http://64.233.167.104/search?q=cache:e_vXuWejgWYJ:javafaq.jp/S000.html+JRE+JDK&hl=en&ct=clnk&cd=1&gl=us&lr=lang_en%7Clang_ja&client=firefox-a
| BLOG TOP |
DATE: CATEGORY:Java 基礎

浮動小数点数の限界

Java では小数は IEEE 754 規格の浮動小数点数で扱います。この場合、2進数の特徴として、期待していた値が厳密には求まらない場合があります。

例えば、 "0.1" という数値は IEEE 754 の 2進数では次のようにあらわされます:

1001100110011001100110011001100110011001100110011010

10進数の分数で表現すると、次のような無限級数になります:

1/10 = 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + ...

つまり、0.1 は浮動小数点数に対応する値が存在せず、厳密に正しい値では表現できないのです。この例のように、途中で計算を打ち切ることで生じる、厳密な値との誤差を 打切り誤差と呼びます。一般に、算術計算では切り捨て/四捨五入/切り上げが必要になることが殆どで、そのために生じる誤差を丸め誤差と呼びます。精密な 値が必要な場合は、丸め誤差モードを何にするのか、有効数字として何桁必要なのかといったことに自覚的である必要があります。

このような問題を解決するために、小数に 10 を乗じて整数として計算し、結果を 10 で割るとなどのテクニックがよく使われます。

BigDecimal クラスはそのような問題を解決するために、10 進数値を文字列として扱います。通常の基本データ型の計算に比べてパフォーマンスが落ちるのですが、お金の計算など、厳密に正しい数値が欲しい場合に好んで使われます

継承階層

java.lang.Object
|
+--java.lang.Number
|
+--java.math.BigDecimal

概要

API 仕様書では次のように説明されています:

変更が不可能な、任意精度の符号付き 10 進数です。BigDecimal は、任意精度の「スケールなしの整数値」と、小数点以下の桁数を表す負でない 32 ビット整数の「スケール」で構成されます。BigDecimal で表される数値は (unscaledValue/10scale) です。BigDecimal は、基本算術、スケール操作、比較、ハッシング、および書式変換の演算を提供します。

コンストラクタ

BigDecimal(BigInteger val)BigInteger を BigDecimal に変換します。
BigDecimal(BigInteger unscaledVal, int scale)BigInteger のスケールなしの値と int スケールを BigDecimal に変換します。
BigDecimal(double val)double を BigDecimal に変換します。
BigDecimal(String val)BigDecmal の String 表現を BigDecimal に変換します。

メソッド

メソッドは数が多いのですべては紹介しません。主として、数値計算用のメソッド、基本データ型への変換のメソッドが用意されています。

修飾子戻り値メソッド名概要
publicBigDecimaladd(BigDecimal val)この BigDecimal に val を加算
publicBigDecimalmultiply(BigDecimal val)この BigDecimal に val を乗算
publicBigDecimaldivide(BigDecimal val,
int roundingMode)
この BigDecimal に val を除算。round にはこのクラスで定義されているフィールドを指定して、丸めモードを指定する。

サンプル

基本データ型を使った例

最初に、基本データ型を使ったアプリケーションを示して、問題を発生させます:

FpcDemo1.java:

// (cents, 個数) ペア用のレコード型
class Rec {
double cents;
int count;

// 小数は基本データ型で保持
Rec(double cents, int count) {
this.cents = cents;
this.count = count;
}
}

class FpcDemo1 {

// レコードのセット
static Rec values[] = {
new Rec(0.01, 1),
new Rec(0.05, 3),
new Rec(0.10, 7),
new Rec(0.25, 3),
new Rec(0.50, 4)
};

public static void main(String args[]) {
double sum = 0.0;

// Rec 型のフィールド cents*count の加算
for (int i = 0; i < values.length; i++) {
Rec r = values[i];
sum += r.cents * r.count;
}

// 合計を表示
System.out.println("sum = " + sum);
System.out.println("sum - 3.61 = " + (sum - 3.61));
}
}
C:\Java>javac FpcDemo1.java

C:\Java>java FpcDemo1
sum = 3.6100000000000003
sum - 3.61 = 4.440892098500626E-16

C:\Java>

簡単な計算であり、期待値としては 3.61 であって欲しいのですが、わずかですが異なっています。 IEEE 756 規格浮動小数点数で表現できる限界で誤差が発生しています。

BigDecimal を使った例

FpcDemo.java:

import java.math.BigDecimal;

// (cents, 個数) ペア用のレコード型
class Rec {
String cents;
int count;

// 小数は文字列で保持
Rec(String cents, int count) {
this.cents = cents;
this.count = count;
}
}

class FpcDemo {

// レコードのセット
static Rec values[] = {
new Rec("0.01", 1), // 小数を文字列でセット
new Rec("0.05", 3),
new Rec("0.10", 7),
new Rec("0.25", 3),
new Rec("0.50", 4)
};

public static void main(String args[]) {
// 加算結果も BigDecimal で保持
// 桁数を小数点以下2桁に設定: "0.00"
BigDecimal sum = new BigDecimal("0.00");

// BigDecimal を使用して、合計値を計算
for (int i = 0; i < values.length; i++) {
Rec r = values[i];

// cents を BigDecimal 型に
BigDecimal cents = new BigDecimal(r.cents);
// 個数を BigDecimal 型に
BigDecimal count = new BigDecimal(r.count);
// BigDecimal 型の計算
// sum = sum + cents*count
sum = sum.add(cents.multiply(count));
}

// 合計値を表示
System.out.println("sum = " + sum);
}
}
C:\Java>javac FpcDemo.java

C:\Java>java FpcDemo
sum = 3.61

C:\Java>

期待したとおりの値が出力されたほかに、不要な0が表示されていない事に注目してください。 BigDecimal 型オブジェクト sum を初期化したときに "0.00" を指定したので、小数点以下2桁だけが表示されているのです。 "0.000" で初期化すれば、小数点以下第3位まで表示されるようになりますので試してみると良いでしょう。


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

| BLOG TOP |
DATE: CATEGORY:Java 基礎

真偽値 (true/false) を表す基本データ型である boolean 型のラップクラスです。

クラス階層

java.lang.Object
|
+--java.lang.Boolean

概要

API 仕様では次のように説明されています:

Boolean クラスは、プリミティブ型 boolean の値をオブジェクトにラップします。Boolean 型のオブジェクトには、型が boolean の単一フィールドが入ります。

さらにこのクラスは、booleanString に、Stringboolean に変換する各種メソッドや、boolean の処理時に役立つ定数およびメソッドも提供します。

コンストラクタ

Boolean(boolean value) value 引数を表す Boolean オブジェクトを割り当てます。
Boolean(String s) 文字列引数が null ではなく、文字列 "true" に等しい (大文字と小文字は区別しない) 場合は、値 true を表す Boolean オブジェクトを割り当てます。

つまり、 Boolean クラスは boolean 型の変数/値、または文字列 true または他の文字列を受け取って、オブジェクトを作ります。

メソッド

メソッド、メンバ変数については、少数なので全て紹介します。詳細は API 仕様を直接ご確認ください。

修飾子戻り値型メソッド概要
 booleanbooleanValue() この Boolean オブジェクトの値をプリミティブ boolean 型として返します。
 booleanequals(Object obj) 引数が null ではなく、このオブジェクトと同じ boolean 値を表す Boolean オブジェクトの場合にだけ、true を返します。
staticbooleangetBoolean(String name) 引数によって指定されたシステムプロパティが存在し、それが文字列 "true" に等しい場合にだけ、true を返します。
 inthashCode() この Boolean オブジェクトのハッシュコードを返します。
 StringtoString() この Boolean 値を表す String オブジェクトを返します。
staticBooleanvalueOf(String s) 指定された String が表す値を持つ Boolean を返します。

boolean 型は truefalse しか値をもち得ないので、メソッドも簡単です。

サンプル

class TestBoolean{
public static void main(String args[]){
//インスタンス化
Boolean objBln1=new Boolean(true);
Boolean objBln2=new Boolean("uso");

System.out.println("objBln1: "+objBln1.booleanValue());
System.out.println("objBln2: "+objBln2.booleanValue());

System.out.print("objBln1 かつ objBln2: ");
System.out.println(objBln1.equals(objBln2));
}
}

インスタンス化の際に、オーバーロードされたコンストラクタを二つとも使っています。一つは引数に boolean 型の値をとり、もう一つは文字列型を取ります。

C:\Java>javac TestBoolean.java

C:\Java>java TestBoolean
objBln1: true
objBln2: false
objBln1 かつ objBln2: false


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

| BLOG TOP |
DATE: CATEGORY:Java 基礎

Java では基本データ型が決まっています。これらの変数や値(リテラル)をオブジェクトとして保持する為のクラスも用意されています。基本データ型の変数やリテラルをオブジェクトとして包んでしまうので、ラップクラスと呼ばれます。

基本データ型クラスAPI 仕様による概要
byteByte Byte クラスは、byte 値の標準ラッパーです。
shortShort Short クラスは short 値の標準ラッパーです。
intInteger Integer クラスは、プリミティブ型 int の値をオブジェクト内にラップします。Integer 型のオブジェクトには、型が int の単一のフィールドが入ります。
longLong Long クラスは、プリミティブ型 long の値をオブジェクト内にラップします。Long 型のオブジェクトには、型が long の単一フィールドが入ります。
charCharacter Character クラスは、プリミティブ型 char の値をオブジェクトにラップします。Character 型のオブジェクトには、型が char の単一フィールドが入ります。
floatFloat Float クラスは、プリミティブ型 float の値をオブジェクト内にラップします。Float 型のオブジェクトには、float 型の単一のフィールドがあります。
doubleDouble Double クラスは、プリミティブ型 double の値をオブジェクトにラップします。型 double のオブジェクトには、型が double の単一フィールドが入ります。
booleanBoolean Boolean クラスは、プリミティブ型 boolean の値をオブジェクトにラップします。Boolean 型のオブジェクトには、型が boolean の単一フィールドが入ります。

byte 型から long 型までが整数値を表し、これに文字型 char を加えたものが整数型と呼ばれます。 floatdouble は浮動小数点数を表し、 boolean 型はブーリアン型(論理型)を表します。ここではラップクラス全ての説明はせずに、 Integer, Character, Double, Boolean を説明します。

API 仕様が公開されているので、それを確認するのが一番です。
[Quote]:http://www.nextindex.net/java/class/wrapped.html

| BLOG TOP |
DATE: CATEGORY:Java 基礎

private

アクセス修飾子の中で最もきついのが private です。クラスの private 修飾子が付されたメンバーは、当該クラス内からしかアクセスできません。内部クラスからは参照可能であり、同じクラスからインスタンス化されたオブジェクトからは相互に参照できます。

アクセス修飾子は、制限を弱める方向でオーバーライド可能です。例外として、private 修飾されたフィールドはオーバーライド不可なのですが、現実的には同じシグネチャ(メソッド名と引数の組)のメソッドをサブクラスで定義可能です。

これがいったいどういうことなのか以下で説明します。

final

final は、継承によってオーバーライドできないメンバーを宣言する修飾子です。private なメンバーは、自動的に final です。同じクラス内からのみアクセスが許されているので、継承するサブクラスからもアクセスできません。したがって、言語仕様上、継承によりオーバーライドすることはできず、本質的に final となるのです。

Java では、継承でオーバーライドできるメンバーは、アクセス可能なものに限られ、private なメンバーは、外部の一切のクラスからアクセス不可能なのでオーバーライドできないのです。

言語仕様として、private なメンバーはオーバーライドできないことを覚えてください。

オーバーライドと隠蔽と private

private なメンバーはオーバーライドされせん。同一クラス内からしかアクセスできないので、サブクラスで継承するオーバーライドの概念にあわないからです。しかし、アクセスできないため、まったく新たなメンバーとして定義可能です。

オーバーライドとは、「スーパークラスで定義されているメソッドと、同じメソッド名と同じシグネチャを持つメソッドをサブクラスで定義する」ことです。このとき、次の条件の何れかを満たさなければコンパイルエラーになります。

  • 戻り値型が一致しなければならない
  • throws 節が競合してはならない
  • アクセス修飾子は、同じか、アクセス制限を緩めるものでなければならない

static 修飾されているメソッドに関しては、更に次の条件が与えられます。

  • スーパークラスの static メソッドをサブクラスの static メソッドで再定義することを隠蔽と呼ぶ
  • static メソッドがインスタンスメソッドを隠蔽するとコンパイルエラーとなる
  • インスタンスメソッドが static メソッドを隠蔽するとコンパイルエラーとなる

スーパークラスの private メソッドをサブクラスで再定義するとき、オーバーライドや隠蔽 (hide) の条件を満たす必要が無く、完全に自由にメソッドを再定義可能です。

インライン化

privatestatic なメソッドは、インライン化される可能性があります。インライン化とは、オブジェクトのメソッドへの参照を持つ代わりに、当該メソッドそのものをメモリの 連続領域に展開することです。ポインタを経由することを省くので、パフォーマンスが向上します。但し、JVM が実行時にそうしても良いというだけなので、必ずインライン化されるわけではありません。インライン化するだけのメモリの余裕がある場合に、そのほかのリ ソースの使用率と相談した上で、 JVM が動作を変更します。

メンバーの private 修飾

フィールドの private

メンバー変数であるフィールドは、原則として全て private にします。

クラス外部からのアクセスは、アクセス用のメソッドを公開します。このメソッドをアクセッサー(ゲッターとセッター)と呼びます。

PrivateFieldDemo.java:

class PrivateField {
private String name;
PrivateField(String aName) {
name = aName;
}
public String getName() {
return name;
}
public void setName(String aName) {
// 同じクラスだからアクセス可能
name = aName;
}
public void setName(PrivateField obj, String aName) {
// 別のオブジェクトでも同じクラスだからアクセス可能
obj.name = aName;
}
}
class PrivateFieldDemo {
public static void main(String[] args) {
PrivateField obj1 = new PrivateField("suzuki");
PrivateField obj2 = new PrivateField("tochihara");

System.out.println("obj1.name(): " + obj1.getName());
System.out.println("obj2.name(): " + obj2.getName());
obj1.setName("hiroe");
obj1.setName(obj2, "sekiya");
System.out.println("obj1.name(): " + obj1.getName());
System.out.println("obj2.name(): " + obj2.getName());
}
}

実行結果:

C:\java>javac PrivateFieldDemo.java
C:\java>java PrivateFieldDemo
obj1.name(): suzuki
obj2.name(): tochihara
obj1.name(): hiroe
obj2.name(): sekiya
C:\java>

メソッドの private

private なメンバーはオーバーライド不可です。しかし、サブクラスで同じシグネチャ(メソッド名と引数の組)のメソッドを定義することが可能で、現象的にはオー バーライドと同じですが、まったく新しいメソッドを別途定義していることになるため、オーバーライドの制約を一切受けません。

PrivateOverrideDemo.java:

class PrivateSuper {
private String msg = "Bye";
private String getPrivateMsg() {
return msg;
}
}
class PrivateOverride extends PrivateSuper{
private String msg = "Hello";
private String getPrivateMsg() { // private メソッドのオーバーライドのように見える
// String str = super.msg; // javac Error
// String str = super.getPrivateMsg(); // javac Error
String str = msg;
return str;
}
public String getMsg() {
return this.getPrivateMsg();
}
}
class PrivateOverrideDemo {
public static void main(String[] rags) {
PrivateOverride obj = new PrivateOverride();
// System.out.println(obj.getPrivateMsg()); // javac Error
System.out.println(obj.getMsg());
}
}

コンストラクタの private

コンストラクタは、クラスがインスタンス化されるときに必ず呼び出されるもので、クラスのメンバーでは在りません。コンストラクタはインスタンス化される前に呼び出されるので、自動的に static です。

コンストラクタを private 修飾する場合を考えましょう。private は他のクラスからは一切アクセス不能なので、private コンストラクタしか持たないクラスはインスタンス化不能に思われます。しかし、そうではないのです。

コンストラクタを private にするメリットは、他のコードが勝手にインスタンス化したオブジェクトを生成できなくすることです。このオブジェクトを取得する仕組みとして、ファクトリメソッドを用意することが考えられます。具体的には、private static なフィールドに自分のインスタンスを用意して、getter メソッドを介して取得します。

class SingletonDemo {
private static SingletonDemo obj = new SingletonDemo();

private SingletonDemo() {
// 適当な初期化
}

public Singleton getSingletonInstance() {
return obj;
}
}

フィールド(クラスのメンバーである変数)に定義されたオブジェクトは、static 宣言されているので、クラスのロード時にただ一回だけ実行されます。従って、クラスが何度参照されようとも、ただ一回だけ初期化され、生成されるインスタ ンスも、一つの JVM で唯一つだけに制限されます。


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

| BLOG TOP |

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