Javaの文法(Javaのぶんぽう)の記事では、プログラミング言語Javaの構文(シンタックス、)について解説する。また、それ以外についても解説している。

キーワード一覧

Javaの言語仕様は68種類(Java 25現在)に抑えたキーワードによって比較的コンパクトにまとめられている。Javaの構文はC++言語によく似たものであり、それよりも比較的平易化されている。従って以下のキーワードを眺めるだけでもJavaプログラミングの大まかなスタイルを掴むことができる。 類別 キーワード 説明アクセス修飾子private同クラス内でアクセス可protected同クラス内と同パッケージ内と派生クラス内でアクセス可public全範囲でアクセス可クラス定義abstract抽象クラス、抽象メソッドclassクラスenum列挙型extendsスーパークラスの指定finalクラスの継承不可、メソッドのオーバーライド不可、フィールドの定数化implements実装するインターフェースinterfaceインターフェースnativeそのメソッドは他言語コンパイルコードで実装されるnon-sealedsealedの解除permits継承できるクラスの指定recordレコード型sealed継承できるクラスの指定static静的フィールド、静的メソッド、静的内部クラスはトップレベル扱いされるstrictfp指定クラス、指定メソッドで厳密な浮動小数点計算が行われるsynchronized同期用クラス、同期用メソッド、同期用ブロックtransient直列化から除外されるフィールドvoid返り値無しのメソッドvolatileそのフィールドは各スレッドからキャッシュ参照されないパッケージimportパッケージ名前空間の解決用package同クラス内と同パッケージ内でアクセス可、パッケージスコープの宣言モジュール定義exportsモジュールが外部に提供するパッケージを指定moduleモジュールを定義openモジュールやパッケージやクラスが開かれた(拡張可能な)ものであることを示すopensパッケージまたはモジュール内の特定のパッケージを開くためのキーワードprovidesサービスプロバイダーがサービスの実装を提供requiresモジュール間の依存関係を宣言toprovidesで指定されたサービスプロバイダーを特定のサービスに提供transitiveモジュール間の依存関係を伝播させるためのキーワードusesサービスを使用withprovidesで指定されたサービスプロバイダーの実装制御構文breakループ脱出caseパターンマッチ項目continueループ起点回帰defaultパターンマッチ外do無条件ループ起点else条件式の偽側フローfor初期値定義と周回毎値変化で修飾された条件式ループif条件式の真側フローinstanceofインスタンスの実行時型チェックreturnメソッドの評価終了switchパターンマッチ起点whenパターンマッチの条件while条件式ループyieldパターンマッチの戻り値例外処理assert条件式が偽ならプログラム中断catch例外パターン捕捉finally例外デフォルト捕捉throw例外発生throwsそのメソッドで発生する例外候補try例外発生ブロックプリミティブ型boolean真偽値byte符号付き8ビット整数char文字表現用16ビット整数double64ビット浮動小数点数float32ビット浮動小数点数int符号付き32ビット整数long符号付き64ビット整数short符号付き16ビット整数参照型newインスタンスの生成superスーパークラスのインスタンスthisカレントクラスのインスタンス変数・引数_変数名の省略var型の省略使用できないgotoconst

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

プリミティブ型 Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)もしくはChapter 4. Types, Values, and Variablesとも。 プリミティブ型はオブジェクトではなく、スーパークラスを持たない。 +整数型byte8ビット符号付きshort16ビット符号付きint32ビット符号付きlong64ビット符号付き 注 オーバフローは例外等にはならず、2の補数として自然な形でラップアラウンド (wrap around) する。例えば、 () に1を加えると、結果は () になる。

+浮動小数点数型float32ビット符号付きdouble64ビット符号付き float f = 2147483647f; double d = 9223372036854775807;float型は数字を符号付き32Bitの最大値(2,147,483,647)まで代入できるが、double型は符号付き64Bitの最大値(9,223,372,036,854,775,807)まで代入できる。

また、float型は代入する数字の末尾に「F」または「f」をつけなければdouble型とみなされ、コンパイルエラーになってしまう。 注 浮動小数点数は決して例外をスローしない 0でない値を0(ゼロ)で割った値はInf(無限大)と等値である 無限大でない値をInfで割った値は0(ゼロ)と等値である。

