読者です 読者をやめる 読者になる 読者になる

【Java】public static void main(String[] args)とは何か

Java
スポンサーリンク

Javaを勉強し始めた時にまず最初に目にするpublic static void main(String[] args)という一文ですが、何となく決まり事なんだという程度で書いていたと思います。 Javaに慣れてきた段階であらためて考えると、色々見えてくることもありますので少しだけ内容を追ってみます。

Javaの入門書などでまず最初に実行するのが以下のような HelloWorld! を出力するプログラムですね。

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

実行すると以下のようになります。

$ javac HelloWorld.java
$ java HelloWorld
Hello World!

なぜ HelloWorld クラスを実行すると main メソッドが実行されているのかというと、main メソッドは java コマンドの実行時に呼び出されます。正確には ① メソッド名が main② 引数が String 型の配列(可変長引数)③ static 修飾子が付与されている メソッドでなければいけません。

この条件を満たしてないクラスを java コマンド実行しようとすると以下のように失敗します。

エラー: メイン・メソッドがクラスHelloWorldで見つかりません。次のようにメイン・メソッドを定義してください。
   public static void main(String[] args)

また、戻り値をvoid以外にした場合も以下のエラーがでます。

エラー: メイン・メソッドはクラスHelloWorldのvoid型の値を返す必要があります。
次のようにメイン・メソッドを定義してください。
   public static void main(String[] args)

メソッド名(main)について

main メソッドは java コマンドのエントリポイントとなる特別なメソッドです。java HelloWorldコマンドを実行すると上記でも述べた特徴の main メソッドを探して実行します。

じゃあ main という名前のメソッドを使ったらいけないのかと言われるとそうではありません。

新しく SubClass を作って、その中にpublic static void main(String[] args)メソッドを定義してください。そして実行する HelloWorld の main メソッドから呼び出してみます。

public class HelloWorld {
    public static void main(String[] args) {
        SubClass.main(new String[] {"Hello SubClass!"});
    }
}

class SubClass {
    public static void main(String[] args) {
            System.out.println(args[0]);
        }
}

実行すると以下の通りになります。

$ javac HelloWorld.java
$ java HelloWorld
Hello SubClass!

このように通常のメソッドと同じように使えますが、このメソッドがあると java コマンドで実行されることを想定してしまうのであまり使わない方がいいかと思います。

static修飾子について

なぜ main メソッドに static 修飾子が必要なのでしょうか。

通常はクラスのメソッドを使用する場合はクラスのインスタンスを new で生成する必要があります。

SubClass sub = new SubClass();
sub.main(new String[] {"Hello SubClass!"});

しかし static 修飾子を付けることによって new でインスタンス化しなくてもメソッドにアクセスできるようになります。

SubClass.main(new String[] {"Hello SubClass!"});

ということは java コマンドを実行してもメインクラスのインスタンスは生成されないため、実行される main メソッドは static 修飾子が付いてる必要があるということです。

引数について

引数には String型の配列、または String型の可変長引数である必要があります。配列はString[] argsまたはString args[]と記述し、可変長引数はString...argsと記述します。どちらも配列として受け取るということでは同じです。引数の名前argsは何でもいいです。

引数には何が入ってくるのかというと、java HelloWorld [args...]のように java コマンド実行時にクラスの後ろに指定した文字列です。

class HelloWorld {
    public static void main(String[] args) {
        System.out.println("length:" + args.length);
        System.out.println("[0]:" + args[0]);
        System.out.println("[1]:" + args[1]);
        System.out.println("[2]:" + args[2]);
    }
}

引数はスペース区切りで指定します。ダブルクォーテーション、シングルクォーテーションで括ると、スペースが含まれていても一つの引数として認識されます。

$ java HelloWorld "hoge fuga" bar foo
length:3
[0]:hoge fuga
[1]:bar
[2]:foo

最初に実行していたように引数なしで java コマンドを実行すると、引数は null にならずに長さ0の配列が生成されます。長さ0の配列にアクセスしようとしてるので例外が出てますね。

$ java HelloWorld
length:0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
    at HelloWorld.main(HelloWorld.java:4)

参考書籍

Javaエンジニア養成読本 [現場で役立つ最新知識、満載!] (Software Design plus)
きしだ なおき のざき ひろふみ 吉田 真也 菊田 洋一 渡辺 修司 伊賀 敏樹
技術評論社
売り上げランキング: 9,661