Java : 1.基礎文法・基本仕様

Javaは世界で最も使われているプログラミング言語の1つであり、JVM(Java Virtual Machine)などから成るJavaテクノロジーの総称でもあります。当ページではJavaの基礎的な文法や基本となる仕様についてまとめています。

コメントアウト

Javaのコメントアウトは2種類です。

//1行コメントアウト


/*

複数行コメントアウト

*/

識別子

識別子とはクラスやメソッド、変数に付ける名前のことです。ファイル名には関係ありません。名前に使える文字数に制限はありませんが、使用できる文字はアルファベット(大文字・小文字は区別されます)・数字・$(ドル記号)・_(アンダースコア)の4種のみです。また、1文字目に数字を使うことはできません。

リテラル

Javaで取り扱うリテラルは6つです。

整数リテラルは小数部を持たない数値です。2進数・8進数・10進数・16進数の4つの書き方があります。2進数は数値の頭に0b(0B)を付けます。8進数は数値の頭に0を付けます。16進数は数値の頭に0x(0X)を付けます。

浮動小数点数リテラルは小数部を持つ数値です。10進数・指数の2つの書き方があります。指数は基数を10とします。書き方は仮数部、続けてe、続けて指数を指定します。例えば、3.0 * 10 ^ 4 は3e4と表記します。

文字リテラルは1つの文字を表します。'(シングルクォート)で特定の1文字を囲む、あるいは文字コードを直接指定するかします。

文字列リテラルは複数の文字の集合体です。"(ダブルクォート)で対象の文字列を囲みます。

論理値リテラルはtrue(真)とfalse(偽)の状態を持ちます。論理値は'(シングルクォート)"(ダブルクォート)で囲んではいけません。

nullリテラルは何も無いという状態を表します。小文字でnullと記述することでnullリテラルとなります。

データ型

Javaのデータ型は基本型と参照型に分けられます。基本型は以下に記す8つのデータ型を指し、参照型はそれ以外全てです。ちなみに配列は全て参照型となりますので注意してください。基本型は値そのものを保持し、参照型は値のある場所の情報を保持します。また、参照型はnullリテラルを持つことができますが基本型はエラーとなります。

//基本型と参照型の違い

class Test {

public static void main(String[] args) {

int a1 = 123;

int a2 = a1;

a1 = 456;

int[] b1 = {123};

int[] b2 = b1;

b1[0] = 456;

System.out.println(a1);

System.out.println(a2);

System.out.println(b1[0]);

System.out.println(b2[0]);

}

}

//a1 == 456

//a2 == 123

//b1[0] == 456

//b2[0] == 456

基本型

byteは-128~127の整数を取り扱う基本型です。

shortは-32,768~32,767の整数を取り扱う基本型です。

intは-2,147,483,648~2,147,483,647の整数を取り扱う基本型です。

longは-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807の整数を取り扱う基本型です。long型を使う際は数値の末尾にl(L)を付ける必要があります。

floatは-3.4E38~+3.4E38の浮動小数点を取り扱う基本型です。float型を使う際は数値の末尾にf(F)を付ける必要があります。

doubleは-1.7E308~+1.7E308の浮動小数点を取り扱う基本型です。

booleanは論理値リテラルを取り扱うことができる基本型です。

String

Stringは文字列を取り扱うことができる参照型です。ただし、その取扱い方や振る舞いは基本型と殆ど同じという非常に変わった特性を持っています。参照型ですのでnullを格納できますし、いくつかのメソッドが用意されています。そして他の参照型とは異なり、Stringは値そのものを保持することができます。

型の変換

基本型は型の暗黙変換という特性を持ちます。これは言うなれば下位にあたるデータ型から上位にあたるデータ型へはデータ型の違いを越えて値の受け渡しをすることができるというものです。byte → short → int → long → float → doubleという方向に変換ができます。あまり使い道は無いでしょうがcharもint以上のデータ型に変換することができます。

先の図において反対方向にデータ型を変換する場合はキャスト演算子を使う必要があります。型を跨いだ変換は概ね問題ありませんが条件次第ではデータの欠損・変容が起こりますので注意が必要です。

