Javaの文法

Javaの文法の最新ニュースをまとめて検索!

Java文法はJavaプログラムを記述し解釈する方法を定義するルールの集合である。

目次

[編集] データ構造

Javaは配列文字列を扱うため専用の文法を持ってはいるが、配列と文字列は基本型ではない: それらはjava.lang.Objectに代入できる参照型である。

[編集] 基本型

整数型
byte 8-bit 符号付き
short 16-bit 符号付き
int 32-bit 符号付き
long 64-bit 符号付き
  • 整数の基本型は例外等は出さずにオーバフローする。例えば、Integer.MAX_VALUE(=231 − 1)に1を加えると、結果はInteger.MIN_VALUE(= −231)になる。
浮動小数点数
float 32-bit 符号付き
double 64-bit 符号付き
  • 浮動小数点数は決して例外をスローしない
  • 0でない値を0(ゼロ)で割った値はInf(無限大)と等値である
  • 無限大でない値をInfで割った値は0(ゼロ)と等値である。
文字
char 16-bit 符号無しUnicode
  • J2SE v 1.4.2までのcharは基本多言語面 (BMP) の範囲内のコードポイントを表現する。
  • J2SE 5.0からは、補助文字をサポートするため、charはUTF-16符号化形式のコード単位に変更され、コードポイントはintに変更された(JSR#204)[1]。但しchar型は互換性の問題からあくまで符号無し16-bitのままとされたので、補助文字を扱う場合はコードポイント一つにchar値のペアが対応する[2]。これらを適切に取り扱う便宜として、StringクラスやプリミティブラッパークラスであるCharacterクラスなどの各種メソッドが利用できる。
ブール型
boolean true または false
  • C/C++や類似の言語と異なり、Javaではfalseの代わりに0(ゼロ)またはnullと書くことはできない
  • 同様に、0でない値を書いてtrueの代わりとすることはできない
  • ブール型をブール型でない基本型へキャストすることとその逆はできない
プリミティブラッパークラス
使用法
  • ある型の値を他の型へ変換するために使うことができる
  • 基本型を参照を使って渡す用途で使用できる
その他
  • メソッドへは値渡しとなる。
  • ブール型以外の基本型の初期値は0。ブール型の初期値はfalse。ラッパークラス(およびObjectクラスに属する全クラス)の初期値はnull。

[編集] リテラル

整数
8進数 0365, 0[0..7]*
16進数 0xF5, 0x[0..9, A..F, a..f]*
10進数 245, [1..9][0..9]*
浮動小数点数
float 23.5F, 23.5f; 1.72E3F, 1.72E3f, 1.72e3F, 1.72e3f
double 23.5, 23.5D, 23.5d; 1.72E3, 1.72E3D, ...
文字リテラル
char 'a', 'Z', '\u0231'
文字列リテラル
String "Hello, world"
エスケープシーケンス
Unicode文字 \u 16進数Unicode文字を表現するときに使用する
タブ文字 \t
後退(Backspace)文字 \b
キャリッジリターン(復帰文字) \r
改ページ \f
バックスラッシュ \\
シングルクォーテーション(単一引用符) \'
ダブルクォーテーション(二重引用符) \"
ラインフィード(改行文字) \n

[編集] 文字列

文字列

  • Stringオブジェクトは不変(変更不能)である
  • Stringオブジェクトは生成時に初期化されなければならない
  • コンパイラは文字列リテラル(ダブルクォーテーションで囲まれた文字列)を見つけると、Stringオブジェクトを生成する
  • 演算子 "+" と "+=" は文字列を連結するためにオーバーロードされる
String str1 = "alpha"; 
String str2 = new String("alpha");

StringBufferとStringBuilder

  • StringBufferStringBuilderオブジェクトは可変(変更可能)なので、オブジェクト生成オーバヘッド無しで柔軟に文字列を生成・変更できる。StringBufferとStringBuilderの違いは、StringBufferがマルチスレッドに対応している(=スレッド・セーフである)のに対し、StringBuilderは対応していないことである。
  • StringとStringBufferは互いに独立であり、一方から派生したものではない
StringBuffer str1 = new StringBuffer("alpha");
str1.append("-meta");
str1.setCharAt(str1.indexOf("m"), 'b');
System.out.println(str1);     //str1.toString() を呼び出す。
                              //印刷結果は"alpha-beta"となる

[編集] 配列

  • Javaは基本型クラスインタフェースそれぞれの配列型はもちろん、配列の多次元配列をも持つ。
  • すべての配列要素は同じ型を引き継がなければならない。
  • すべての配列クラスはクラスjava.lang.Objectを引き継ぎ、そこに含まれる型階層を反映する。
  • 配列オブジェクトは配列要素の数を表す読み取り専用の属性「length」を持つ。
  • 配列は実行時に領域確保されるので、配列を生成する際の要素数として変数を書くことができる(この点例えばC言語では定数しか書けない)。
  • Javaにおける配列は一次元である。多次元配列はサポートされているが、配列の配列として扱われる。
// 配列を宣言 - 配列名は「myArray」、 要素の型は "SomeClass" への参照
SomeClass[] myArray = null;
// 配列を生成
myArray = new SomeClass[10];
// または宣言と生成を同時に行う
SomeClass[] myArray = new SomeClass[10];
// 配列の要素を割り当てる (ただし、基本型の配列なら必要ない)
for (int i = 0; i < myArray.length; i++)
    myArray[i] = new SomeClass();

[編集] 国際化サポート

Javaはbyte文字型とを区別する。文字は内部的にはUCS-2で表現されるが、J2SE 5.0以降においては、内部表現としてUTF-16とそのサロゲートもサポートされる。したがってJavaプログラムのソースには、あらゆるUnicode文字を記述できる。

ゆえに、次の例はJavaのコードとして完璧に有効である。ここではクラス名、変数名、および文字列リテラルとして日本語の文字を使っている:

public class こんにちは世界 {
    private String 文字列 = "こんにちは世界";
}

[編集] 演算子

[編集] 算術演算子

二項演算子
文法 意味
+ 加算
- 減算
* 乗算
/ 除算
% 剰余 (整数の余りを返す)
単項演算子
文法 意味
- 単項マイナス (符号反転)
++ インクリメント (変数の前か後につけることができる)
-- デクリメント (変数の前か後につけることができる)
! ブール補数演算
~ ビット単位反転
(型名) キャスト

[編集] 代入演算子

文法 意味
= 代入
+= 加算と代入
-= 減算と代入
*= 乗算と代入
/= 除算と代入
%= 剰余と代入
&= ビット演算 ANDと代入
|= ビット演算 ORと代入
^= ビット演算 XORと代入
<<= 左シフト(ゼロ埋め)と代入
>>= 右シフト (符号拡張)と代入
>>>= 右シフト (ゼロ埋め) と代入

[編集] 関係演算子

文法 意味
==
!=
>
>=
<
<=
instanceof - のインスタンス

関係演算子(==!=)を参照型に対して用いた場合、そこで比較されるのは参照先のオブジェクトが同じかどうかであり、オブジェクトの中身の値が一致するか否かではない。オブジェクトの中身を比較したい場合は.equals(Object)メソッドを使用する。instanceof演算子は或るオブジェクトが或るクラスのインスタンスであるか否かを判定するために用いる。

[編集] 三項演算子

三項演算子は二つの記号?:を組み合わせて記述する。条件演算子とも呼ぶ。構文:

条件 ? 式1 : 式2

条件がtrueであるとき、式1の値をとる。そうでない場合は式2の値をとる。

例:

String answer = (p < 0.05) ? "reject": "keep";
// これは以下のコードと等価である:
String answer;
if (p < 0.05){
  answer = "reject";
}else{
  answer = "keep";
}

[編集] 論理演算子

  • 短絡評価論理演算(結果が判定するまでオペランドを左から右へと評価する)
  • 必要最小限の式しか評価しない
  • 部分的な評価 (完全な評価ではない)
文法 意味
&& AND (左のオペランドがfalseのとき、式はfalseを返し、右のオペランドは評価されない)
|| OR (左のオペランドがtrueのとき、式はtrueを返し、右のオペランドは評価されない)
! NOT (論理否定)

(訳注: 上の通り、&&と||は左のオペランドしか評価しない可能性がある。これに対し、ビット演算子にも挙げられている&と|を代わりに書いた場合は、左右のオペランド両方が完全に評価される。実用上は&&と||を用いるのが一般的である)

[編集] ビット演算子

二項演算子
& AND (論理演算子としても使用可。その場合両辺が完全に評価される)
| OR (論理演算子としても使用可。その場合両辺が完全に評価される)
^ XOR
<< 左シフト (ゼロ埋め)
>> 右シフト (符号拡張)
>>> 右シフト (ゼロ埋め)
単項演算子
~ NOT (ビット反転)

[編集] 文字列演算子

Syntax Meaning
+ 連結
+= 連結と代入

[編集] 制御構造

[編集] if ... else

if (expr) {
    statements;
}
else if (expr) {
    statements;
}
else {
    statements;
}
  • exprは真偽値を与えなければならない。したがって例え"if(String a1 == String a2)"の中身の値が等しくても真とはならない。何故ならこの式は真偽値ではなく参照型としてのa1とa2の値を比較するからである。このような場合には、替わりに"if(String a1.equals(String a2))"と書くか、または何らかの比較用のインスタンスを用いる必要がある。

(訳注: 上記文章では、「関係演算子」の節で述べている事柄であると考えられる。)

[編集] switch文

switch (expr) {
case VALUE: 
    statements;
    break;
case VALUE: 
    statements;
    break;
default:
    statements;
    break;
}
  • expr値はbyte, short, int またはchar型でなければならない。
  • 各々のcase値はユニークなリテラル値でなければならず、変数を書くことはできない。

[編集] forループ

for (initial-expr; cond-expr; incr-expr) {
    statements;
}

[編集] for-each ループ

J2SE 5.0では、for-each文と呼ばれる新機能が追加された。これは集合の中の全要素を順番に参照するような処理を大いに簡素化する。このような場合、従来は次の例に示すような反復子(iterator)を書かねばならなかった:

public int sumLength(Set<String> stringSet) {
    int sum = 0;
    Iterator<String> itr = stringSet.iterator();
    while (itr.hasNext()) {
        sum += itr.next().length();
    }
    return sum;
}

for-each文はこのメソッドを大いに簡素化する:

public int sumLength(Set<String> stringSet) {
    int sum = 0;
    for (String s : stringSet) {
        sum += s.length();
    }
    return sum;
}

この例の動作としては、stringSetに含まれる全てのStringについて、長さを取得してsumに加算する。

[編集] whileループ

while (expr) {
    statements;
}

[編集] do ... while

do {
    statements;
} while (expr);

[編集] 分岐命令

文法 意味
break; 最も深いループから直ちに脱出する。
continue; ループの現在の回を中断し、次の回の冒頭に移る。
break LABEL ラベル付き文の実行を中断し、ラベル付き文の直後の文に移る。
continue LABEL ラベル付きの文にジャンプする(ラベル付きの文またはラベル付きループを冒頭から再開する)

[編集]

int sum = 0;
for (int i = 1; i < 10; i++) {
    if (i == 3) {
        continue;  //このループの残りをスキップしforに戻る。
    }
    sum += i;
 
    if (sum > 15) {
        break;  // ループを脱出する。
    }
}

(訳注:原文のサンプルのバグを修正した。)

[編集] ラベル

  • 末尾にコロンがついた識別子からなる
  • 分岐命令が参照する文またはブロックを識別するために使われる。
  • 仮にラベルを外したとすると、分岐命令は最も内側のループについて機能する。

LABEL1: statement;
LABEL2: { statements; }

[編集] 注、"goto" 文について

"goto" 文はJavaの予約語であるが、Javaでは機能しない。

[編集] オブジェクト

[編集] クラス

Javaでは別のクラスやインタフェース内部で宣言された「ネスト」されたクラスを作ることができる。ネストされていないクラスは「トップレベル」クラスと呼ばれる。非staticなネストされたクラスのことは「内部クラス」と呼ぶ。

クラスを宣言する際は以下の修飾子を付けることができる:

  • abstractインスタンス化できない。インタフェースとabstract(抽象)クラスだけがabstract(抽象)メソッドを持つことができる。抽象クラスを継承する具象(非abstract)サブクラスは、引き継がれた全ての抽象メソッドを、abstractでないメソッドでオーバーライドしなければならない。修飾子finalと併用することはできない。
  • final – サブクラスを作らせない。 finalクラスのすべてのメソッドは無条件にfinalになる。 修飾子abstractと併用することはできない。
  • strictfp – このクラスとそこに含まれる全てのネストクラスにおいて、全ての浮動小数点演算は厳密な浮動小数点演算動作を使用する。厳密な浮動小数点演算動作は、演算結果がプラットフォームに関わりなく同一となることを保証する。

Javaのクラスはセミコロン(";")で終わらせる必要はない点に注意。この点はC++の文法と異なる。

[編集] 継承

// 子クラスは親クラスを継承する
class ChildClass extends ParentClass { ... }  
  • 任意のクラスのデフォルトの親クラスはObjectクラスである。
  • あるクラスは単一の親クラスだけを継承できる(実装多重継承はできない)。

[編集] スコープ

  • this – 現在のサブクラス(デフォルト)への参照(例:this.someMethod())。
  • super – 親クラスへの参照(例:super.someMethod())。サブクラスがオーバライドした親クラスのメソッドや、サブクラスが継承しつつも隠蔽した親クラスのフィールドにアクセスするために使うことができる。

[編集] インタフェース

インタフェースとは、実装の詳細がいっさいない抽象クラスである。その目的は複数のクラスの用途をまとめて定義することにある。共通のインタフェースを実装する複数のクラスは、そのインタフェース型のコンテキストにしたがって互いに交換可能とすることができる。インタフェースはまた、抽象化 – クラスの実装方法を隠蔽すること – という考え方を強制するのにも役立つ。

インタフェースは抽象メソッドとstatic finalフィールドだけを含むことができる。インタフェースメソッドはデフォルトでpublicかつabstractであり(実装を持たない)、インタフェースフィールドはデフォルトで public static final である。

Javaは完全な直交多重継承はサポートしていない。C++における多重継承には、複数の親クラスや型から複数回継承したフィールドやメソッドを識別するための複雑なルールが伴う。インタフェースを実装から分離することにより、インタフェースはより単純かつ明快に多重継承が持つ利点の多くを提供する。もっとも、多重継承を避ける代価としてコードは若干冗長になる。というのは、インタフェースはクラスのシグネチャを定義するのみで実装を持てないため、インタフェースを継承する全てのクラスは定義されたメソッドをいちいち実装しなければならないからである。純粋な多重継承であれば実装自体も継承されるのでこのようなことはない。

Javaのインタフェースは Objective-C規約のコンセプトによく似た振る舞いをする。

[編集] インタフェースの実装

クラスは、一つのクラスを継承できるのに加えて、implementsキーワードを用いて一つ以上のインタフェースを実装することができる。

interface MyInterface {
    void foo();
}
interface Interface2 {
    void bar();
}
class MyClass implements MyInterface {
    void foo() {...}
    ...
}
class ChildClass extends ParentClass implements MyInterface, Interface2 {
    void foo() {...}
    void bar();
    ...
}

以下の例では、

public interface Deleteable {
    void delete();
}

Deleteableインタフェースを実装する非abstractクラスは、引数無しで戻り型がvoidであるdeleteという名前の非抽象メソッドを定義しなければならない。そのメソッドの実装と機能は各々のクラスによって決定される。このコンセプトにはさまざまな使い道がある。例えば:

public class Fred implements Deleteable {
    // このメソッドはDeleteableインタフェースを満足する
    public void delete() {
        // ここにコードを実装
    }
    public void someOtherMethod() {
    }
}
public void deleteAll(Deleteable[] list) {
    for (int i = 0; i < list.length; i++) {
        list[i].delete();
    }
}

上の配列に含まれる全てのオブジェクトはdelete()メソッドを持つことが保証されるので、deleteAll()メソッドはFredオブジェクトと他の如何なるDeleteableオブジェクトをも区別する必要がない。

[編集] インタフェースの継承

インタフェースはextendsキーワードを用いて一つ以上のインタフェースを継承することができる。

interface ChildInterface extends ParentInterface, AnotherInterface {
    ...
}

結果として生じるインタフェースを実装するクラスは、元のインタフェースに含まれたメソッドをも併せて定義しなければならない。

public interface MyInterface {
    foo();
}
public interface Interface2 extends MyInterface {
    bar();
}
public class MyClass implements Interface2 {
    void foo() {...}
    void bar() {...}
    ...
}

[編集] アクセス修飾子

アクセス修飾子は、そのクラスやクラスメンバにアクセス可能なコードが誰であるかを決定する。

[編集] トップレベルクラスアクセス

デフォルトでは、Javaのクラスは、それら自身のJavaパッケージからのみアクセスできる。これは、クラスのパッケージが、裏に隠れて機能を実行するようなAPIを提供することを可能とする。外にアクセスを公開されたクラスの動作を、隠されたクラスが支える形になる。

  • デフォルト(修飾子を省略した場合) – 定義されたパッケージ内からのみアクセス可能。
  • public – 定義されたパッケージの外のクラスからもアクセス可能。

[編集] クラスメンバアクセス

クラスメンバとはフィールド、メソッド、コンストラクタ、クラス内で定義されたネストされたクラスのことである。アクセス制限が厳しいものから並べると、クラスメンバのアクセス修飾子は次の通り。

  1. private – そのクラスからのみアクセス可能 (内部クラスからのアクセスを含む)。private宣言されたメンバはサブクラスによって引き継ぐことができない。
  2. package-private(修飾子を省略した場合) – 同じパッケージ内の他クラスからもアクセス可能。
  3. protected – 上に加え、パッケージ外の継承クラスからアクセス可能。
  4. public – 任意のクラスからアクセス可能。

メソッドをオーバライドする際、そのメソッドのアクセス権を「より厳しく」することはできない。さもなくば親クラスのインタフェース契約を壊してしまうからである。したがってオーバライドされる場合、publicメソッドはpublicとして宣言されねばならず、protectedメソッドをデフォルトアクセス権(修飾子省略)とすることはできない。しかしながら、メソッドをオーバライドしてアクセス権を「より緩める」ことは許される。したがってオーバライドする際、デフォルト(パッケージ)アクセス権のメソッドはprotectedまたはpublicとして宣言することができ、protectedメソッドはpublicとして宣言することができる。

[編集] フィールド

アクセス修飾子に加えて、データフィールドは以下の修飾子によって宣言される:

  • final – このフィールドの中身は変更できない。ただ一度のみ値を設定(初期化)できる。イニシャライザ(初期化子)がないfinalフィールドを「ブランクfinal」フィールドと呼ぶ。staticなブランクfinalフィールドは最終的にスタティックイニシャライザによって初期化されなければならない。staticでないブランクfinalフィールドはコンストラクタの実行中に必ず初期化されなければならない。volatileにはなれない。
  • static – クラスのインスタンスではなくクラスに属する。
  • transient – オブジェクトの中でも永続的(persistent)にできないフィールドである。このフィールドの中身を待避または復元してはならないことをコンパイラに知らせる。
  • volatile – そのフィールドが他スレッドによって非同期にアクセスされる可能性があることをコンパイラに知らせる。finalにはなれない。

[編集] 定数

staticfinal両方を宣言されたフィールドは事実上、定数である。staticはそのフィールドがそのクラスにおいてただ一つのみ存在することを示し、finalはそのフィールドがただ一度のみ値を設定(初期化)可能であることを意味する。

[編集] 初期化子

「イニシャライザ」(初期化子)はフィールドのイニシャライザと同時に実行されるコードのブロックである。

[編集] 静的初期化子

「スタティックイニシャライザ」(静的初期化子)はstaticフィールドのイニシャライザと同時に実行されるコードのブロックである。静的フィールド初期化子と静的初期化子は宣言された順番に実行される。静的初期化はクラスがロードされた後で実行される。

static int count = 20;
static int[] squares;
static {  // スタティックイニシャライザ
    squares = new int[count];
    for (int i = 0; i < count; i++)
        squares[i] = i * i;
}
static int x = squares[5];  // x には値25が代入される。

[編集] インスタンス初期化子

「インスタンスイニシャライザ」(インスタンス初期化子)はインスタンスの(非staticな)フィールドの初期化子と同時に実行されるコードのブロックである。インスタンスフィールド初期化子とインスタンス初期化子は宣言された順番に実行される。

インスタンス初期化子とインスタンスフィールド初期化子はコンストラクタが呼び出された際に実行される。正確な実行順序としては、親クラスのコンストラクタが実行された後、かつ、自身のコンストラクタが実行される前、となる。

[編集] メソッド

アクセス修飾子に加えて、メソッドには以下の修飾子を付けて宣言できる:

  • abstract – 当該クラスでは定義されないメソッドであり、代わりに当該クラスの全ての具象(非abstract)サブクラスによって定義されなければならない。staticfinalnativeのいずれとも併用できない。
  • final – サブクラスによって再定義できないメソッド。そのメソッドがインスタンス(非static) メソッドでありかつ十分小さいならば、コンパイラはそのメソッドをインライン関数のように各所に展開する場合がある(訳注:性能改善目的と思われる)。abstractと併用はできない。
  • native – このメソッドはネイティブなマシン依存コードにリンクする。メソッド本体無しで宣言される。abstractと併用はできない。
  • static – クラスのインタンスではなく、クラスに属する。abstractと併用はできない。
  • strictfp – メソッドとそこに含まれる内部クラス全てにおける浮動小数点演算が、厳密な浮動小数点演算動作を使用する。厳密な浮動小数点演算動作は、演算結果がプラットフォームに関わりなく同一となることを保証する。
  • synchronized – メソッド本体を実行する前に、関連オブジェクトを排他する。関連オブジェクトが他スレッドにて排他済である場合、他スレッドが排他を解除し自スレッドが排他を獲得するまで実行を待たされる。ここで言う関連オブジェクトとは、そのメソッドがstaticならばClassオブジェクトを指し、非staticならばオブジェクトインスタンスを指す。abstractメソッドをsynchronizedとして宣言することは可能だが意味はない。何故なら排他とは宣言ではなく実装に伴う機能であり、抽象メソッドは実装を持たないからである。

privateメソッドは自ずからfinalであり、abstractにはできない点に注意。

[編集] 可変引数

Java SE 5.0において、引数の個数が可変であるようなメソッドについての文法上の便宜(varargs)[1]が追加された。これによって引数の個数が可変であるメソッドをタイプセーフに使用することが容易になる。最後のパラメタの後に「...」と書くと、Javaは全ての引数を配列に格納する:

public void drawPolygon (Point... points) {…}

このメソッドを呼ぶ際、プログラマは個々のpointsを単にカンマで区切って書けばよく、Pointオブジェクトの配列をわざわざ用意する必要はない。このメソッドの内部でpointsを参照する際はpoints[0]points[1]、などのように書ける。pointsが渡されていない場合、配列のlengthは0となる。可変個の引数と別に固定的に必要なパラメタがある場合は、それらのパラメタは可変引数に先立って指定すればよい。

// ポリゴンは少なくとも3つの点を必要とする。
public void drawPolygon (Point p1, Point p2, Point p3, Point... otherPoints) {}

[編集] コンストラクタ

コンストラクタはオブジェクトが割り当てられた後すぐに呼び出され、オブジェクトの初期処理を行う。コンストラクタは典型的にはnewキーワードを使用して呼び出されるが、リフレクションを使用して呼ぶこともできる。リフレクション機能はjava.lang.reflectパッケージより提供される。

コンストラクタを宣言する際に使える修飾子はアクセス修飾子のみである。

  • 可能ならば、オブジェクトはひとたびコンストラクタを呼ばれた以後は直ちに有効かつ有意味なオブジェクトとなるべきである。分割された複数の初期化用メソッドを使わなければ初期処理が完了しないというような設計は好ましくない。
  • 慣習として、引数としてそのオブジェクト自身の型を受け取ってデータメンバを複写するようなコンストラクタを「コピーコンストラクタ」と呼ぶ。
  • コンストラクタが明示的に定義されていない場合、コンパイラは暗黙のうちに内容が空で引数を取らないデフォルトのコンストラクタを生成する。
  • コンストラクタはオーバーロードできる。
  • コンストラクタ内の最初の文は親クラスのコンストラクタ:super(...);または同じクラス内の別のコンストラクタ:this(...);を呼び出せる。
  • もし、super(...) または this(...)に対する明示的な呼び出しがないならば、コンストラクタ本体が実行される前に、親クラスのデフォルトコンストラクタsuper();が呼ばれる。

[編集] Objectクラスのメソッド

Objectクラスのメソッドは継承されるので、全てのクラスにて使用できる。

[編集] cloneメソッド

詳細は「クローン (関数)」を参照

Object.clone()メソッドは現在のオブジェクトのコピーである新しいオブジェクトを返す。クラスは、それがクローンできることを明示するためにマーカーインタフェースCloneableを実装しなければならない。

[編集] equalsメソッド

Object.equals(Object)メソッドはそのオブジェクトともう一つのオブジェクトを比較し、二つのオブジェクトが同一かどうかをboolean型の値で返す。意味的には、このメソッドはオブジェクトの内容を比較するのに対し、関係演算子"=="はオブジェクトの参照を比較する。equalsメソッドはjava.utilパッケージにあるデータ構造クラスの多くで使われる。これらのデータ構造クラスのいくつかはObject.hashCodeメソッドにも依存している - equalshashCodeとの間の契約の詳細について、hashCodeメソッドを参照のこと。

[編集] finalizeメソッド

詳細は「ファイナライザ」を参照

Object.finalize()メソッドはガベージコレクタがオブジェクトのメモリを解放する前に必ず一度だけ呼び出される。オブジェクトが消滅する前に実行しなければならない何らかの後処理がある場合、各クラスはfinalizeをオーバーライドすることができる。とはいえほとんどのオブジェクトはfinalizeをわざわざオーバーライドする必要はない。

finalizeメソッドがいつ呼ばれるかは保証されない。複数のオブジェクトのfinalizeがどのような順番で呼ばれるかも不定である。もしJVMがガベージコレクションを実行せずに終了するならば、OSがオブジェクトを解放する可能性があり、その場合finalizeメソッドは呼ばれない。

finalizeメソッドは、他のクラスから呼ばれるのを防ぐために、常にprotectedとして宣言されるべきである。

protected void finalize() throws Throwable { ... }

[編集] getClassメソッド

Object.getClass()メソッドはオブジェクトをインスタンス化するために使われたクラスのClassオブジェクトを返す。このクラスオブジェクトはJavaにおけるリフレクションの基本となる。その他のリフレクション機能はjava.lang.reflectパッケージにて提供される。

[編集] hashCodeメソッド

Object.hashCode()メソッドは連想配列にオブジェクトを保存するための「ハッシュ値」として(int型の)整数を返す。java.util.Mapインタフェースを実装するクラスは連想配列を提供しhashCodeメソッドに依存する。hashCodeの良い実装は安定(不変)かつ均等に分布するハッシュ値を返す(異なるオブジェクトのハッシュ値は互いに異なる値となる傾向を持ち、かつハッシュ値は整数値の範囲内で均等に分布する。)。

連想配列はequalshashCodeの両メソッドに依存するため、これら二つのメソッドの間では、オブジェクトがMapに挿入される場合に関する或る重要な契約[3]が維持されねばならない:

二つのオブジェクト a と b に関して
  • a.equals(b) == b.equals(a)でなければならない。
  • もしa.equals(b)ならばa.hashCode() == b.hashCode()でなければならない。

この契約を維持するために、equalsメソッドをオーバーライドしたクラスは同時にhashCodeメソッドもオーバーライドし、逆もまた同様として、hashCodeequalsが常に同じ性質(または同じ性質の一部)に基づくようにしなければならない。

マップがオブジェクトとの間に有する更なる契約は、ひとたびオブジェクトがマップに挿入されたなら、hashCodeequals両メソッドの結果は以後変わらないということである。したがって、一般にハッシュ関数はオブジェクトの不変(変更不能)な属性に基くように設計するのが良い。

[編集] toStringメソッド

Object.toString()メソッドはオブジェクトの文字列表現をStringで返すものである。toStringメソッドは、オブジェクトが文字列連結演算子(++=)のオペランドとして使われたとき、コンパイラによって暗黙のうちに呼び出される。

[編集] waitとnotifyスレッドシグナルメソッド

全てのオブジェクトは、そのオブジェクトに関連するスレッドについての二つの待ちリストを持つ。一つの待ちリストはsynchronizedキーワードに伴いオブジェクトをミューテックス排他するために使われる。もしミューテックスが他スレッドによって排他されているならば、自スレッドは排他を待っているスレッドのリストに追加される。もう一つの待ちリストはスレッド間でシグナルを送るためのもので、これはwaitnotifynotifyAllの各メソッドを通して使用される。

wait/notifyを用いるとスレッド間での能率的な連携が可能となる。あるスレッドが別スレッドでの処理が終わるのを待ち合わせる必要があるとき、または何らかのイベントが発生するまで待たねばならないとき、スレッドはその実行を一時停止してイベントが発生した際に通知を受け取ることができる。これはポーリングとは対照的である。ポーリングにおいては、スレッドは一定時間スリープしてはフラグや他の状態表示をチェックする処理を繰り返す。ポーリングはスレッドがチェックを繰り返さねばならないという点でより計算コストが掛かる上に、実際にチェックしてみるまでイベント発生を検知できないという意味で鈍感でもある。

[編集] waitメソッド

waitメソッドには三つのオーバーロード版があり、タイムアウト値の指定方法がそれぞれ異なる:wait()wait(long timeout)wait(long timeout, int nanos)の三つである。一つ目のメソッドはタイムアウト値が0であり、これはタイムアウトが発生しないことを意味する。二つ目のメソッドはミリ秒単位のタイムアウト値を取る。三つ目のメソッドはナノ秒単位のタイムアウト値を取り、これは1000000 * timeout + nanosとして計算される。

waitを呼んだスレッドは待機状態となり、そのオブジェクトの待ちリストに追加される。そのスレッドは以下の三つのイベントのいずれか一つが起きるまで、オブジェクトの待ちリスト上に留まる:

  1. 別のスレッドがそのオブジェクトのnotifyまたはnotifyAllメソッドを呼ぶ (詳細はnotifyメソッド参照)
  2. 別のスレッドがそのスレッドのinterrupt()メソッドを呼ぶ
  3. waitにて指定した0でないタイムアウト値が満了する

waitメソッドは、そのオブジェクトについての同期(synchronized)ブロックまたは同期(synchronized)メソッドの内部からのみ呼ばねばならない。これはwaitnotifyとの間で競合を起こさないためである。スレッドが待ちリストに入るとき、そのスレッドはそのオブジェクトのミューテックス排他を解除する[4]。そのスレッドが待ちリストから削除され実行可能スレッドとなった際に、そのスレッドは走行を再開するのに先立ってそのオブジェクトのミューテックスを改めて排他しなければならない。

[編集] notifynotifyAllメソッド

Object.notify()Object.notifyAll() メソッドはオブジェクトの待ちリストから一つ以上のスレッドを削除し、それらを実行可能スレッドとする。notifyは待ちリストから1スレッドのみ削除し、notifyAllは待ちリストから全てのスレッドを削除する。notifyがどのスレッドをリストから削除するかは規定されておらず、JVMの実装に依存する。

notifynotifyAllメソッドは、そのオブジェクトについての同期(synchronized)ブロックまたは同期(synchronized)メソッドの内部からのみ呼ばねばならない。これはwaitnotifyとの間で競合を起こさないためである。

[編集] 入出力

関連項目: Java Platform, Standard Edition#java.io と New I/O

J2SE1.4よりも前のバージョンのJavaはストリーム・ベースブロッキングI/Oのみをサポートしていた。これは1ストリームにつき1スレッドを必要とした。何故ならストリームの入力または出力を行おうとすると、それが完了するまでそのスレッドは完全に待ちに入ってしまい、他の処理がいっさい行えなくなったからである。これは、Javaを用いたネットワークサービスを構築する上で、スケーラビリティと性能双方の面で大きな問題となっていた。J2SE1.4以降では非ブロッキングI/OフレームワークとしてNIO(New I/O)が導入され、このスケーラビリティ問題は修正された(ただし、サンによるNIO APIの実装にはまだ多くの問題点がある)。

非ブロッキングIOフレームワークは、以前のブロッキングIOフレームワークより遥かに複雑ではあるが、一つのスレッドで任意の数の"チャネル"を扱うことができる。このフレームワークはReactorパターンをベースとしている。

[編集] 実行コード

[編集] アプリケーション

public class MyClass {
    public static void main (String[] args) {...}
    ...
}

[編集] アプレット

詳細は「Javaアプレット」を参照

  • ウェブブラウザで明示された表示領域上で実行されるJavaコード。
  • initdestroyは一度だけ呼ばれるが、startstopはユーザがウェブページを訪問するたびに何回も呼ばれる。
// MyApplet.java

import java.applet.*;

public class MyApplet extends Applet {
    init() {...}     // ブラウザが最初にアプレットを読み込むときに呼ばれる。
    destroy() {...}  // ユーザがブラウザを終了するときに呼ばれる。
    start(){...}     // アプレットを実行し始めるときに呼ばれる。
    stop() {...}     // ユーザがウェブページを去るとき、再読込するとき、
                     // ブラウザを終了するときに呼ばれる。
}

<applet code="MyApplet" width="200" height="200">
</applet>

[編集] appletタグの埋め込み

  • HTMLのappletタグをアプレットのソースコードに埋め込むことができる。
  • appletタグを書くと、そのアプレットは.htmlファイル無しでも、簡易アプレットビューアによって直接実行可能となる。
  • 典型的には、appletタグはimport文の直後に書かれる。
  • appletタグは/* */コメントによって囲まれていなければならない。
// MyApplet.java
...
/*
<applet code="MyApplet" width="200" height="200">
</applet> 
*/
...

[編集] サーブレット

詳細は「Java Servlet」を参照

  • Webサーバ上で実行されるJavaコードであり、その出力(一般的にHTMLXML)は典型的にはウェブブラウザに対して送信される。
  • ServletはCGIPHPASP.NETなど非Java系動的Web技術のJavaにおける相当物である。

[編集] JSP (JavaServer Pages)

詳細は「JavaServer Pages」を参照

  • ウェブページにJavaコードを埋め込む形態。
  • JSPタグはウェブサーバで処理され、出力結果(一般的にHTMLやXML)はクライアントに送信される。
  • JSPコードは実行される前にJava Servletにコンパイルされる。
  • JSPはJava Servletの拡張である。
  • JSPタグの使用法はPHPASPのタグの使用方法と類似する。

[編集] JSPタグ

文法 意味
<% Java構文 %> スクリプトレット
<%= 単一Java構文の出力 %> 構文
<%! Java宣言文 %> 宣言
<%@ [page, include, taglib] JSPディレクティブ %> ディレクティブ

[編集] その他

[編集] ケースセンシビティ (大文字小文字区別)

Javaはケースセンシティブ (大文字小文字を区別する) である。

[編集] コメント

// 一行コメント
/* 複数行
   コメント */
/**
 * この行はクラス、インタフェース、メソッド、データメンバ宣言の直前に記述する。
 * このコメントはクラスのドキュメンテーションを自動生成する
 * ユーティリティで使用することができる。
 */

[編集] 関連項目

ウィキブックス
ウィキブックスJava関連の教科書や解説書があります。

[編集] 参考文献

  • James Gosling, Bill Joy, Guy Steele, and Gilad Bracha, The Java language specification, third edition. Addison-Wesley, 2005. ISBN 0-321-24678-0.
  • Patrick Naughton, Herbert Schildt. Java 2: The Complete Reference, third edition. The McGraw-Hill Companies, 1999. ISBN 0-07-211976-4
  • Vermeulen, Ambler, Bumgardner, Metz, Misfeldt, Shur, Thompson. The Elements of Java Style. Cambridge University Press, 2000. ISBN 0-521-77768-2

[編集] 脚注

  1. ^ Java プラットフォームにおける補助文字のサポート
  2. ^ Sun Microsystems, Inc.. "Character (Java 2 Platform SE 5.0)". Sun Microsystems, Inc.. 2009-06-11 閲覧。
  3. ^ 訳注:ここで言う「契約」の意味については契約プログラミング参照
  4. ^ 訳注:オブジェクトを排他していないスレッドがwait、notify、またはnotifyAllを呼ぶと、IllegalMonitorStateExceptionが生成され、current thread not ownerと表示される

[編集] 外部リンク

[編集] サン・マイクロシステムズ

最終更新 2009年9月16日 (水) 02:23 (日時は個人設定で未設定ならばUTC)。
【Javaの文法】変更履歴

ご利用上の注意