その2: C言語欠点からのJava 変数宣言と型

変数宣言位置に対して

C言語では、ローカル変数をブロックの先頭で、実行文を始まる前に、まとめて宣言する必要がありました。
C言語では、auto変数の宣言を{ } のブロック内先頭でまとめて宣言しました。
つまり、実行文の後で、宣言文を使うとコンパイルエラーでした。
文の参考⇒(確認後はブラウザの戻る操作で戻ってください

対してJavaでは

そのような制約がなくなり、使う前であれば、実行文を記述した後で宣言しても構いません。
しかし、初期化しない変数を使うと警告(warning)でなくエラーになります。←(C言語ではwarningでした) 以下にエラーとなるプログラム一部と、コンパイルエラーの表示を示します。

		int c;
		c = c + 1;
ソースファイル名:エラー箇所でソース行番号: 変数 c は初期化されていない可能性があります。
                c = c + 1;
                    ^

以下のように初期化すると、エラーはなくなります。なおJavaでは、行単位のコメントで//の表現を使い、記述位置よりその行終端までがコメントになります。 なお、複数行も含めたある範囲をコメントにするには、C言語と同じ/* */を使います。

		int c=0; //0が記憶される変数を作る 
		c = c + 1;

以下のように、cへの代入演算子を使ってもエラーはでません。

		int c; //C言語と同じで、何が記憶されるか分からない変数になります。
 
		c = 0;
		c = c + 1;

しかし、その判断は論理的なミスに対して考慮されていません。(今後コンパイラの性能が上がれば考慮できるかも?) よって、上記でエラーにならないのに、下のプログラムでは『変数 c は初期化されていない可能性があります』のエラーが出ます。

		int c; //C言語と同じで、何が記憶されるか分からない変数になります。
		boolean b=true;// 論理値のtrueかfalseを記憶変数で、trueで初期化
		if (b){
			c = 0;
		}
		c = c + 1;

上記では、bに成立の意味のtrueが記憶されているのでifで必ず成立して、必ずc = 0が実行されます。
よってc + 1の実行時はcに0が記憶されることは明らかなのでコンパイルエラーにしなくてもよさそうです。 しかしエラーなので、そこまでコンパイラが賢く作られていないということです。
 なおJavaのifやwhile for など、判定式を書く部分に、演算結果が(true 又は false)の値になる表現を書かなければなりません。 これは、boolean(ブーリアン)型になります。
C言語では成立が『0以外の値』でしたが、Javaではtrueが成立の意味の定数です。 逆にfalseが不成立の意味の定数です。 Javaでは結果がtrueやfalseのboolean型にならない式をifなど条件式に使うとコンパイルエラーです。

なお、Javaではforの繰り返し前の初期設定部で、変数宣言が可能です。その変数スコープは繰り返し対象範囲だけとなります。 以下に例を示します。 が通用範囲です。

		int sum=0; //1+2+3+4を求める
		for (int n = 1; n <= 4; n++){
			sum += n;
		}
		//ここで、sumの変数は使えるが、変数 n は、存在しないので使うとコンパイルエラーです。

またC言語と異なり、次のように{ のブロック内部で、同じ名前の変数を使うことは許されていません。

	{
		int n = 1;
		{
			int n = 5;// C言語では可能ですがJavaでは許されません。この位置にコンパイルエラーの指摘がでます
		}
		// C言語では、この位置で、1が記憶される変数nが使える。
	}

すでに〜で定義されています。のエラーになります。つまり、あいまいに見える変数を作れなくしているのです。 (C++と発展した言語では、C言語仕様を引きずるので可能です)
その他のauto変数(メソッドの中で宣言する変数)のスコープは、C言語と同じように考えてください。

型の種類に対して

C言語の型の参考⇒(確認後はブラウザの戻る操作で戻ってください
C言語に似ている型の体系ですが、intやshortやlong型のあいまいな意味をなくしています。次がJavaの型の種類で、変数宣言で利用します。

大分類 型:宣言時に使うキーワード 記憶範囲
論理型 boolean 関係演算のtrueかfalse
整数型 byte 1byteの-128〜127
char 文字16bit(\u0000〜\uffff)
short 16bit整数
int 32bit整数
long 64bit整数
実数 float 単精度浮動点少数(32bit)
double 倍精度浮動点少数(64bit)
参照型 Stringクラス 文字列
StringBufferクラス 変更を目的にした文字列
その他のクラス 目的に応じてたくさんのクラスがある
配列型 上記の全てや、配列を、配列の要素にできます。

新しい型で、成立を意味する定数trueか、 不成立を意味するfalseのどちらかだけを記憶できるbooleanブーリアンと呼びます)の型があります。

charは、2byteの文字を記憶する型です。
C言語のchar型はbyte型に対応します。

論理型、整数型、実数型が基本型となります。 そしてオブジェクトを参照する参照型があり、この2つに分類する考え方があります。
基本型if(a == b)〜で記憶内容が等しいか判定ができますが、参照型はC言語のポインタと同じように、 データの中身をチェックするのではなく、『同じ記憶域を指し示すか?』 の判定です。

"123""abc"の表現はポインタではなく、 文字列というString型を使います。

Scannerクラスのように既存のクラス以外に、プログラマが作るクラスを含めると無限の型があると言えます。
クラスとは、情報や命令の入れ物で、それらをまとめた設計書と考えるとよいでしょう。
既存のクラスが始めからたくさん用意されており、それらクラスの情報や機能を利用してプログラミングします。
クラスの情報を利用する場合、クラス名の型の変数を用意し、 オブジェクトをnew 演算子で生成して=の代入演算子で管理させて(参照させて)使う形態になります。

型のチェックを厳しくしたJava

C言語では、int型変数へdouble型データの代入が許されていました。 しかし、これで情報を失うプログラムミスになりがちです。 (警告(warning)を出しましたが、コンパイルはできてきます。)
ミスでなく意図的に行う場合はキャスト演算を使いました。
C言語キャスト演算の参考⇒(確認後はブラウザの戻る操作で戻ってください

さて、Java言語では情報を失うプログラムミスをなるべく無くすために、 型のチェックは厳しくしています。
それは、情報を失う可能性の代入はキャスト演算が必要で、それを行わない場合は warningでなくコンパイルエラーにしています。以下に例とコンパイラメッセージを示します。

		int i;
		double d = 1.23;

		i = d;	// (int) d   のキャスト演算子を使わないとエラーです。 
ソースファイル名:エラー箇所でソース行番号: 精度が落ちている可能性
検出値  : double
期待値  : int
                i = d;
                    ^