最終課題に向けて
ここに示した内容はこれまでに提出された課題を見て,説明が必要であろうと思われる部分を抜粋しました.
- Visual Studio Code で表示されるラベルについて
- インデントを揃える.
- コンパイル&実行結果を確認する.
- スコープについて
- メソッドの呼び出しについて
- メソッド分割について
- エラーについて
- 例外の責任転嫁について
Visual Studio Code で表示されるラベルについて
Visual Studio Codeなどの昨今の IDE (Integrated Development Environment; 統合開発環境) では, EoD (Ease of Development) のため実引数に仮引数の名前を表示する機能があります. 以下に例を図示します.

この図中の5, 7行目と12行目にそれぞれ,prefix
,format
という文字列が見えます.
これは IDE の機能により表示されているラベルです.
実際にプログラム中にこのラベルを書くとコンパイルエラーになるため,注意してください.
インデントを揃える.
インデントをしっかりと揃える必要がありますが,手作業でインデントを揃えないようにしましょう. 手作業でインデントすると漏れや間違いが起こる可能性があるためです. 利用しているエディタの一括インデントを行ってください.
Visual Studio Code の場合,Option+Shift+F で一括インデントが行えます.
コンパイル&実行結果を確認する.
提出された練習問題を見てみるとごく単純なコンパイルエラーが残っているケースが見られます. どんなに面倒でも一度コンパイルしてください. そして,コンパイルできたら実行して,結果を確認してください. その際,どのような入力により,どのような結果が期待されるのかを確認してから実行すると良いでしょう.
以下のような場合は,速やかにTA,教員に相談してください. 授業中に挙手する他に,Teams でのチャットでも質問対応しております. 相談により成績が下がることはありませんが,相談せずに未完成のまま提出することは 結果的に成績の低下に繋がります.
- コンパイル方法がわからない.
- 実行方法がわからない.
- コンパイルエラーが修正できない.
- 期待する結果がわからない.
- 期待する結果と実行結果の差がわからない.
スコープについて
変数には有効範囲があります.この有効範囲のことを スコープ(scope) と呼びます.
プログラム中の {
と }
で囲まれた範囲を ブロック(block) と呼びます.
スコープは変数が宣言された後,宣言されたブロックの中でのみ有効です.
メソッドの呼び出しについて
メソッドを呼び出すには,何らかの実体に対して呼び出す必要があります. この実体のことを レシーバ(receiver) と呼びます.
例えば,以下のフィボナッチ数列のn番目の値を求めるプログラムFibonacci
で考えてみましょう.
public class Fibonacci {
void run(String[] args) {
Integer index = 10;
if(args.length != 0)
index = Integer.parseInt(args[0]);
Integer result = fibonacci(index);
}
Integer fibonacci(Integer index) {
if(index < 2)
return 1;
return fibonacci(index - 1) + fibonacci(index - 2);
}
public static void main(String[] args) {
HelloWorld app = new HelloWorld();
app.run(args);
}
}
main
メソッド内で,app.run(args)
というメソッド呼び出しを行なっています.
この呼び出しのapp
がレシーバ,args
が実引数(arguments),run
がメソッド名です.

run
メソッド内やfibonacci
メソッド内の fibonacci
メソッドの呼び出しには
レシーバがないように見えます.
これは実はthis
というレシーバが隠されており,自分自身を表しています.
次に,8行目のfibonacci
メソッドの宣言に注目してください.
この行の最初の Integer
は返り値の型であり,このメソッドの最後にこの型の値を return
する必要があります.
fibonacci
はメソッド名,括弧内のindex
は仮引数(parameter)と呼びます.
波括弧で囲まれた部分はメソッドボディやメソッドの中身と呼ばれ,そのメソッドが行う処理が書かれています.

