実行と起動の罠

実行と起動の罠

このレッスンでできるようになること。java コマンドで起動できる main メソッドの形を見分けられるようになり、コマンドライン引数の番号を間違えずに読めるようになります。

まず予測してください

次の4つのクラスを java Main で起動したとき、正常に動くのはどれでしょうか。答えを決めてから先に進んでください。

// A public class Main { public static void main(String[] args) { } } // B public class Main { static public void main(String[] args) { } } // C public class Main { public static void main(String... args) { } } // D public class Main { public void main(String[] args) { } }

答えと理由

起動できるのは A と B と C です。D だけが起動できません。

  • 修飾子の順番は自由です。 static public でも public static でも同じです。ここを「順番が違うからエラー」と読ませるのが定番の引っ掛けです
  • 可変長引数でも起動できます。 String... args は内部的に String[] args と同じ扱いなので、起動用の main として認められます
  • static が無いと起動できません。 D はコンパイル自体は通ります。通るのに実行時に落ちる、というのが厄介なところで、Main method is not static のようなエラーになります

つまり「コンパイルエラー」と「実行時エラー」を分けて考える必要があります。試験ではこの2つを混ぜた選択肢が必ず並びます。

引数の名前と型

引数名は args でなくてもかまいません。public static void main(String[] a) でも起動します。逆に、型が違うものは起動用として認められません。main(int[] args)main(String args) はコンパイルは通りますが、起動用の main としては使われません。

戻り値は void である必要があります。public static int main(String[] args) はコンパイルできますが、起動には使えません。

コマンドライン引数の数え方

java Main hello world と打ったとき、配列 args の中身は次のようになります。

  • args.length は 2
  • args[0]hello
  • args[1]world

クラス名 Main は配列に入りません。 ここが C 言語の argv と決定的に違うところで、args[0] をクラス名だと思い込むと1つずつずれます。引数を渡さずに起動したときは args.length が 0 になります。null にはなりません。空の配列が渡ってくるので、args.length を見るコードは安全に動きます。ここで「args が null だから NullPointerException」と読ませる選択肢もよく出ます。

存在しない添字を読むと ArrayIndexOutOfBoundsException になります。引数を1つしか渡していないのに args[1] を読むコード、というのが試験で最も多い形です。

まとめ

順番は自由、static は必須、可変長引数も可、引数の先頭はクラス名ではなく最初の引数です。この4点だけ覚えれば、この分野の出題はほぼ落とせません。

要件

  1. 受け取った2つの文字列から、要素数2の String 配列 args を作ること
  2. args.length と args[0] を半角スペース1つでつないだ文字列を返すこと
  3. クラス名は Main、メソッド名は firstArg のままにすること

入出力例

firstArg("hello", "world")"2 hello" firstArg("java", "silver")"2 java" firstArg("main", "exam")"2 main"

ヒント

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部
main.java
学習モード

メモ

実行と起動の罠

⌘S で保存