はじめに
- JavaBronze試験にて、コンパイルエラーか実行時に例外がスローされるか判断できないと解けない問題があります
- 「動かないことはわかるけど、、どっちのエラーかわからん!」となることが多々ありますよね。IDEが教えてくれるからわからなくても…とか思っちゃいますが、試験なので覚えなくてはなりません
- 自分の理解向上のために問題を10題つくってみました、ぜひ挑戦してみてください
- 簡略化のために、実行時に例外がスローされることを「実行時エラー」と表現していますのでご了承ください
判断方法
- 文法に誤りがあるなら、コンパイルエラー
- シンプルにこれだけです。コンパイルができるけど、それ以降でコケるものは全て実行時エラーです
- 問題を解いて体で覚えていきましょう
問1
//これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
final String FRUIT = "apple";
FRUIT = "banana";
System.out.println(FRUIT);
}
答え
答え:コンパイルエラー
一度宣言した定数に値を代入する=文法上不可なので、コンパイルエラーとなります
問2
// これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
int i = 5; j = 3;
System.out.print(i + j);
}
答え
答え:コンパイルエラー
変数の宣言時は「データ型と変数名」をセットで宣言する、という文法ルールに違反しているのでコンパイルエラーになります
// jの宣言前にintを追加すれば動く
public static void main(String[] args) {
int i = 5;
int j = 3;
System.out.print(i + j);
}
問3
// これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
int[] array = new int[3];
array[0] = 3.1;
System.out.print(array[0]);
}
答え
答え:コンパイルエラー
int型の配列に小数点のあるdouble型の数字を入れようとしているのでコンパイルエラーとなります
「型に一致しないデータを代入しようとしている→コンパイルエラー」という認識をしておけば、迷うことはなさそうですね
問4
// これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
char a = 'A';
if (a = 'A')
System.out.print("A");
}
答え
答え:コンパイルエラー
(2023/08/19 頂いたコメントを元に修正しました)
代入式 a='A' の結果はchar型であり、booleanに変換できないため、コンパイルエラーとなります
ifの条件式の結果はboolean型(true/false)である必要がある、という文法に反しています
a == 'A'とすることでコンパイルエラーが解消されます。見間違わないように気を付けましょう!
問5
// これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
double a = 3.14;
switch (a) {
case 3.14:
System.out.print("hoge");
break;
case 4.14:
System.out.print("hoge");
break;
case 5.14:
System.out.print("hoge");
break;
}
}
答え
答え:コンパイルエラー
double型はSwitch文の条件として使えないのでコンパイルエラーになります
浮動小数点は使えないので、float型の場合もコンパイルエラーです
問6
// これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
int i = 0;
do (i<10){
System.out.print(i);
i++;
} while;
}
答え
答え:コンパイルエラー
これはdo-while文を知っていればわかりやすい問題ですね
条件式を記述する場所がdoの後ではなく、whileの後である必要があるためコンパイルエラーとなります
問7
public class Main {
// これはコンパイルエラー?実行時エラー?
// 「java Main」で実行することとする
public static void main(String[] args) {
System.out.print(args[0]);
}
}
答え
答え:実行時エラー
要素数0の配列argsの0番目の要素にアクセスしようとしているので、そんなの存在しないよ~と例外をはきます
文法上の問題はなく、コマンドライン引数を指定して実行すれば例外は出ないため、これは実行時エラーとなります
問8
// これはコンパイルエラー?実行時エラー?
class Fruit {
private String name;
public Fruit(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void printName() {
System.out.println(name);
}
}
public class Main {
public static void main(String[] args) {
Fruit f = new Fruit();
f.setName("banana");
f.printName();
}
}
答え
答え:コンパイルエラー
明示的にコンストラクタを定義しているにもかかわらず、インスタンス化の際にFruitに引数をセットしていないため、コンパイルエラーとなります
問9
// これはコンパイルエラー?実行時エラー?
class Fruit {
private String name;
public Fruit(String name) {
this.name = name;
}
public void printName() {
System.out.println(name);
}
}
public class Main {
public static void main(String[] args) {
Fruit f = new Fruit("apple");
f.name("banana");
f.printName();
}
}
答え
答え:コンパイルエラー
nameのアクセス修飾子はprivateなので、f.name("banana")
のように他のクラスからアクセスすることができません。
アクセス修飾子(public,pritected,なし,private)についてはコンパイル時点で確認が走るので、基本はコンパイルエラーという認識で大丈夫そうです
問10
// これはコンパイルエラー?実行時エラー?
public static void main(String[] args) {
int[] numbers = new int[5];
numbers[5] = 3;
System.out.print(numbers[5]);
}
答え
答え:実行時エラー
事前に指定したnumbers配列のインデックスは0~4であるのに対し、インデックス5番目に値を代入しようとしているため例外java.lang.ArrayIndexOutOfBoundsExceptionが発生します
配列の長さを事前に定義して、そこの範囲外にアクセスしようとしているんだからコンパイルエラーでも良くない?と思ってしまったのですが、何か理由があるのでしょう(調べておらずすみません)
さいごに
- 基本は文法の誤りであるコンパイルエラーを疑う
- ただし、配列の範囲外アクセスor実行しないと発生しないエラーは実行時エラー(実行時例外スロー)
- 上記の認識をしておけば試験問題は解けるかな、と思います
- まだ勉強中の身ですので、間違いあればコメントくださると助かります