Javaの文法

データ型

Javaのデータ型には大別して、プリミティブ型と参照型がある。

参照型

すべての参照型はオブジェクト型を表すクラスObjectから派生する。オブジェクトは参照型のインスタンスである。クラスclassは既定でObjectから派生する参照型である。列挙型enumは抽象クラスEnumから暗黙的に派生する参照型である。
リフレクション機能のための「クラスを表現するクラス（メタクラス）」としてClassが存在するが、クラス自体はオブジェクトではない。

国際化サポート

Javaは1バイト整数の型（byte）と文字の型（char）とを区別する。なお、charは、名前に反して必ずしも文字を表現していない場合があり得る。すなわち、実際にはUCS-2（UTF-16）による、いわゆるダブルバイトである。J2SE 5.0以降ではサロゲートAPIによって、サロゲートペアに対応した。
JavaプログラムのソースコードおよびソースファイルはUTF-8でエンコードするのが基本である。Unocodeに対応したエンコードであれば、Javaプログラムのソースコードに直接Unicode文字を記述することもできる。なお、-encodingコンパイルオプションを指定することで、対応する任意のエンコードを使用することもできる。ロケール依存のコードページ（日本語版Microsoft Windowsで使われているCP932等）を利用することもできる。
文字列リテラルやコメントの他、クラス名や変数名も国際化に対応している。例えば、次のソースコードはJavaのコードとして正しく解釈されコンパイルされ実行できる。ここではクラス名、変数名、および文字列リテラルとして日本語の文字を使っている。
public class こんにちは世界 {
    private String 文字列 = "こんにちは世界";}

三項演算子

三項演算子は二つの記号?と:を組み合わせて記述する。条件演算子とも呼ぶ。構文は以下である。
条件 ? 式1 : 式2
条件がtrueであるとき、式1の値をとる。そうでない場合は式2の値をとる。
例:
String answer = (p < 0.05) ? "reject": "keep";
// これは以下のコードと等価である:String answer;if (p < 0.05) {
  answer = "reject";} else {
  answer = "keep";}

forループ

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

for-each ループ

J2SE 5.0では、for-each文と呼ばれる新機能が追加された。これは集合の中の全要素を順番に参照するような処理を大いに簡素化する。このような場合、従来は次の例に示すような反復子 (iterator) を書かねばならなかった:
// Java 5.0以前にはジェネリクスもないため、実際にはさらに煩雑となる。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);

例

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

    if (sum > 15) {
        break;  // ループを脱出する。
    }}

goto

Javaのキーワードには「goto」という綴りも含まれているが、goto文は無い（他にもうひとつ、constも同様に、キーワードとして予約されているが、予約されているだけで使われていない）。

インタフェース

インタフェースとは、実装の詳細がいっさいない抽象型である。その目的は複数のクラスを多態性によって統一的に扱うことである。共通のインタフェースを実装する複数のクラスは、そのインタフェース型のコンテキストにしたがって互いに交換可能とすることができる（リスコフの置換原則）。インタフェースはまた、抽象化 – クラスの実装方法を隠蔽すること – という考え方を強制するのにも役立つ。
インタフェースは抽象メソッドと定数フィールド (static finalフィールド) だけを含むことができる。インタフェースメソッドはデフォルトでpublicかつabstractであり（実装を持たない）、インタフェースフィールドはデフォルトで public static final である。インスタンスフィールドやクラスフィールドすなわち状態を持つことができない点が抽象クラスと異なる。
Javaは完全な直交の多重継承はサポートしておらず、インタフェースによる「型の多重継承」のみをサポートする。C++における多重継承（実装の多重継承）には、複数の親クラスや型から複数回継承したフィールドやメソッドを識別するための複雑なルールが伴う。インタフェースを実装から分離することにより、インタフェースはより単純かつ明快に多重継承が持つ利点の多くを提供する。もっとも、実装の多重継承を避ける代価としてコードは若干冗長になる。というのは、インタフェースはクラスのシグネチャを定義するのみで実装を持てないため、インタフェースを継承する全てのクラスは定義されたメソッドをいちいち実装しなければならないからである。純粋な多重継承であれば実装自体も継承されるのでこのようなことはない。
なお、Java 8ではインタフェースのデフォルトメソッドにより実装の多重継承を限定的にサポートするようになった。また、インタフェースが静的メソッドを持つこともできるようになった。
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();
    ...}
