ブロックとスコープ
ブロック
ブロックとは、{ と } で括られた、
プログラム処理上のひとまとまりのことである。
ブロックの例1:
if( a > 0) { //1行目 ブロック開始
System.out.println(a); //2行目
} //3行目 ブロック終了
上記で、1行目の { でブロックが開始し、3行目の } でブロックが終了する。
2行目、ブロック内の処理となる。
ブロックの例2:
while( a > 0) { //1行目 ブロック開始
a--; //2行目
System.out.println(a); //3行目
} //4行目 ブロック終了
上記で、1行目の { でブロックが開始し、4行目の } でブロックが終了する。
2行目、3行目は、ブロック内の処理となる。
ブロックを使う理由は2つある。
- if, for, while等の分岐処理で複数の処理を実行したいとき。
if, for, while等の分岐処理は、一つの処理のみを実行する場合、
文法上はブロックを利用する必要はない。
ブロックを利用しない例:
if( a > 0) System.out.println(a);
しかし、分岐処理で複数の処理(行)を実行したい場合、ブロックを利用する必要がある。
ブロックを利用することにより、ブロック処理を一つの処理のまとまりとして扱うことができる。
ブロックを利用する例:
if( a > 0) {
System.out.print("A の値は"); //複数の処理をtrue の時に実行したい
System.out.println(a); //複数の処理をtrue の時に実行したい
}
- ブロック内のスコープで有効なローカル変数を利用するとき
詳細は下記スコープの説明を参照
ブロックの利用の注意事項
- 複数のブロックをネストすることができる
例(概念):
{ //ブロック1開始
{ //ブロック2開始
} //ブロック2終了
} //ブロック1終了
例(具体例):
while(true){ //ブロック1開始
if(a == 0){ //ブロック2開始
System.out.println(a);
} //ブロック2終了
} //ブロック1終了
- 複数のブロックをオーバーラップすることはできない。
例(概念):
{ //ブロック1開始
{ //ブロック2開始
} //ここでブロック2より先にブロック1は終了できない
} //ここでブロック1より後にブロック2は終了できない
例(エラーの具体例):
while(true){ //ブロック1開始
if(a>0){ //ブロック2開始
System.out.println(a);
} //ここでブロック2より先にブロック1は終了できない
}else{ //ここでブロック1より後にブロック2は終了できない
System.out.println(-a);
}
スコープ
変数にはスコープ(変数にアクセスできるプログラムの範囲)がある。
例えば、
局所変数(ローカル変数)のスコープは宣言された場所から宣言されたブロックの終りまでである。
スコープの例1 (エラーの例)
public class Foo {
public static void main (String[] args){
int a=0;
while(a < 10){
int b;
b = a;
a++;
}
System.out.println(a);
System.out.println(b);
}
}
スコープの例2 (エラーの例)
public class Bar {
public static void main (String[] args){
int a=0;
for(int b=0; b<10; b++){
a = b;
}
System.out.println(a);
System.out.println(b);
}
}
スコープの例3 (エラーの例)
public class FooBar {
public static void main (String[] args){
for(int b; b<10; b++){
if(b%2 == 0){
int c;
c = 1;
}else{
c = 0;
}
System.out.println(b);
System.out.println(c);
}
}
}
練習課題
以下のプログラムでは、forループを最後に抜ける前の i の状態だけを表示したい。
(最後にループした時のiの値)
以下の例では、スコープがforループの外にある変数 last を準備し、ループ中の変数 i の値を保持して表示したい。
しかし、以下のソースコードではコンパイル時にエラーが出る。
public class Scope2 {
public static void main(String[] args){
int last;
for(int i = 0; i<10; i++){
last = i;
}
System.out.println("last の最後の値は "+ last); // <-- ここでコンパイルエラー
}
}
「変数 last は初期化されていない可能性があります。」とコンパイルエラーが出る。
これは、last に値が代入される前に参照される可能性があるためである。
for文の中で last = i; で 変数last に代入しているが、
for文のブロックはfor文の条件が true の時にしか実行されないので、
必ず値が代入されるかコンパイラが判断できない。
以下の出力結果のように、lastの値を表示するように、last の初期化を追加せよ。
※ヒント: 必ず last に値が代入されるように、最初に変数 last に値を代入しておく。
$ java Scope2
last の最後の値は 9
$
mackin