class Test {

public static void main(String[] args) {

//下位から上位への暗黙変換

byte foo1 = 123;

double foo2 = foo1;

System.out.prinln(foo2); //123.0 と出力

//キャスト演算子による上位から下位への型変換

double foo3 = 456.789;

byte foo4 = (byte)foo3

System.out.println(foo4); //456 と出力

}

}

変数・配列

普通の変数(スカラ変数)の文法は以下の通りです。データ型の前にfinal演算子を付けると定数になります。文法は他のプログラミング言語とほぼ変わらないかと思います。

//変数の宣言

データ型 変数名;

int foo1;


//変数へ代入

変数名 = 値;

foo1 = 123;


//変数の初期化

データ型 変数名 = 値;

int foo2 = 456;


//定数(初期化のみ認められる)

final演算子 データ型 変数名;

final int foo3 = 789;

配列の取り扱いはインスタンス化に慣れていないと若干厄介です。まず、配列を格納することが可能な変数を宣言します。次に宣言した変数と同じデータ型の配列をインスタンス化させて、その領域へのアドレスを変数に格納します。このとき要素数を決めるのですがインデックスとは異なり要素数は1からカウントしますので注意が必要です。また、配列を定数化させることはできません。

//配列を収めることができる変数の宣言

データ型[] 変数名;

int[] foo1;


//インスタンス化して領域確保

変数名 = new データ型[要素数];

foo1 = new int[3];


//宣言と領域確保を同時に行う

int[] foo2 = new int[3];


//配列への代入

変数名[インデックス] = 値;

foo1[0] = 1;


//配列の初期化

データ型[] 変数名 = {インデックス0に代入する値, インデックス1に代入する値, ... インデックスnに代入する値};

int[] foo3 = {1, 22, 333};

メンバ変数(メンバ配列)

class直下に宣言された変数(定数含む)・配列はメンバ変数・メンバ配列となります。それ以外はローカル変数・ローカル配列と呼称します。メンバだとアクセス修飾子の指定が義務付けられ、またstatic化が可能になります。

演算子

演算子は何らかの演算を行うための記号です。Javaでは多くの演算子が用意されており、カテゴリ分けすることができます。

算術演算子は数値の計算を担います。+(加算)・-(減算)・*(乗算)・/(徐算)・%(除算の余り)の5つがあります。

単項演算子は1つの値に用いるものです。-(負の数を表す)・++(インクリメント)・--(デクリメント)の3つです。インクリメントとデクリメントは数値の前に付けるか、後ろに付けるかで挙動が変わるの注意してください。個人的には特別な理由が無いかぎりは前付けで統一するべきだと思います。

class Test {

public static void main(String[] args) {


int foo1 = 0;

foo1 = foo1++ + foo1++;

System.out.println(foo1); //1 が出力されます


int foo2 = 0;

foo2 = foo2++ + ++foo2;

System.out.println(foo2); //2 が出力されます


int foo3 = 0;

foo3 = ++foo3 + foo3++;

System.out.println(foo3); //2 が出力されます


int foo4 = 0;

foo4 = ++foo4 + ++foo4;

System.out.println(foo4); //3 が出力されます


}

}

代入演算子は左辺の値に、右辺の値をそのまま、あるいは加工して代入する働きがあります。=(代入)・+=(両辺を加算した結果を代入)・-=(両辺を減算した結果を代入)・*=(両辺を乗算した結果を代入)・/=(両辺を除算した結果を代入)・%=(両辺を除算した余りを代入)の6つです。

関係演算子は両辺の値を比較して、その結果を論理値リテラルで返します。==(両辺が等しいときtrue)・!=(両辺が等しくないときtrue)・>(左辺の値が右辺より大きいときtrue)・>=(左辺の値が右辺以上のときtrue)・<(右辺の値が左辺より大きいときtrue)・<=(右辺の値が左辺以上のときtrue)の6種類あります。

