質問
のメソッドシグニチャーのJava main() 方法:
public static void main(String[] args){
...
}
ある理由のためにこのメソッドがstatic?
解決
メソッドは静的です。さもないと、あいまいさが生じるからです。どのコンストラクターを呼び出すべきですか?特に、クラスが次のようになっている場合:
public class JavaClass{
protected JavaClass(int x){}
public void main(String[] args){
}
}
JVMはnew JavaClass(int)
を呼び出す必要がありますか? x
には何を渡す必要がありますか?
そうでない場合、JVMはコンストラクターメソッドを実行せずにJavaClass
をインスタンス化する必要がありますか?それは、クラス全体を特別なケースにするからです-初期化されていないインスタンスがあり、呼び出される可能性のあるすべてのメソッドでそれをチェックする必要がある場合があります。
JVMがエントリポイントが呼び出される前にクラスをインスタンス化する必要があるという意味では、エッジケースと曖昧さが多すぎます。それがmain
が静的である理由です。
public
が常に<=>とマークされている理由がわかりません。
他のヒント
こちらです。はもちろん、メイン名()の引数で渡され、純粋な約に従います。
実際のjava.exe (javaw.exe Windowsでは、何が本当に起きてやフィラバルセロナ、カンプが、JNI(Java Native Interface)に発信します。これらの通話の負荷のDLLた、JVM(そう-java.exe なのJVM).JNIのツールを使用していた時の仮想マシンの世界、世界のC,C++など---。逆の場合も同様である-できない(少なくとも私の知る)は、実際には、JVMエラーパラメータを用いJNI.
基本的には、java.exe 超簡単Cアプリを解析し、コマンドラインを通じて、新しい文字配列のJVM催者の引数を解析し、クラス名として指定を含むmain()を使用してJNI呼べるメイン()メソッドは、次を呼び出し、本()メソッドを渡れても、新しく作成された文字列の配列としてのパラメータとします。これは非常にいい場からの反射Javaで使用して紛らわしい外観の名のネイティブ関数呼び出します。
この完全に合法で書版java.exe (ソース配布されているものであり、JDK)という全く異なります。実際、それが私たちがなすべてのJavaアプリ.
当社のJavaアプリケーションはランチアタックを当てる主としていま独自のアイコンやプロセス名だけでお手軽にその他の状況というものmain()の呼び出かい(例えば、一例としてCOM相互運用性を実際にパスCOM取扱いにmain()の代わりに文字列配列)の
なので、長短:の理由で静b/cるので便利です。の理由で必要なことしなければならなかったものを、主に()がしっか昔のC(当時の名称機能 た 重要).はないかと思うjava.exe が容だけを指定し完全指定の主なメソッド名、だけでなく、クラス(java com.mycompany.Foo.someSpecialMain)-もうけることが難しくなってるIdeのメールを自動検出のlaunchable'授業プロジェクト.
main()
、C++
、およびC#
のJava
メソッドは静的です
その後、オブジェクトをインスタンス化する必要なしにランタイムエンジンによって で呼び出すことができるため、<=>の本文のコードが残りを実行します。
なぜpublic static void main(String [] args)?
これが、Java言語の設計方法とJava仮想マシンの設計方法と記述方法です。
Oracle Java言語仕様
第12章実行-セクション12.1.4呼び出しを確認してください。 Test.main :
最後に、クラスTestの初期化の完了後(その他の結果的なロード、リンク、および初期化が行われている可能性がある間)、Testのメソッドmainが呼び出されます。
mainメソッドは、public、static、およびvoidとして宣言する必要があります。文字列の配列である単一の引数を受け入れる必要があります。このメソッドは次のいずれかとして宣言できます
public static void main(String[] args)
または
public static void main(String... args)
Oracle Java Virtual Machine Specification
第2章Javaプログラミング言語の概念-セクション2.17をご覧ください。実行:
Java仮想マシンは、指定されたクラスのメソッドmainを呼び出し、それに単一の引数(文字列の配列)を渡すことで実行を開始します。これにより、指定されたクラスがロードされ(<!>#167; 2.17.2)、使用される他のタイプにリンクされ(<!>#167; 2.17.3)、初期化されます(<!>#167; 2.17。 4)。メソッドmainは、public、static、およびvoidとして宣言する必要があります。
Oracle OpenJDKソース
ソースjarをダウンロードして抽出し、JVMの記述方法を確認します。コマンド../launcher/java.c
の背後にあるネイティブCコードが含まれているjava [-options] class [args...]
を確認してください:
/*
* Get the application's main class.
* ... ...
*/
if (jarfile != 0) {
mainClassName = GetMainClassName(env, jarfile);
... ...
mainClass = LoadClass(env, classname);
if(mainClass == NULL) { /* exception occured */
... ...
/* Get the application's main method */
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
"([Ljava/lang/String;)V");
... ...
{ /* Make sure the main method is public */
jint mods;
jmethodID mid;
jobject obj = (*env)->ToReflectedMethod(env, mainClass,
mainID, JNI_TRUE);
... ...
/* Build argument array */
mainArgs = NewPlatformStringArray(env, argv, argc);
if (mainArgs == NULL) {
ReportExceptionDescription(env);
goto leave;
}
/* Invoke main method. */
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
... ...
単純に、アプリケーションのエントリポイントとしてstatic
は必要ないふりをしましょう。
アプリケーションクラスは次のようになります。
class MyApplication {
public MyApplication(){
// Some init code here
}
public void main(String[] args){
// real application code here
}
}
OOでは、コンストラクタはインスタンスが適切に初期化されていることを確認するだけなので、コンストラクタコードとmain
メソッドの区別が必要です。初期化後、インスタンスは目的の<!> quot; service <!> quot;に使用できます。完全なアプリケーションコードをコンストラクタに配置すると、それが台無しになります。
したがって、このアプローチでは、アプリケーションに対して 3つの異なる契約が強制されます。
- デフォルトのコンストラクタである必要があります 。そうしないと、JVMは呼び出すコンストラクターと提供するパラメーターを認識しません。
-
abstract
メソッド 1 でなければなりません 。さて、これは驚くことではありません。 - クラスはであってはなりません。そうしないと、JVMはそれをインスタンス化できませんでした。
<=>アプローチでは、 1つの契約のみが必要です:
- <=>メソッド 1 が必要です。
ここでは、<=>も複数のコンストラクターも重要ではありません。
Javaはユーザーにとって単純な言語である ように設計されているため、アプリケーションのエントリポイントが one コントラクトと 3つの独立した脆弱な契約を使用した複雑な方法ではありません。
注意:この引数は、JVM内またはJRE内の単純性に関するではありません。この議論は、ユーザーのシンプルさに関するものです。
1 ここでは、完全な署名は1つの契約としてのみカウントされます。
そうでない場合、複数のコンストラクタがある場合、どのコンストラクタを使用する必要がありますか?
mainメソッドが呼び出される前は、オブジェクトはインスタンス化されていません。 staticキーワードがあると、最初にオブジェクトを作成せずにメソッドを呼び出すことができます。
それ以外の場合は、実行するオブジェクトのインスタンスが必要です。ただし、通常はmain()関数(ブートストラップ)のタスクであるため、最初にオブジェクトを構築せずに最初から呼び出す必要があります。通常、これらの引数/プログラムパラメータを使用して、引数を解析し、オブジェクトを構築します。
public static void main(String args[])
の意味は何ですか?
-
public
はアクセス指定子であり、JVM(Java Virtual Machine。 など、だれでもアクセス/呼び出しできます。
-
static
により、クラスのオブジェクトが作成される前にmain()
を呼び出すことができます。オブジェクトが作成される前にvoid
がJVMによって呼び出されるため、これは必要です。静的であるため、クラスを介して直接呼び出すことができます。class demo { private int length; private static int breadth; void output(){ length=5; System.out.println(length); } static void staticOutput(){ breadth=10; System.out.println(breadth); } public static void main(String args[]){ demo d1=new demo(); d1.output(); // Note here output() function is not static so here // we need to create object staticOutput(); // Note here staticOutput() function is static so here // we needn't to create object Similar is the case with main /* Although: demo.staticOutput(); Works fine d1.staticOutput(); Works fine */ } }
同様に、オブジェクトを作成する必要がないように、ユーザー定義メソッドにはいつかstaticを使用します。
-
String[] args
は、args
メソッドが宣言されていることを示します 値を返しません。 -
String
は、<=>メソッドの唯一のパラメーターを指定します。<=>-クラスタイプ<=>のオブジェクトの配列を含むパラメーター。
これらのことをもっと簡単な方法で説明させてください:
public static void main(String args[])
アプレットを除くすべてのJavaアプリケーションは、main()
から実行を開始します。
キーワードpublic
は、クラスの外部からメンバーを呼び出すことができるアクセス修飾子です。
static
が使用されるのは、そのクラスの特定のインスタンスをインスタンス化することなくvoid
を呼び出すことができるためです。
<=>は、<=>が値を返さないことを示します。
さまざまな種類のアプレット、ミッドレット、サーブレット、およびBeanが構築され、ライフサイクルメソッドが呼び出されます。 mainの呼び出しは、メインクラスに対して行われるすべての操作であるため、複数回呼び出されるオブジェクトに状態を保持する必要はありません。 mainを別のクラスに固定することは非常に普通です(素晴らしいアイデアではありませんが)、クラスを使用してメインオブジェクトを作成する方法が妨げられます。
これは単なる慣例ですが、おそらく他の方法よりも便利です。静的メインでは、Javaプログラムを呼び出すために知っておく必要があるのは、クラスの名前と場所だけです。静的でない場合は、そのクラスをインスタンス化する方法を知っているか、クラスに空のコンストラクターがあることを要求する必要があります。
mainメソッドが静的でない場合、プログラムの外部からメインクラスのオブジェクトを作成する必要があります。どうしますか?
java
コマンドを使用してJava仮想マシン(JVM)を実行すると、
java ClassName argument1 argument2 ...
アプリケーションを実行するときは、上記のようにjavaコマンドの引数としてクラス名を指定します
JVMは、指定したクラスのメインメソッドを呼び出そうとします
<!>#8212;この時点では、クラスのオブジェクトは作成されていません。
main
を静的として宣言allows
JVMをinvoke
メインwithout
作成する クラスのinstance
。
コマンドに戻りましょう
ClassName
は、実行するクラスを指示するJVMへのcommand-line argument
です。 ClassNameの後に、JVMがアプリケーションに渡すコマンドライン引数としてlist of Strings
(スペースで区切る)を指定することもできます。 -そのような引数は、アプリケーションを実行するためのオプション(ファイル名など)を指定するために使用される可能性があります-これが、メイン
String[] args
というパラメーターがある理由です
キーワード 'static'はメインメソッドをクラスメソッドにし、クラスメソッドはそのコピーを1つだけ持ち、すべてで共有でき、参照用のオブジェクトを必要としないと思います。したがって、ドライバクラスがコンパイルされると、メインメソッドを呼び出すことができます。 (私はちょうどJavaのアルファベットレベルです、私が間違っている場合は申し訳ありません)
main()は静的です。アプリケーションのライフサイクルのその時点では、オブジェクトがまだインスタンス化されていないため、アプリケーションスタックは本質的に手続き型です。
これはきれいな状態です。オブジェクトは宣言されていなくても、この時点でアプリケーションは実行されています(手続き型およびオブジェクト指向コーディングパターンがあることを思い出してください)。開発者は、オブジェクトのインスタンスを作成し、内部でコンパイルされたコードに応じて、アプリケーションをオブジェクト指向ソリューションに変換します。
オブジェクト指向は、何百万という明白な理由で優れています。しかし、ほとんどのVB開発者が<!> quot; goto <!> quot;のようなキーワードを定期的に使用していた時代は終わりました。コード内。 <!> quot; goto <!> quot; VBの手続き型コマンドで、オブジェクト指向のメソッド呼び出しに置き換えられます:メソッド呼び出し。
静的なエントリポイント(メイン)を純粋な自由として見ることもできます。 Javaがオブジェクトをインスタンス化し、実行時にそのインスタンスのみを表示するのに十分なほど異なっていた場合、手続き型アプリを作成することはできません。 Javaに聞こえるかもしれませんが、手続き型アプローチを必要とする多くのシナリオが存在する可能性があります。
これはおそらく非常にあいまいな返信です。覚えておいてください、<!> quot; class <!> quot;相互に関連するコードのコレクションのみです。 <!> quot;インスタンス<!> quot;そのクラスの孤立した、生きている、呼吸する自律的な世代です。
プロトタイプpublic static void main(String[])
は、 JLS :
mainメソッドは、public、static、およびvoidとして宣言する必要があります。宣言された型がStringの配列である仮パラメーター(<!>#167; 8.4.1)を指定する必要があります。
JVM仕様 5.2。仮想マシンの起動読み取り可能:
Java仮想マシンは、ブートストラップクラスローダー(<!>#167; 5.3.1)を使用して、実装依存の方法で指定される初期クラスを作成することにより起動します。次に、Java仮想マシンは初期クラスをリンクし、初期化して、パブリッククラスメソッドvoid main(String [])を呼び出します。このメソッドの呼び出しは、それ以降のすべての実行を促進します。メインメソッドを構成するJava仮想マシンの命令を実行すると、追加のクラスとインターフェイスのリンク(およびその結果としての作成)、および追加のメソッドの呼び出しが発生する可能性があります。
おもしろいことに、JVM仕様では、メインメソッドが静的である必要があることは言及されていません。 ただし、仕様では、Java仮想マシンが2ステップ前に実行することも示されています。
クラスまたはインターフェイスの初期化は、そのクラスまたはインターフェイスの初期化メソッドの実行で構成されます。
クラスまたはインターフェースの初期化メソッドが定義されています:
クラスまたはインターフェースには最大で1つのクラスまたはインターフェース初期化メソッドがあり、そのメソッドを呼び出すことで初期化(<!>#167; 5.5)されます。クラスまたはインターフェースの初期化メソッドは、特別な名前
<clinit>
を持ち、引数をとらず、無効です。
そして、クラスまたはインターフェースの初期化メソッドは、次のように定義されたインスタンスの初期化メソッドとは異なります:
Java仮想マシンのレベルでは、Javaプログラミング言語(JLS <!>#167; 8.8)で記述されたすべてのコンストラクターは、特別な名前
<init>
を持つインスタンス初期化メソッドとして表示されます。
JVMは、実際にはコンストラクターであるインスタンス初期化メソッドではなく、クラスまたはインターフェースの初期化メソッドを初期化します。 したがって、メインメソッドを呼び出す前にインスタンスが作成されないという事実によって暗示されるため、メインメソッドがJVM仕様で静的である必要があることを言及する必要はありません。
最近、同様の質問がProgrammers.SEに投稿されました
- コンストラクタではなく、JavaおよびC#の静的なメインメソッドを使用する理由
(特に)JavaとC#が静的メソッドをエントリポイントとして持つことにした理由について、プライマリソースまたはセカンダリソースからの明確な回答を探しています<!>#8211;エントリポイントが適切なコンストラクターである
Application
クラスのインスタンスによってアプリケーションインスタンスを表すのではなく、
TL; DR 受け入れられた回答の一部は、
Javaでは、
public static void main(String[] args)
の理由は
- Gosling が欲しい
- Cの経験者(Javaではない)が書いたコード
- PostScript を NeWS
<!> nbsp;
C#の場合、推論はいわば推移的に類似です。言語設計者は、プログラムエントリポイント Javaから来たプログラマに馴染みのある構文。 C#アーキテクトとして Anders Hejlsbergは次のように述べています、... C#での私たちのアプローチは、単にJavaプログラマーに代わるものを提供することでした...
...
これは単なる慣例です。 JVMは、もしそれが慣例であれば、静的でないmainメソッドを確実に処理できます。結局、クラスで静的初期化子を定義し、main()メソッドに到達する前に無数のオブジェクトをインスタンス化できます。
public
キーワードはアクセス修飾子であり、プログラマが制御できるようにします
クラスメンバーの可視性。クラスメンバの前にprivate
が付いている場合、それは
メンバーは、それが宣言されているクラスの外部のコードからアクセスできます。
main()
の反対はstatic
で、クラスの外部で定義されたコードがメンバーを使用することを防ぎます。
この場合、void
は<=>として宣言する必要があります。
プログラムの起動時にクラス外のコードによって。
キーワード<=>は <=>クラスの特定のインスタンスをインスタンス化することなく呼び出されます。オブジェクトが作成される前に<=>がJavaインタープリターによって呼び出されるため、これが必要です。
キーワード<=>は、<=>が値を返さないことをコンパイラに伝えるだけです。
アプリケーションへの真のエントリポイントは静的メソッドです。 Java言語がインスタンスメソッドを<!> quot; entry point <!> quot;としてサポートしている場合、ランタイムはそれをオブジェクトのインスタンスを構築する静的メソッドとして内部的に実装し、その後インスタンスメソッドを呼び出す必要があります。
それが邪魔にならないように、次の3つのオプションの特定の1つを選択する理由を調べます。
- A
static void main()
今日のように。 - 新しく構築されたオブジェクトで呼び出されるインスタンスメソッド
void main()
。 - エントリポイントとして型のコンストラクターを使用する(たとえば、エントリクラスが
Program
の場合、実行は実質的にnew Program()
で構成されます)。
内訳:
main()
- 囲んでいるクラスの静的コンストラクターを呼び出します。
- 静的メソッド
new ClassName()
を呼び出します。
<=>
- 囲んでいるクラスの静的コンストラクターを呼び出します。
- <=>を効果的に呼び出して、囲んでいるクラスのインスタンスを構築します。
- インスタンスメソッド<=>を呼び出します。
<=>
- 囲んでいるクラスの静的コンストラクターを呼び出します。
- クラスのインスタンスを構築します(その後、何もせずに単に戻ります)。
根拠:
これについては逆の順序で行きます。
Javaの設計目標の1つは、優れたオブジェクト指向プログラミングの実践を強調すること(可能な場合は必須にすること)であることに留意してください。このコンテキストでは、オブジェクトのコンストラクターはオブジェクトを初期化しますが、オブジェクトの動作を担当するべきではありません。したがって、エントリポイント<=>を指定した仕様は、<!> quot; ideal <!> quotの設計に例外を強制することにより、新しいJava開発者の状況を混乱させます。すべてのアプリケーションのコンストラクタ。
<=>をインスタンスメソッドにすることで、上記の問題は確実に解決されます。ただし、<=>メソッドの署名と同様に、エントリクラスのコンストラクタの署名をリストする仕様を要求することにより、複雑さが生じます。
要約すると、 <=>を指定すると、動作をメソッドに配置するという原則を順守しながら、最も複雑性の低い仕様が作成されます。それ自体がクラスのインスタンスを構築し、インスタンスメソッドを呼び出す<=>メソッドを実装することがいかに簡単かを考えると、インスタンスメソッドとして<=>を指定することには実質的な利点はありません。
static-JVMがmainメソッドを呼び出すとき、呼び出されるクラスに対してオブジェクトが存在しないため、クラスからの呼び出しを許可する静的メソッドが必要です。
オブジェクトがインスタンス化される前にJVMがmainメソッドを呼び出すかどうかわかりません...しかし、main()メソッドが静的である理由ははるかに強力です... JVMのmainメソッドを呼び出すときクラス(たとえば、Person)。 <!> quot; Person.main() <!> quot;で呼び出します。ご覧のとおり、JVMはクラス名でそれを呼び出します。そのため、main()メソッドは、JVMからアクセスできるように静的でパブリックであると想定されています。
お役に立てば幸いです。もしそうなら、コメントして教えてください。
静的メソッドはオブジェクトを必要としません。直接実行されるため、mainは直接実行されます。
mainメソッドではインスタンス化が行われないため、mainメソッドで静的キーワードが使用されます。 しかし、mainメソッドで静的キーワードを使用する結果、呼び出しではなくオブジェクトが構築されます。 jvmコンテキストでは、クラスがロードされるときにメモリが作成されます。すべての静的メンバーはそのメモリに存在します。メインを静的にすると、メモリ内にあり、jvm(class.main(..))にアクセスできるようになるため、ヒープを作成する必要なくメインメソッドを呼び出すことができます。
ここで見られるように、これは単なる慣例です:
メソッドは publicおよびstaticとして宣言する必要があります。 値。String配列をパラメーターとして受け入れる必要があります。デフォルトでは、 最初の非オプション引数は、呼び出されるクラスの名前です。 完全修飾クラス名を使用する必要があります。 -jarオプションが 指定されている場合、最初の非オプション引数はJARアーカイブの名前です アプリケーションのクラスおよびリソースファイルを含む Main-Classマニフェストヘッダーで示される起動クラス。
http://docs.oracle。 com / javase / 1.4.2 / docs / tooldocs / windows / java.html#description
public static voidキーワードは、Java仮想マシン(JVM)インタープリターがプログラムのメインメソッドを呼び出して、クラスのインスタンス(静的)を作成せずにプログラム(パブリック)を開始でき、プログラムが返らないことを意味します終了時にJava VMインタープリター(void)にデータを送信します。
基本的に、オブジェクトに関連するタスクを実行しない静的メンバーとしてこれらのデータメンバーとメンバー関数を作成します。メインメソッドの場合、オブジェクトを作成しているかどうかに関係なくメインメソッドが常に実行されるため、オブジェクトとは何の関係もないため、静的メソッドとして作成しています。
Javaで静的として宣言されたメソッドは、クラス自体に属します。
繰り返しますが、特定のクラスの静的メソッドには、Class_name.method_name();
したがって、静的メソッドにアクセスする前にクラスをインスタンス化する必要はありません。
したがって、main()メソッドはstatic
として宣言されているため、そのクラスのオブジェクトを作成せずにアクセスできます。
メインメソッドが存在するクラスの名前でプログラムを保存するため(またはプログラムの実行を開始する場所から、main()
method()(Advanced Level)のないクラスに適用可能)。上記の方法で:
Class_name.method_name();
メインメソッドにアクセスできます。
簡単に言うと、プログラムがコンパイルされると、次のようなString
引数を持つmain(String args[])
メソッドが検索されます:<=>言及されたクラス(プログラムの名前による)で、最初からそのクラスをインスタンス化するスコープがないため、main()メソッドはstaticとして宣言されています。
java.sun.com から(詳細情報があります)サイトで):
メインメソッドは静的で、Java VMインタープリターに、最初にコントロールクラスのインスタンスを作成せずにクラスを開始する方法を提供します。コントロールクラスのインスタンスは、プログラムの起動後にmainメソッドで作成されます。
私の理解では、常に、静的メソッドと同様に、関連するクラスのインスタンスを作成せずにメインメソッドを呼び出すことができ、プログラム内で他のメソッドの前に実行できます。静的でない場合は、呼び出す前にオブジェクトをインスタンス化する必要があります。これは、「鶏と卵」の問題を引き起こします。メインメソッドは、通常、プログラムの開始時にオブジェクトをインスタンス化するために使用するものです。 p>