Java のメイン メソッドに常に引数が必要なのはなぜですか? String[] args
引数を使用するときだけ書くのではなく、毎回書く必要があるのはなぜですか?
このようなメソッドは、Main method not found
コンパイラ エラーを生成します。main メソッドには引数を使用しないため、これを許可する必要があります。
public static void main()
{
}
これは面接の質問ではありません。プログラミングをしていてふと思いつきました。
基本的に、4つの答えがあります。
それが設計された方法だからです。ええ、私はそれが循環論法であることを知っています。しかし、要点は、これが現状であり、変わらないということです。したがって、独自の言語を設計することを計画していない限り、問題は議論の余地があります。
デザインのクリーンさ(別名DRY原則)。1つが仕事をすることができるとき、2つのエントリポイント署名を指定しないでください。そして明らかに、それは可能です。
セマンティックなシンプルさ。(仮に)Javaがvoid main(String[])
エントリポイントとエントリポイントの両方をサポートしたと仮定しますvoid main()
。クラスが両方のメソッドを定義した場合はどうなりますか?それはエラーですか?そうでない場合、あいまいさが存在する場合、どちらが優先されますか?これはもう混乱していますか?
を認識するだけvoid main(String[])
で、JLSはその問題を回避します1。
これは、標準のCおよびC++エントリポイント署名に類似しています。(確かに、一部のC / C ++ランタイムは、他の非標準のエントリポイントもサポートしています...しかし、それは必ずしも良いことではありません... IMO。)
これは、別の方法でそれを行うことが明らかに間違っていたことを意味するものではありません。たとえば、C#は代替の署名を提供し、開発者に別の方法でエントリポイントを指定するように要求することで、あいまいさの問題に対処します。
FWIW、このウィキペディアのページでは、多くの言語で「メイン」の方法について説明しています。
1-それでも、Javaを初めて使用する人は、複数のエントリポイントが機能するはずだと(誤って)推測し、試して、驚きを感じるかもしれないという「問題」があります。しかし、「当て推量によるプログラミング」に対応できるデザインはないと思います。
アプリケーションを実行するjava
ツールは、特定の署名を持つ を検索するためmain
、正しい署名を呼び出していることがわかります。Java にはメソッドのオーバーロードがあるため、メソッドを検索するときは、かなり完全なシグネチャを指定する必要があります。確かに、このjava
ツールはもっと複雑なことを行うことができます (特定の署名を探し、それが見つからない場合は、いずれかを探し、main
1 つしか見つからない場合はそれを呼び出します)、それは Java 設計者が行うことを決定したことではありません (主観的に、FWIW、それが最善だと思います—シンプルにしてください)。
詳細については、Java 言語仕様のChapter 12: Executionを参照してください。main
Java が可変引数リストを取得した時点で、2 つの異なる方法で宣言できるようになったことに注意してください。
public static void main(String[] args)
// or
public static void main(String... args)
JVM が Java プログラムの実行を開始すると、このシグネチャ (文字列配列) を持つメイン メソッドを検索します。
それはまさに彼らが設計した方法です。その当然の結果として、そのいとこ (C#) がパラメーターの有無にかかわらず Main メソッドを許可する理由を尋ねるかもしれません。それは彼らが設計した方法です。
そこには重大な根拠はありません。各言語の設計者は、どの原則に従うべきかを好みます。当面の間、それは私たちが推測したり、固執したりする場合があります(時には私たちの思い通りにならないこともあります)。
うーん...これは私が今使っているOSを思い出させます。OS X Lion より前のバージョンでは、ウィンドウの右下隅でのみサイズを変更できました。OS の任意のウィンドウの隅でサイズを変更する機能を最終的に導入するまで、28 年以上待ちました。
私は Mac OS が好きすぎて、ウィンドウのサイズを変更できるのは 1 つの隅だけであるべきだという前に、彼らのスタンスを擁護するつもりはありません。熱心であることと、盲目的に固執することは別のことです。
したがって、批判的思考を実践し、Java のメイン メソッド シグネチャが唯一の正しい方法であると盲目的に信じないことは良いことです。
C#
var p = new {
Lastname = "Lennon",
Firstname = "John",
PlacesBeen =
new[]
{
new { City = "Liverpool", Country = "England" },
new { City = "New York", Country = "US" },
new { City = "Tokyo", Country = "Japan" }
}
};
return Json(p);
Javascript:
var p = {
"Lastname" : "Lennon",
"Firstname" : "John",
"PlacesBeen" :
[
{ "City" : "Liverpool", "Country" : "England" },
{ "City" : "New York", "Country" : "US" },
{ "City" : "Tokyo", "Country" : "Japan" }
]
};
その結果、C# のファーストクラスのプロパティ (メソッドに押し付けられていない) とコレクション初期化子を使用すると、コードが簡潔で整然としたものになるだけでなく、ほとんどの開発者が現在使用しているデータ交換形式、つまり JSON に非常に似ています。
Java のオブジェクト初期化構文は、JSON スタイルとはかけ離れています。この点に関して、Java の設計上の決定 (プロパティの構文/設計など) を擁護するつもりはありません :-)
したがって、Java のプロパティー構文/設計に関する Java 言語設計者の設計上の決定を擁護しないのと同じ流れで、私は擁護しませんpublic static void main(String[] args)
ツ</p>
Java プログラムを実行しようとすると、JVM は文字列配列を引数としてメイン メソッドを検索し、そこからプログラムの実行を開始します。あなたが与えられたメソッドはその署名を持っていないので、例外が発生しますNo main method found
Java はこの習慣を c/c++ から「コピー」し、 java.c にハードコーディングしたと思います。
/* Get the application's main method */
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
if (mainID == NULL) {
if ((*env)->ExceptionOccurred(env)) {
ReportExceptionDescription(env);
} else {
message = "No main method found in specified class.";
messageDest = JNI_TRUE;
}
goto leave;
}
Java はこのように設計されています。文字列 args[] を書かないと、プログラムはコンパイルされますが、実行されません。