以下の例では、Deleteableインタフェースを実装する非abstractクラスは、引数無しで戻り型がvoidであるdeleteという名前の非抽象メソッドを定義しなければならない。そのメソッドの実装と機能は各々のクラスによって決定される。
public interface Deleteable {
    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() {...}
    ...}

アクセス修飾子

アクセス修飾子は、そのクラスやクラスメンバにアクセス可能なクラスを決定する。

定数

staticとfinal両方を宣言されたフィールドは事実上、定数である。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な) フィールドの初期化子と同時に実行されるコードのブロックである。インスタンスフィールド初期化子とインスタンス初期化子は宣言された順番に実行される。
インスタンス初期化子とインスタンスフィールド初期化子はコンストラクタが呼び出された際に実行される。正確な実行順序としては、親クラスのコンストラクタが実行された後、かつ、自身のコンストラクタが実行される前、となる。

可変引数

Java SE 5.0において、引数の個数が可変であるようなメソッドについての文法上の便宜 (varargs) が追加された。これによって引数の個数が可変であるメソッドをタイプセーフに使用することが容易になる。最後のパラメタの後に「...」と書くと、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) { /* ... */ }

Objectクラスのメソッド

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

cloneメソッド

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

equalsメソッド

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

toStringメソッド

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

waitとnotifyスレッドシグナルメソッド

全てのオブジェクトは、そのオブジェクトに関連するスレッドについての二つの待ちリストを持つ。一つの待ちリストはsynchronizedキーワードに伴いオブジェクトをミューテックス排他するために使われる。もしミューテックスが他スレッドによって排他されているならば、自スレッドは排他を待っているスレッドのリストに追加される。もう一つの待ちリストはスレッド間でシグナルを送るためのもので、これはwait、notify、notifyAllの各メソッドを通して使用される。
wait/notifyを用いるとスレッド間での能率的な連携が可能となる。あるスレッドが別スレッドでの処理が終わるのを待ち合わせる必要があるとき、または何らかのイベントが発生するまで待たねばならないとき、スレッドはその実行を一時停止してイベントが発生した際に通知を受け取ることができる。これはポーリングとは対照的である。ポーリングにおいては、スレッドは一定時間スリープしてはフラグや他の状態表示をチェックする処理を繰り返す。ポーリングはスレッドがチェックを繰り返さねばならないという点でより計算コストが掛かる上に、実際にチェックしてみるまでイベント発生を検知できないという意味で鈍感でもある。

notifyとnotifyAllメソッド

Object.notify() と Object.notifyAll() メソッドはオブジェクトの待ちリストから一つ以上のスレッドを削除し、それらを実行可能スレッドとする。notifyは待ちリストから1スレッドのみ削除し、notifyAllは待ちリストから全てのスレッドを削除する。notifyがどのスレッドをリストから削除するかは規定されておらず、JVMの実装に依存する。
notifyとnotifyAllメソッドは、そのオブジェクトについての同期(synchronized)ブロックまたは同期(synchronized)メソッドの内部からのみ呼ばねばならない。これはwaitとnotifyとの間で競合を起こさないためである。

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

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

コメント

コメントの文法はC++と同じである。
// 一行コメント/* 複数行   コメント */
なお、ドキュメンテーションコメントとしてJavadoc方式をサポートする。
/** * この行はクラス、インタフェース、メソッド、フィールド宣言の直前に記述する。 * このコメントはクラスのドキュメントを自動生成する * ユーティリティで使用することができる。 */