メソッド分割について
メソッドは細かく分割しましょう. メソッドを分割するのは,処理に名前をつけるために行います. 処理に名前が適切に付けられていると,処理内容を理解しなくても何が行われるのかを理解できます. つまり,読みやすくなるのです.
適切な名前のためには,命名規則に従うことも重要でしょう. Javaの場合,メソッド名は動詞から始まり,キャメルケースで命名することが推奨されています. このことを意識して適切なメソッド名をつけてみましょう.
最初は適切な名前をつけるのは難しいかもしれません. そのような場合,日本語(ローマ字)で付けるのも良いでしょう.
一方でメソッドを分けるときに,次のようなメソッドの中で他のメソッドを呼び出しているだけのメソッドには分割の意味はありません.
public class SomeClass {
void run(String[] args) {
perform(args);
}
void perform(String[] args) {
// 何らかの処理
}
// mainメソッドは省略.
}
- Q&A なぜメソッドに分けないといけないのでしょうか
- Q&A どのようにメソッドに分ければ良いのでしょうか
- うまくメソッド名を付けるための参考情報 (qiita.com)
- メソッド名、迷った時に参考にできる単語一覧 (blog.77jp.net)
エラーについて
コンパイルエラーや実行時エラーの場合,エラーメッセージと発生した場所をしっかりと確認しましょう.
コンパイルエラーについて
コンパイルエラーは次のようにエラーの内容とエラーの場所を示してくれます.
この例の場合,Fibonacci.java
の 18 行目で,「シンボルを見つけられない」というコンパイルエラーです.
シンボルを見つけられないというエラーは,典型的には綴りを間違えています.
その変数の名前をしっかりと確認しましょう.
Fibonacci.java:18: エラー: シンボルを見つけられません
prev2 = reslut; // result を代入して,次の i に備える.
^
シンボル: 変数 reslut
場所: クラス Fibonacci
エラー1個
また,典型的なコンパイルエラーとその原因は次の通りです. 指摘された箇所を失火路と確認して修正していきましょう.
- シンボルが見つかりません.
- 綴りは合っていますか?
import
は忘れていませんか.- 変数の有効範囲(スコープ)は合っていますか?
- クラス
Xxxx
はpublic
であり,ファイルXxxx.java
で宣言しなければなりません- クラス名とファイル名が一致していますか? 大文字小文字も区別してください.
\12288
は不正な文字です.- 全角スペースが入っていないか確認してください.全角スペースはC言語と同じく文字列以外での利用が許されていません.
以下の内容も併せてご覧ください.
実行時エラーについて
実行時に何らかのエラーが起こった場合,次のようなメッセージが出力されます. このようなメッセージのことをスタックトレース(stack trace)と呼びます.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at FizzBuzz.run(FizzBuzz.java:5)
at FizzBuzz.main(FizzBuzz.java:25)
1行目にどのようなエラーであるか,2行目以降にプログラムのどこで発生したかが書かれています.
どのようなエラーなのかは,thread "main"
の後ろを見てみましょう.
ここには,エラーの原因となった例外のクラス名が書かれています.
上の例の場合,ArrayIndexOutOfBoundsException
,すなわち,array index out of bounds exception です.
これは,配列の範囲を超えて要素にアクセスしようとした場合に発生する例外です.
英語の意味がわからない場合,Google 翻訳や DeepL 翻訳にかけてみましょう.
2行目以降は,クラス名.メソッド名(ソースファイル名:行番号)
のように出力されています.
表示された場所と例外クラスの名前を手掛かりに実行時エラーが起こらないよう修正しましょう.
スタックトレースとは,実行時に例外が発生したときに表示されるエラーメッセージです. 上で示したように,どこでどのような例外が発生したのかを把握する手掛かりとなる重要なメッセージです.
そして,例外が発生してスタックトレースを出力するときになると,
例外が発生した箇所はどのような経緯で呼び出されたのかを辿ってmain
メソッドまで到達しようとします.
メソッドの呼び出しはスタックで管理されていますので,スタックを辿っていくわけです.
このことからスタックトレースと呼ばれています.
スタックトレースは Java に限ったものではなく,例外機構を導入しているプログラム言語であれば 似たような出力が行われます.
例外の責任転嫁について
ファイルの入出力時に発生する可能性のある IOException
などの検査例外 と呼ばれる例外は,
例外が発生したときの対応をプログラム中に明示しておかなければコンパイルできないようになっています.
対応方法は以下の2種類です.
- 例外に対してその場で対応し,プログラム実行を復帰させる.
- メソッドの呼び出し元に対応を任せる(責任を転嫁する).
この講義では,呼び出し元に責任を転嫁します.
責任を転嫁するには,例外が発生する可能性のあるメソッドのシグネチャに throws
節を追加します.
public class Cat {
void run(String[] args) throws IOException {
for(String arg: args) {
performEach(arg);
}
}
void performEach(String arg) throws IOException {
BufferedReader in = new BufferedReader(new FileReader(arg));
String line;
while((line = in.readLine()) != null)
System.out.println(line);
in.close();
}
public static void main(String[] args) throws IOException {
SomeClass app = new SomeClass();
app.run(args);
}
}
こうすることで,performEach
内で IOException
が発生した場合,呼び出し元である run
メソッドに対応を任せます.
しかし,run
メソッドも同様に throws
節が宣言されており,呼び出し元である main
メソッドに対応を任せています.
同様に main
メソッドも throws
節があるため,呼び出し元に責任転嫁しています.
main
メソッドの呼び出し元とは,java
コマンドです.
もし,例外が発生した場合,java
コマンドまで例外が伝播し,そこでスタックトレースが出力されてプログラムが終了することになります.