+文字char16ビット符号無しUnicode 注 J2SE 1.4.2までのcharは基本多言語面 (BMP) の範囲内のコードポイントを符号無し16ビットで表現する。 J2SE 5.0からは、補助文字をサポートするため、charは符号無し16ビットで表現可能でありBMPの範囲内に限ればコードポイントと同値となるUTF-16符号化形式のコード単位を表現するように変更され、21ビットが必要となるコードポイントの表現にはintを使用するように変更された(JSR#204)Java プラットフォームにおける補助文字のサポート。つまりchar型は互換性の問題からあくまで符号無し16ビットのままとされており、UTF-16符号化形式を採用したことから補助文字を扱う場合はコードポイント一つにコード単位を格納したchar値のペアが対応する 。これらを適切に取り扱う便宜として、クラスやプリミティブラッパークラスであるクラスなどの各種メソッドが利用できる。

+ブーリアン型booleantrue または false 注 C/C++や類似の言語と異なり、Javaではfalseの代わりに0(ゼロ)またはnullと書くことはできない 同様に、0でない値を書いてtrueの代わりとすることはできない ブール型をブール型でない基本型へキャストすることとその逆はできない

参照型 すべての参照型はオブジェクト型を表すクラスから派生する。オブジェクトは参照型のインスタンスである。クラスclassは既定でから派生する参照型である。列挙型enumは抽象クラスから暗黙的に派生する参照型である。

リフレクション機能のための「クラスを表現するクラス(メタクラス)」としてが存在するが、クラス自体はオブジェクトではない。

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

String str1 = "alpha"; String str2 = new String("alpha");

とオブジェクトは可変(変更可能)なので、オブジェクト生成オーバヘッド無しで柔軟に文字列を生成・変更できる。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"となる

プリミティブラッパークラス プリミティブラッパークラス

機能 ある型の値を他の型へ変換する静的メソッドを提供する 基本型を参照型としてラッピングする目的(ボックス化)で使用できる(コレクションに格納するなど)

その他

ブール型以外の基本型の初期値は0。ブール型の初期値はfalse。ラッパークラス(およびObjectクラスに属する全クラス)の初期値はnull。

配列 配列自体はオブジェクト型のサブクラスつまり参照型である。 プリミティブ型の配列、オブジェクト型の配列、さらにそれらの配列の配列(ジャグ配列)、などの配列を扱える。 プリミティブ型の配列では、全ての要素はその型の値でなければならない。 オブジェクトの配列では、階層関係にある必要がある(例えば、インタフェースの配列では、あるオブジェクトがその要素になるには、そのインタフェースを実装したクラスのインスタンスでなければならない)。 配列オブジェクトは配列要素の数を表す読み取り専用の属性「length」を持つ。 すべての配列は動的に領域確保される。配列を生成する際の要素数として、定数だけでなく変数を使用することができる。 「配列の配列」ではない、(C#にあるような「本物の」)多次元配列(矩形配列)は無い。

// 配列を宣言 - 配列名は「myArray」、要素の型は "SomeClass" への参照 SomeClass[] myArray = null;

// 配列を生成 myArray = new SomeClass;

// または宣言と生成を同時に行う SomeClass[] myArray = new SomeClass;

// 配列の要素を割り当てる (ただし、基本型の配列なら必要ない) for (int i = 0; i < myArray.length; i++) myArray[i] = new SomeClass();

リテラル リテラルの例を示す。

データ型例booleantrue falseint0b1010(2進法表記、0bか0Bで始まる) 0365(8進法表記、0で始まる) 0xF5(16進法表記、0xか0Xで始まる) 245(10進法表記) 123_456 値が byte, short, long の範囲内であれば型キャストなしに代入できる。long245L (末尾にLかlをつける。1とlは区別しにくいのでLが推奨される)float23.5F 23.5f 1.72E3F 1.72E3f 1.72e3F 1.72e3fdouble23.5(末尾にdかDを付けなくてもdoubleのリテラルとなる) 23.5D 23.5d 1.72E3 1.72E3Dchar'a' 'Z' '\u000A'(コードポイントの16進数表記による) '\0231'(コードポイントの8進数表記による) '\t'(タブ文字) '\b'(後退 (Backspace) 文字) '\r'(キャリッジリターン (復帰文字)) '\f'(改ページ) '\\'(バックスラッシュ) '\''(シングルクォーテーション (単一引用符)) '\"'(ダブルクォーテーション (二重引用符)) '\n'(ラインフィード (改行文字))null"Hello, world" """ 1行目 2行目 """

国際化サポート Javaは1バイト整数の型(byte)と文字の型(char)とを区別する。なお、charは、名前に反して必ずしも文字を表現していない場合があり得る。すなわち、実際にはUCS-2(UTF-16)による、いわゆるダブルバイトである。J2SE 5.0以降ではサロゲートAPIによって、サロゲートペアに対応した。

JavaプログラムのソースコードおよびソースファイルはUTF-8でエンコードするのが基本である。Unicodeに対応したエンコードであれば、Javaプログラムのソースコードに直接Unicode文字を記述することもできる。なお、-encodingコンパイルオプションを指定することで、対応する任意のエンコードを使用することもできる。ロケール依存のコードページ(日本語版Microsoft Windowsで使われているCP932等)を利用することもできる。

文字列リテラルやコメントの他、クラス名や変数名も国際化に対応している。例えば、次のソースコードはJavaのコードとして正しく解釈されコンパイルされ実行できる。ここではクラス名、変数名、および文字列リテラルとして日本語の文字を使っている。

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

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

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

関係演算子 関係演算子 表記意味==左辺の数値は右辺の数値と等しい。左辺のインスタンスは右辺のインスタンスと同一である。!=左辺の数値は右辺の数値と等しくない。左辺のインスタンスは右辺のインスタンスと同一ではない。>左辺の数値は右辺の数値より大きい。>=左辺の数値は右辺の数値と等しい、または、より大きい。<左辺の数値は右辺の数値より小さい。<=左辺の数値は右辺の数値と等しい、または、より小さい。instanceof左辺のインスタンスのクラスは右辺のクラスまたは右辺のクラスのサブクラスである。

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

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

条件 ? 式1 : 式2

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

例: String answer = (p < 0.05) ? "reject": "keep";

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

論理演算子 論理演算子 短絡評価論理演算 (結果が判定するまでオペランドを左から右へと評価する) 必要最小限の式しか評価しない 部分的な評価 (完全な評価ではない)

表記意味&&論理積(左のオペランドが false のとき、式は false を返し、右のオペランドは評価されない)||論理和(左のオペランドが true のとき、式は true を返し、右のオペランドは評価されない)!論理否定

ビット演算子 ビット演算子 +二項演算子文法意味&ビット積|ビット和^ビット排他的和<<左シフト(ゼロ埋め)>>右シフト(符号拡張)>>>右シフト(ゼロ埋め) +単項演算子表記意味~ビット反転

文字列演算子 表記意味+連結+=連結と代入

制御構造 if... else if文 if (expr) { statements; } else if (expr) { statements; } else { statements; } exprは真偽値を与えなければならない。

switch文 switch文 switch (expr) { case VALUE1: statement11 ; … ; statement1L ; break ; case VALUE2: statement21 ; … ; statement2M ; break ; default: statementd1 ; … ; statementdN ;

expr 値の型はbyte/short/int/charあるいはそれらのプリミティブラッパークラスでなければならない。 J2SE 5.0以降では列挙型 (Enumのサブクラス) を、Java SE 7以降ではString型を使用することもできる。caseラベルの値にnullは使用できない。 各々のcaseラベルの値はユニークなリテラル、あるいはコンパイル時に値が定まる定数式 (constant expression) でなければならず、変数を書くことはできない。 上記は古いJavaのswitch文で現在のJavaは機能が拡張されている。

forループ for文 for (initial-expr; cond-expr; incr-expr) { statements;

for-each ループ J2SE 5.0では、for-each文The For-Each Loopと呼ばれる新機能が追加された。これは集合の中の全要素を順番に参照するような処理を大いに簡素化する。このような場合、従来は次の例に示すような反復子 (iterator) を書かねばならなかった: // J2SE 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に含まれる全てのについて、長さを取得してsumに加算する。

whileループ while文

while (expr) { statements;

do ... while 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 Javaのキーワードには「goto」という綴りも含まれているが、goto文は無い(他にもうひとつ、constも同様に、キーワードとして予約されているが、予約されているだけで使われていない)。

オブジェクト クラス Javaではクラスあるいはインタフェースの内部で別のクラスを宣言することができる。これは「ネストされたクラス」(nested class) と呼ばれる。ネストされていないクラスは「トップレベルクラス」(top-level class) と呼ばれる。ネストされたクラスがstatic修飾されていない場合、「内部クラス」(inner class) となる。内部クラスは外側のクラスのインスタンスを暗黙的にキャプチャすることで、静的メンバ、非静的メンバいずれにもアクセスすることができる。ネストされたクラスがstatic修飾されている場合、「静的クラス」(static class) となり、静的メンバのみにアクセスできる。メソッドの内部にクラスを定義することもでき、これは「ローカルクラス」(local class) と呼ばれる。ローカルクラスでは、外側のローカル変数には読み取りアクセスのみできる。また、型の名前を持たないローカルクラスとして「匿名クラス」(anonymous class) を定義し、同時にインスタンス生成をすることもできる。

クラスあるいはインタフェースの内部で別のインタフェースを宣言することもできる。これは「ネストされたインタフェース」と呼ばれる。

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

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

継承 // 子クラスは親クラスを継承する class ChildClass extends ParentClass { ... }

任意のクラスのデフォルトの親クラスはObjectクラスである。 クラスは単一の親クラスだけを継承できる。実装多重継承はできない。

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

インタフェース インタフェースとは、実装の詳細がいっさいない抽象型である。その目的は複数のクラスを多態性によって統一的に扱うことである。共通のインタフェースを実装する複数のクラスは、そのインタフェース型のコンテキストにしたがって互いに交換可能とすることができる(リスコフの置換原則)。インタフェースはまた、抽象化 – クラスの実装方法を隠蔽すること – という考え方を強制するのにも役立つ。

インタフェースは抽象メソッドと定数フィールド (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();