論理演算子は関係演算子に似た働きをしますが若干癖があります。多くの場合は関係演算子を使った計算式を両辺に置いて使います。&は両辺がtrueのときtrueを返します。両辺を評価します。&&は両辺がtrueのときtrueを返します。左辺がfalseのときは右辺を評価しません。|は両辺のどちらかがtrueならtrueを返します。両辺を評価します。||は両辺のどちらかがtrueならtrueを返します。左辺がtrueのとき右辺を評価しません。^は両辺に論理値リテラルを配置します。両辺が異なるときtrueを返します。!は1つの値(あるいは変数など)の頭に付けます。その値がtrueのときはfalseを返し、falseのときはtrueを返します。

余談ですが参照型で使用できるnullリテラルは関係演算子の==!=でチェックすることができます。

分岐処理

Javaの分岐処理にはif文・switch文の2つが用意されています。

if文の書き方は以下の通りです。else if文およびelse文は省略可能です。また、if文・else if文・else文全てに共通ですが処理が1文しか無いときは括弧を省略できます。

//文法

if(条件式) {

処理

} else if(条件式) {

処理

} else {

処理

}


//文法(省略版)

if(条件式) 処理

else if(条件式) 処理

else 処理

//例文

if(foo == 0) {

System.out.println("変数fooは0です");

} else if(foo == 1) {

System.out.println("変数fooは1です");

} else {

System.out.println("変数fooは0・1ではありません");

}


//例文(省略版)

if(foo == 0) System.out.println("変数fooは0です");

else if(foo == 1) System.out.println("変数fooは1です");

else System.out.println("変数fooは0・1ではありません");

switch文の書き方は以下の通りです。式に指定した値と等しい値をもつところから処理が始まり、break文あるいはswitch文の終わりに到達するまで処理が行われます。式と対応したcaseが見つからないときはdefaultから処理が行われます。defaultは省略できます。

//文法

switch(式) {

case 値1:

処理

case 値2:

処理

:

:

:

case 値n:

処理

default:

処理

}

//例文

switch(foo) {

case 1:

System.out.println("fooは1です");

break;

case 2:

System.out.println("fooは2です");

break;

default:

System.out.println("fooは1・2ではありません");

}

繰り返し処理

Javaで繰り返し処理をするために、while文・do while文・for文・拡張for文の4つが用意されています。

while文は条件式がtrueを返すときwhileブロック内の処理を実行します。

//文法

while(条件式) {

※処理

}

//例文

int i = 0;

while(i < 5) {

System.out.println(i);

++i;

}

do while文は必ず1度はwhileブロック内の処理を実行するwhile文です。

//文法

do {

※処理

} while(条件式)

//例文

int i = 0;

do {

System.out.println(i);

++i;

} while(i < 5)

for文は3つの式を持つステートメントです。式1は変数へ代入、式2は条件式、式3はifブロック内の処理が終わった後に行う処理となります。各式は省略することができますが式2を省略すると無限ループになりますので注意してください。

//文法

if(式1; 式2; 式3) {

※処理

}

//例文

if(int i = 0; i < 5; ++i) {

System.out.println(i);

}

拡張for文は他のプログラミング言語ではfor each文と呼ばれることが多いであろう処理です。まとまりをもつデータからデータを1つずつ取り出して変数に代入して処理を行っていきます。ちなみに拡張if文で用いる変数は拡張if文内で宣言する必要があります。

//文法

for(変数宣言 : データ) {

※処理

}

//例文

char[] foo = {'a', 'b', 'c'};

for(char i : foo) {

System.out.println(i);

}

繰り返し制御文

以上4つのステートメントに対して使用できる特殊な処理が3つあります。

break文はループから出る働きがあります。

continue文は条件式に戻る働きがあります。

ラベルは繰り返し処理がネストしているとき、break文とcontinue文がどの階層の繰り返し処理に対応しているかを表したものです。

//例文

int foo1 = 0;

int foo2 = 0;

label:

while(foo1 < 5) {

System.out.println(foo1);

++foo1;

while(foo2 < 5) {

System.out.println(foo2);

++foo2;

break label;

}

}

Javaにおけるオブジェクト指向

Javaにおけるオブジェクト指向プログラミングに直接関係する処理についてまとめます。

具象クラス