- JAVA
Java public static void mainの意味とargsの使い方
public static void main(String[] args) とは、Javaのプログラムが最初に実行する「入口」のメソッドです。public は「どこからでも呼べる」、static は「オブジェクトを作らずに呼べる」、void は「値を返さない」、String[] args は「コマンドラインから渡された文字列の配列を受け取る」という意味です。 java コマンドはこの形のメソッドを探して呼び出すので、1語でも変えると「メイン・メソッドが見つかりません」というエラーになります。
この記事では、1語ずつの意味を表にまとめたうえで、それぞれを外したり変えたりしたときに出るエラーメッセージを実際に再現しました。後半では、コマンドライン引数 args の受け取り方、個数チェック、数値への変換、空白やクォートを含む引数、ワイルドカード展開、終了コードまでを、OpenJDK 21.0.10 の実行結果つきで説明します。Java 25 で正式機能になった簡略な main(void main())は、OpenJDK 25.0.4.1 で実行した結果を載せています。
public static void mainの早見表
| 語 | 種類 | 意味 | 外す・変えるとどうなるか(Java 21.0.10) |
|---|---|---|---|
public |
アクセス修飾子 | どのクラスからでも呼べる。JVM(Javaを動かす仕組み)が外から呼ぶために必要 | 「メイン・メソッドがクラスNoPublicで見つかりません」 |
static |
修飾子 | オブジェクトを作らなくても呼べる。起動直後はまだオブジェクトが1つもないため必要 | 「メイン・メソッドがクラスNoStaticのstaticではありません」 |
void |
戻り値の型 | 値を返さない。結果は終了コードで伝える | 「メイン・メソッドはクラスIntMainのvoid型の値を返す必要があります」 |
main |
メソッド名 | java コマンドが探す決まった名前。小文字 | Main にすると「メイン・メソッドが…見つかりません」 |
String[] |
引数の型 | 文字列の配列。コマンドライン引数が入る | String にすると「メイン・メソッドが…見つかりません」 |
args |
引数の名前 | arguments(引数)の略。名前は自由に変えられる | argv などに変えても動く |
変えてよいところ・そのままにするところを分けると、次のようになります。
| 書き方 | 動く?(Java 21.0.10 で確認) |
|---|---|
public static void main(String[] args) |
動く(基本形) |
public static void main(String... args) |
動く(可変長引数) |
public static void main(String args[]) |
動く(配列の [] を名前側に書く形) |
static public void main(String[] args) |
動く(修飾子の順番は入れ替え可) |
public static void main(final String[] argv) |
動く(引数名の変更、final の追加) |
static void main(String[] args) |
エラー(Java 25 では動く) |
public void main(String[] args) |
エラー(Java 25 では動く) |
public static void main() |
エラー(Java 25 では動く) |
public static int main(String[] args) |
エラー |
public static void Main(String[] args) |
エラー |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Java public static void mainの意味とargsの使い方」
動作確認の環境
| 項目 | 内容 |
|---|---|
| 主に使った JDK | OpenJDK 21.0.10(Ubuntu 24.04、シェルは bash) |
| Java 25 の確認 | OpenJDK 25.0.4.1 |
| エラー文の言語 | 日本語は -Duser.language=ja、英語は -Duser.language=en を付けて表示 |
| 表記について | 実行時はクラスの出力先(-cp out)と文字コードの指定を付けています。記事では読みやすさのため java クラス名 引数 の形に整えて載せています |
mainメソッドの基本形と動かし方
まずは基本形です。ファイル名はクラス名と同じ Hello.java にします。
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, Java");
}
}
$ javac Hello.java
$ java Hello
Hello, Java
javac がソースコードをクラスファイル(Hello.class)に変換し、java Hello がそのクラスを読み込んで main メソッドを呼び出します。流れを図にするとこうなります。
flowchart LR
A["java Hello apple 100"] --> B["JVM が起動"]
B --> C["Hello クラスを読み込む"]
C --> D["public static void main を探す"]
D --> E["args に apple と 100 を入れて呼び出す"]
E --> F["main が終わると終了コードを返す"]
java コマンドに渡すのは「クラス名」で、ファイル名ではありません。 .class を付けたり、大文字小文字を変えたり、つづりを間違えたりすると、次のエラーになります。
$ java Hello.class
エラー: メイン・クラスHello.classを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: Hello.class
$ java Helo
エラー: メイン・クラスHeloを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException: Helo
英語表示では Error: Could not find or load main class Helo です。
1語ずつ外すと出るエラーを再現する
それぞれのキーワードが必要な理由は、外してみるとよくわかります。以下はすべて、コンパイルは通り、実行したときに java コマンドが出すエラーです(Java 21.0.10、終了コードはいずれも 1)。
publicを外す
public class NoPublic {
static void main(String[] args) { System.out.println("no public"); }
}
$ java NoPublic
エラー: メイン・メソッドがクラスNoPublicで見つかりません。次のようにメイン・メソッドを定義してください。
public static void main(String[] args)
またはJavaFXアプリケーション・クラスはjavafx.application.Applicationを拡張する必要があります
英語表示:
Error: Main method not found in class NoPublic, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
private static void main にしても同じメッセージでした。Java 21 までは、JVM がクラスの外から呼び出せるように public が必要です。
staticを外す
public class NoStatic {
public void main(String[] args) { System.out.println("no static"); }
}
$ java NoStatic
エラー: メイン・メソッドがクラスNoStaticのstaticではありません。次のようにメイン・メソッドを定義してください。
public static void main(String[] args)
英語表示は Error: Main method is not static in class NoStatic です。static のないメソッドは、new でオブジェクトを作ってからでないと呼べません。プログラムが始まった時点ではオブジェクトがまだ1つもないので、オブジェクトなしで呼べる static が必要になります。
voidを別の型に変える
public class IntMain {
public static int main(String[] args) { return 0; }
}
$ java IntMain
エラー: メイン・メソッドはクラスIntMainのvoid型の値を返す必要があります。
次のようにメイン・メソッドを定義してください。
public static void main(String[] args)
英語表示は Error: Main method must return a value of type void in class IntMain です。C言語の int main と違い、Javaの main は値を返しません。呼び出し元(シェルやバッチ)に結果を伝えたいときは System.exit(番号) を使います(後述)。
mainの名前や引数の型を変える
public class BigMain {
public static void Main(String[] args) { System.out.println("Main"); }
}
Main(大文字)、引数なしの main()、引数が String 1つの main(String args) は、どれも Java 21 では「メイン・メソッドがクラス○○で見つかりません」になりました。Javaは大文字と小文字を区別し、引数の型まで含めてメソッドを探しているためです。
エラーと原因の対応表
| エラーメッセージ(日本語/英語の先頭) | 主な原因 | 直し方 |
|---|---|---|
| メイン・メソッドがクラスXで見つかりません/Main method not found in class X | public がない、名前が Main、引数が String[] でない、main を書いていない |
public static void main(String[] args) の形にそろえる |
| メイン・メソッドがクラスXのstaticではありません/Main method is not static | static がない | static を付ける |
| メイン・メソッドはクラスXのvoid型の値を返す必要があります/Main method must return a value of type void | 戻り値が void 以外 | void にして、結果は System.exit で返す |
| メイン・クラスXを検出およびロードできませんでした/Could not find or load main class X | クラス名のつづり違い、.class を付けた、クラスパスが違う |
クラス名だけを正しく指定する。場所は -cp で指定する |
コマンドライン引数argsを受け取る
引数を表示して確かめる
java クラス名 の後ろに空白で区切って書いた文字列が、順番に args[0]、args[1]…に入ります。確認用のプログラムを用意します。
public class ShowArgs {
public static void main(String[] args) {
System.out.println("個数: " + args.length);
for (int i = 0; i < args.length; i++) {
System.out.println("args[" + i + "] = [" + args[i] + "]");
}
}
}
$ java ShowArgs
個数: 0
$ java ShowArgs apple 100 true
個数: 3
args[0] = [apple]
args[1] = [100]
args[2] = [true]
ここからわかることを3つ挙げます。
| ポイント | 説明 |
|---|---|
| 引数なしでも args は null にならない | 長さ 0 の配列が渡される。args.length は 0 |
args[0] は最初の引数 |
C言語などと違い、プログラム名は入らない |
100 も true もすべて文字列 |
数値として使うには変換が必要 |
空白やクォートを含む引数
引数は空白で区切られます。空白を含む1つの値を渡したいときは、クォート(引用符)で囲みます。
$ java ShowArgs "hello world" 'a b' c\ d
個数: 3
args[0] = [hello world]
args[1] = [a b]
args[2] = [c d]
$ java ShowArgs '' ""
個数: 2
args[0] = []
args[1] = []
$ java ShowArgs '"quoted"' \$HOME "$HOME"
個数: 3
args[0] = ["quoted"]
args[1] = [$HOME]
args[2] = [/root]
クォートを解釈しているのは Java ではなくシェル(bash など)です。 Java のプログラムには、クォートが外れた後の文字列が届きます。そのため、OS やシェルによって書き方が少し変わります。
| やりたいこと | bash・zsh(Linux/macOS) | Windows のコマンドプロンプト |
|---|---|---|
| 空白を含む値を1つの引数にする | "hello world" または 'hello world' |
"hello world"(シングルクォートは区切りにならない) |
| 空文字を渡す | '' または "" |
"" |
| ダブルクォートそのものを渡す | '"quoted"' または \"quoted\" |
\"quoted\" |
| 変数を展開させずに渡す | '$HOME' または \$HOME |
—(%NAME% が展開の書き方) |
Windows の列は公式ドキュメントと一般的な仕様にもとづく記載で、手元では bash の結果のみ確認しています。
ワイルドカード(*)の展開
* を含む引数は、シェルがファイル名に展開してから Java に渡します。memo1.txt〜memo3.txt がある場所で実行した結果です。
$ java ShowArgs memo*.txt
個数: 3
args[0] = [memo1.txt]
args[1] = [memo2.txt]
args[2] = [memo3.txt]
$ java ShowArgs 'memo*.txt'
個数: 1
args[0] = [memo*.txt]
$ java ShowArgs nothing*.xyz
個数: 1
args[0] = [nothing*.xyz]
| 書き方 | bash での結果 |
|---|---|
memo*.txt(クォートなし) |
一致するファイル名に展開され、ファイルの数だけ引数になる |
'memo*.txt'(クォートあり) |
展開されず、memo*.txt という文字列のまま届く |
| 一致するファイルがない | bash の既定では、書いた文字列のまま届く |
「引数が1つのはずなのに args.length が増えている」ときは、* がシェルに展開されていないかを確認すると原因が見つかります。計算プログラムで掛け算の記号として * を渡したい場合も、'*' とクォートで囲みます。
日本語の引数
日本語の引数は、ロケール(言語と文字コードの設定)が UTF-8 のときにそのまま受け取れました。
$ LC_ALL=C.UTF-8 java ShowArgs 東京 "新 宿"
個数: 2
args[0] = [東京]
args[1] = [新 宿]
ロケールが未設定(LANG が空)の環境で実行したところ、日本語の引数が文字化けしました。このとき sun.jnu.encoding というプロパティは ANSI_X3.4-1968(ASCII)になっており、UTF-8 ロケールにすると UTF-8 になりました。コンテナやバッチ環境で日本語の引数が化けるときは、LANG や LC_ALL を UTF-8 のロケールに設定すると解決します。
引数の個数チェックと数値変換
チェックなしで書くとどうなるか
2つの整数を足すプログラムを、まずはチェックなしで書いてみます。
public class AddRaw {
public static void main(String[] args) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
System.out.println(args[0] + args[1]); // 文字列の連結
System.out.println(a + b); // 数値の足し算
}
}
$ java AddRaw 10 20
1020
30
args[0] + args[1] は文字列どうしの連結なので「1020」になり、Integer.parseInt で int に変換してから足すと「30」になります。args の中身はすべて String なので、計算に使うときは変換が必要です。
引数を付け忘れたり、数字以外を渡したりすると、例外で止まります。
$ java AddRaw
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
at AddRaw.main(AddRaw.java:3)
$ java AddRaw 10 abc
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:778)
at AddRaw.main(AddRaw.java:4)
| 例外 | 意味 | 起きる場面 |
|---|---|---|
| ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0 | 長さ 0 の配列の 0 番目を読もうとした | 引数なしで args[0] を読んだ |
| NumberFormatException: For input string: "abc" | 数値に変換できない文字列だった | abc、2.5(小数)、空文字などを parseInt に渡した |
直した後:個数チェックと使い方の表示
使う人にとって親切なのは、例外のスタックトレースではなく「使い方」を表示する形です。
public class Add {
public static void main(String[] args) {
if (args.length != 2) {
System.err.println("使い方: java Add <整数1> <整数2>");
System.exit(2);
}
try {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
System.out.println(a + " + " + b + " = " + (a + b));
} catch (NumberFormatException e) {
System.err.println("整数を指定してください: " + e.getMessage());
System.exit(1);
}
}
}
$ java Add 10 20
10 + 20 = 30
(終了コード 0)
$ java Add 10
使い方: java Add <整数1> <整数2>
(終了コード 2)
$ java Add 10 abc
整数を指定してください: For input string: "abc"
(終了コード 1)
ポイントは3つです。
- 最初に
args.lengthを確かめる:args[0]を読む前に個数をチェックする - エラーメッセージは
System.errに出す:通常の出力(System.out)と分けておくと、結果をファイルに保存するときにメッセージが混ざらない - 0 以外の終了コードで終わる:呼び出し元が「うまくいかなかった」と判断できる
型ごとの変換メソッド一覧
import java.nio.file.Path;
import java.time.LocalDate;
public class Conv {
enum Mode { FAST, SAFE }
public static void main(String[] args) {
int count = Integer.parseInt(args[0]);
long big = Long.parseLong(args[1]);
double rate = Double.parseDouble(args[2]);
boolean verbose = Boolean.parseBoolean(args[3]);
Mode mode = Mode.valueOf(args[4].toUpperCase());
LocalDate date = LocalDate.parse(args[5]);
Path file = Path.of(args[6]);
System.out.println(count + 1);
System.out.println(big * 2);
System.out.println(rate * 100);
System.out.println(verbose);
System.out.println(mode);
System.out.println(date.plusDays(1));
System.out.println(file.getFileName());
}
}
$ java Conv.java 5 3000000000 0.25 TRUE fast 2026-10-02 data/in.csv
6
6000000000
25.0
true
FAST
2026-10-03
in.csv
| 変換先 | メソッド | 変換できないとき |
|---|---|---|
| int | Integer.parseInt(s) |
NumberFormatException |
| long | Long.parseLong(s) |
NumberFormatException |
| double | Double.parseDouble(s) |
NumberFormatException |
| boolean | Boolean.parseBoolean(s) |
例外は出ず、true(大文字小文字は問わない)以外はすべて false |
| enum | 列挙型.valueOf(s) |
IllegalArgumentException(大文字小文字を区別するので toUpperCase() と組み合わせる) |
| 日付 | LocalDate.parse(s) |
DateTimeParseException(2026-10-02 の形式) |
| ファイルのパス | Path.of(s) |
— |
オプション形式(-v、-n 3)を自分で読み取る
-v や -n 3 のようなオプションも、args の中ではただの文字列です。小さなツールなら、次のように for 文と switch で読み取れます。
import java.util.ArrayList;
import java.util.List;
public class Opts {
public static void main(String[] args) {
boolean verbose = false;
int limit = 10;
List<String> files = new ArrayList<>();
for (int i = 0; i < args.length; i++) {
switch (args[i]) {
case "-v", "--verbose" -> verbose = true;
case "-n", "--limit" -> {
if (i + 1 >= args.length) {
System.err.println(args[i] + " には値が必要です");
System.exit(2);
}
limit = Integer.parseInt(args[++i]);
}
default -> files.add(args[i]);
}
}
System.out.println("verbose=" + verbose + " limit=" + limit + " files=" + files);
}
}
$ java Opts.java -v -n 3 a.txt b.txt
verbose=true limit=3 files=[a.txt, b.txt]
$ java Opts.java a.txt
verbose=false limit=10 files=[a.txt]
$ java Opts.java -n
-n には値が必要です
(終了コード 2)
オプションの数が増えてきたら、picocli や Apache Commons CLI といった引数解析用のライブラリを使うと、ヘルプ表示や型変換まで任せられます(この記事の環境では外部ライブラリを取得できないため、ライブラリの動作は未確認です)。
argsとシステムプロパティ・環境変数の違い
プログラムに外から値を渡す方法は、args のほかに2つあります。クラス名より前に書いたものは java コマンド自身へのオプション、後ろに書いたものが args です。
public class Prop {
public static void main(String[] args) {
System.out.println("プロパティ mode = " + System.getProperty("mode"));
System.out.println("環境変数 APP_ENV = " + System.getenv("APP_ENV"));
System.out.println("args = " + java.util.Arrays.toString(args));
}
}
$ APP_ENV=test java -Dmode=dev Prop -Dmode=prod x
プロパティ mode = dev
環境変数 APP_ENV = test
args = [-Dmode=prod, x]
クラス名の後ろに書いた -Dmode=prod はプロパティにならず、そのまま args に入っています。
| 渡し方 | 書く場所 | 受け取り方 | 向いている用途 |
|---|---|---|---|
| コマンドライン引数 | クラス名の後ろ | args[i] |
実行のたびに変わる値(対象ファイル、件数) |
| システムプロパティ | クラス名の前に -D名前=値 |
System.getProperty("名前") |
動作の切り替え、設定値 |
| 環境変数 | シェルや OS 側で設定 | System.getenv("名前") |
実行環境ごとの設定、パスワードなど表示させたくない値 |
終了コードとSystem.exit
main の戻り値は void ですが、プログラムは終わるときに 終了コード(exit code) という整数を呼び出し元に返します。0 が「正常に終わった」、0 以外が「何か問題があった」という意味で使われます。
public class ExitDemo {
public static void main(String[] args) {
String mode = args.length > 0 ? args[0] : "ok";
try {
switch (mode) {
case "exit3" -> System.exit(3);
case "throw" -> throw new IllegalStateException("想定外の状態");
default -> System.out.println("正常終了");
}
} finally {
System.out.println("finally を通過");
}
}
}
$ java ExitDemo
正常終了
finally を通過
(終了コード 0)
$ java ExitDemo exit3
(終了コード 3)
$ java ExitDemo throw
finally を通過
Exception in thread "main" java.lang.IllegalStateException: 想定外の状態
at ExitDemo.main(ExitDemo.java:7)
(終了コード 1)
| 終わり方 | 終了コード | finally |
|---|---|---|
| main が最後まで実行された | 0 | 実行される |
System.exit(n) を呼んだ |
n | 実行されない(その場で JVM が終了する) |
| 例外が main の外まで出た | 1 | 実行される |
| java コマンドが main を見つけられなかった | 1 | — |
System.exit を呼ぶと、その時点で JVM が終了に向かうため、finally ブロックは実行されませんでした。後始末が必要な処理があるときは、System.exit を main の最後の1か所にまとめると見通しがよくなります。
終了コードは、シェルで echo $?(Windows のコマンドプロンプトでは echo %ERRORLEVEL%)で確認できます。&& や || と組み合わせると、結果に応じて次のコマンドを実行できます。
$ java Add 10 20 && echo 成功のときだけ表示
10 + 20 = 30
成功のときだけ表示
$ java Add 10 || echo 終了コードが0以外のときだけ表示
使い方: java Add <整数1> <整数2>
終了コードが0以外のときだけ表示
終了コードの番号に言語としての決まりはありませんが、「0 は正常、1 は一般的なエラー、2 は使い方の間違い」という使い分けが広く見られます。値は 0〜255 の範囲に収めておくと、どの OS でもそのまま伝わります。
mainメソッドの応用
可変長引数 String... でも書ける
String[] args は String... args と書いても、java コマンドから同じように呼ばれます。
public class Vararg {
public static void main(String... args) { System.out.println("個数=" + args.length); }
}
$ java Vararg a b c
個数=3
可変長引数はコンパイルすると配列として扱われるためです。テストコードなどから Vararg.main("a", "b") のように直接呼びたいときに書きやすくなります。
mainは普通のメソッドとしても呼べる・複数のクラスに書ける
main は特別な名前ですが、中身は普通の static メソッドです。ほかのクラスから呼ぶことも、引数違いで同じ名前のメソッドを作る(オーバーロード)こともできます。
public class Two {
public static void main(String[] args) {
System.out.println("Two.main");
Other.main(new String[] {"from", "Two"}); // main は普通のメソッドとしても呼べる
}
public static void main(int n) { System.out.println("オーバーロード: " + n); }
}
class Other {
public static void main(String[] args) {
System.out.println("Other.main " + String.join(",", args));
}
}
$ java Two
Two.main
Other.main from,Two
$ java Other p q
Other.main p,q
main を持つクラスが複数あっても問題はなく、java コマンドで指定したクラスの main が入口になります。main(int n) のようなオーバーロードは、入口としては選ばれません。
java Foo.java の単一ファイル実行
Java 11 以降は、javac を使わずにソースファイルを直接実行できます。小さな確認にとても便利です。
$ java Hello.java
Hello, Java
$ java Script2.java 田中
こんにちは、田中
ファイル名の後ろに書いたものが args になります。クラスファイルは作られず、メモリ上でコンパイルして実行されます。注意点が1つあり、Java 21 では、ファイルの中で最初に書かれたクラスの main が実行されます。
// Script.java(main のないクラスを先に書いた場合)
class Helper {
static String greet(String n) { return "こんにちは、" + n; }
}
public class Script {
public static void main(String[] args) {
System.out.println(Helper.greet(args.length > 0 ? args[0] : "名無し"));
}
}
$ java Script.java (Java 21.0.10)
エラー: クラスにmain(String[])メソッドが見つかりません: Helper
$ java Script.java (Java 25.0.4.1)
こんにちは、名無し
Java 21 では、main を持つクラスをファイルの先頭に置くと動きます。同じファイルを Java 25.0.4.1 で実行すると、そのままで動きました。
単一ファイル実行で static を外した場合は、エラー文が少し変わります(Java 21.0.10)。
$ java NoStatic.java
エラー: 'mainメソッドが'public static'として宣言されていません
| 実行方法 | コマンド | 特徴 |
|---|---|---|
| コンパイルしてから実行 | javac Hello.java → java Hello |
クラスファイルが残る。複数ファイルの構成に向く |
| 単一ファイル実行 | java Hello.java |
1ファイルで完結する確認や小さなツールに向く |
| 複数ファイルのソース実行 | java Main.java(Java 22 以降) |
同じフォルダのほかのソースも自動で読み込む(JEP 458。手元の Java 21 では未実行) |
Java 25の簡略なmain(void main・インスタンスmain・IO)
Java 25 では、JEP 512「Compact Source Files and Instance Main Methods」が正式機能になり、入門時のコードがぐっと短く書けるようになりました。以下は OpenJDK 25.0.4.1 で実行した結果です。
クラスを書かずに void main() だけで動く
// Simple.java
void main() {
IO.println("Hello, Java 25");
var names = List.of("A", "B"); // import なしで List が使える
IO.println(names);
}
$ java Simple.java (Java 25.0.4.1)
Hello, Java 25
[A, B]
クラスの宣言も、public も static も String[] args もありません。IO.println は Java 25 で追加された java.lang.IO クラスのメソッドで、System.out.println の短い書き方として使えます。このような「クラス宣言のないソースファイル」はコンパクトソースファイルと呼ばれ、java.base モジュールの公開パッケージ(java.util など)が自動で import されるため、List をそのまま使えています。
コンパイルして中身を見ると、ファイル名から作られた final クラスになっていました。
$ javac -d o Simple.java && javap -cp o Simple
final class Simple {
Simple();
void main();
}
引数を受け取る・入力を読む
// WithArgs.java
void main(String[] args) {
IO.println("個数: " + args.length);
String name = args.length > 0 ? args[0] : IO.readln("名前を入力: ");
IO.println(greet(name));
}
String greet(String name) { // static なしのメソッドをそのまま呼べる
return "こんにちは、" + name + "さん";
}
$ java WithArgs.java 田中 (Java 25.0.4.1)
個数: 1
こんにちは、田中さん
$ echo 鈴木 | java WithArgs.java
個数: 0
名前を入力: こんにちは、鈴木さん
引数が必要なときは void main(String[] args) と書けば受け取れます。IO.readln はメッセージを表示して1行読み込むメソッドです。main がインスタンスメソッドなので、static を付けていない greet をそのまま呼べます。
通常のクラスでもインスタンスmainが使える
public class Inst {
private int count = 0;
void main() { // インスタンス main(static なし)
count++;
System.out.println("count=" + count);
}
}
$ java Inst.java (Java 25.0.4.1)
count=1
java コマンドが引数なしのコンストラクタでオブジェクトを作り、その main を呼んでいます。動かして確かめた選ばれ方は次のとおりです。
| 条件 | Java 25.0.4.1 での結果 |
|---|---|
public static void main(String[] args) と void main() の両方がある |
main(String[] args) が選ばれた |
public のない static void main(String[] args) |
動いた(Java 21 ではエラー) |
static のない public void main(String[] args) |
動いた(Java 21 ではエラー) |
引数のない public static void main() |
動いた(Java 21 ではエラー) |
| インスタンス main で、引数なしのコンストラクタがない | 「クラスに引数なしのコンストラクタが見つかりません: NoCtor」 |
private static void main(String[] args) |
「メイン・メソッドが…見つかりません」(private は対象外) |
public static int main(String[] args) |
「メイン・メソッドが…見つかりません」(void が必要な点は同じ) |
Java 21で同じコードを動かすと
$ java Simple.java (Java 21.0.10)
Simple.java:1: エラー: 無名クラスはプレビュー機能であり、デフォルトで無効になっています。
void main() {
^
(無名クラスを有効にするには--enable-previewを使用します)
Java 21 ではこの機能はプレビュー(試用)段階でした。java --enable-preview --source 21 Inst.java とすると、インスタンス main は Java 21 でも動くことを確認しました。ただし IO クラスは Java 21 にはありません。
| 項目 | Java 21 | Java 25 |
|---|---|---|
public static void main(String[] args) |
動く | 動く(これまでのコードはそのまま使える) |
void main()/インスタンス main |
プレビュー(--enable-preview が必要) |
正式機能 |
| クラス宣言のないソースファイル | プレビュー | 正式機能(コンパクトソースファイル) |
IO.println/IO.readln |
なし | あり(java.lang.IO) |
これまでの public static void main(String[] args) は Java 25 でもそのまま動きます。 既存のコードやフレームワークのサンプルはこの形で書かれているので、基本形の意味を理解したうえで、短い書き方も選べるようになった、と捉えるとよいでしょう。
つまずきやすい点のチェックリスト
| 症状 | 原因 | 直し方 |
|---|---|---|
| メイン・メソッドが見つかりません | public がない、Main と大文字、引数が String[] でない |
基本形と1語ずつ見比べる |
| メイン・クラスを検出およびロードできませんでした | クラス名の間違い、.class を付けた、実行する場所が違う |
クラス名だけを指定し、-cp で場所を指定する |
| ArrayIndexOutOfBoundsException | 引数を付けずに args[0] を読んだ |
先に args.length を確かめる |
| NumberFormatException | 数字以外や小数を parseInt に渡した | try-catch で受けて使い方を表示する。小数は parseDouble |
| 足し算が「1020」になる | 文字列のまま + している |
数値に変換してから足す |
| 引数の個数が思ったより多い | * がシェルに展開された、空白で分かれた |
クォートで囲む |
-Dname=value が効かない |
クラス名の後ろに書いている | クラス名の前に書く |
| System.exit の後の finally が動かない | exit はその場で JVM を終了させる | exit は main の最後にまとめる |
よくある質問
Q. args という名前は変えてもよいですか?
A. 変えられます。argv でも params でも動きます(argv で動くことを確認済みです)。ただし、ほとんどの Java のコードが args と書いているので、そろえておくと読む人が迷いません。
Q. mainメソッドはどのクラスに書けばよいですか?
A. どのクラスに書いても構いません。java コマンドで指定したクラスの main が入口になります。入口専用のクラス(Main や App など)を1つ用意し、そこから他のクラスを呼ぶ構成がよく使われます。
Q. 引数を付けずに実行したとき、args は null ですか?
A. null ではなく、長さ 0 の配列です。args.length は 0 になり、args[0] を読むと ArrayIndexOutOfBoundsException になります。args == null のチェックは不要で、args.length を確かめれば十分です。
Q. IDE(Eclipse や IntelliJ IDEA)ではコマンドライン引数をどう渡しますか?
A. 実行構成(Run Configuration)の「プログラムの引数(Program arguments)」欄に、コマンドラインと同じように空白区切りで書きます。-D で始まるシステムプロパティは「VM 引数(VM options)」欄に書きます。
まとめ
public static void main(String[] args)はプログラムの入口:java コマンドがこの形を探して呼び出す- public は外から呼べる、static はオブジェクトなしで呼べる、void は値を返さない:1語でも外すと Java 21 では「メイン・メソッドが見つかりません」などのエラーになる
- args はコマンドライン引数の配列:引数なしなら長さ 0。中身はすべて文字列なので、数値は
Integer.parseIntなどで変換する args.lengthを先に確かめ、使い方を System.err に表示する:例外で止まるより親切なツールになる- 空白・クォート・
*を処理するのはシェル:1つの値として渡したいときはクォートで囲む - 結果は終了コードで返す:正常は 0、問題があれば
System.exit(1)など 0 以外 - Java 25 では
void main()とIO.printlnで短く書ける:これまでの基本形もそのまま使える
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Java public static void mainの意味とargsの使い方」
株式会社RJCでは、Javaのmainメソッドのような基礎を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。