なぜJavaメインメソッドは静的なのですか?


505

Java main()メソッドのメソッドシグネチャは次のとおりです。

public static void main(String[] args){
    ...
}

このメソッドが静的である理由はありますか?


1
この場合、メソッドのシグネチャは言うべきではありません。この用語はメソッド名とそのパラメータのみを指しているためです
Andrew Tobilko

Javaは、Cプログラマに馴染みがあるように意図的に設計されています。これは、Cの規則に非常に近いものです。
–ThorbjørnRavn Andersen 2016

回答:


337

それ以外の場合はあいまいさがあるため、メソッドは静的です:どのコンストラクターを呼び出す必要がありますか?特にクラスが次のようになっている場合:

public class JavaClass{
  protected JavaClass(int x){}
  public void main(String[] args){
  }
}

JVMは呼び出す必要がありますnew JavaClass(int)か?それは何のために渡すべきxですか?

そうでない場合、JVM JavaClassはコンストラクタメソッドを実行せずにインスタンス化する必要がありますか?クラス全体が特殊なケースになるので、そうすべきではないと思います。初期化されていないインスタンスがあり、呼び出される可能性のあるすべてのメソッドでそれを確認する必要がある場合があります。

エントリポイントが呼び出される前に、JVMがクラスをインスタンス化しなければならないという意味では、エッジケースとあいまいさが多すぎます。それmainが静的である理由です。

なぜmainいつもマークされてpublicいるのか分かりません。


4
インターフェイスを実装しても、インスタンス化の問題は解決されません。
Jacob Krall、

26
私は個人的にそれがpublic static void mainエントリーポイントのマーカーとして機能するのが好きです–公開パラメーターなしコンストラクターは「これはおそらくエントリーポイントです!」と叫びません。同じやり方で。
ジェイコブクラル

5
@EdwinDalorzo-エントリポイントクラスを強制的にインスタンス化することで何が得られますか?静的メソッドを呼び出すと、クラスへの負荷が最小になります。それがあなたのデザインにとってより理にかなっているなら、それ自体をインスタンス化するのは自由です
David Harkness

18
「どのコンストラクターを呼び出す必要がありますか?」それはおそらく問題でさえありますか?どちらmainを呼び出すかについても、同じ「問題」があります。奇妙なことに(あなたにとって)、JVMはこれを適切に管理します。
コンラートルドルフ

9
mainメソッドは、ランタイムエンジンであるJVMからアクセスする必要があるため、常にパブリックです。
gthm 2013

398

これは単なる慣習です。実際、名前main()と渡された引数でさえ、純粋に慣例です。

java.exe(またはWindowsではjavaw.exe)を実行すると、実際に起こっているのは、いくつかのJava Native Interface(JNI)呼び出しです。これらの呼び出しは、実際にはJVMであるDLLをロードします(そうです-java.exeはJVMではありません)。JNIは、仮想マシンの世界とC、C ++などの世界をつなぐ必要があるときに使用するツールです。逆も当てはまります。実際には、(少なくとも私の知る限り) JNIを使​​用せずに実行されているJVM。

基本的に、java.exeはコマンドラインを解析し、JVMに新しい文字列配列を作成してそれらの引数を保持し、main()を含むと指定したクラス名を解析し、JNI呼び出しを使用して、 main()メソッド自体、次にmain()メソッドを呼び出し、新しく作成された文字列配列をパラメーターとして渡します。これは、Javaからのリフレクションを使用する場合と非常によく似ています。代わりに、紛らわしい名前のネイティブ関数呼び出しを使用するだけです。

独自のバージョンのjava.exe(ソースはJDKとともに配布されます)を作成し、まったく異なるものを実行することは完全に合法です。実際、それが私たちのすべてのJavaベースのアプリで行っていることです。

Javaアプリにはそれぞれ独自のランチャーがあります。主にこれを行うので、独自のアイコンとプロセス名を取得しますが、通常のmain()呼び出し以外に何かを実行したい場合(たとえば、あるケースでは、 COMの相互運用性。実際には、COMハンドルを文字列配列ではなくmain()に渡します。

つまり、長くて短く、静的である理由は、便利なb / cです。'main'と呼ばれるのは、それが何かである必要があったためです。main()は、Cの昔(そして当時、関数の名前重要でした)で行ったことです。java.exeでは、クラス(java com.mycompany.Foo.someSpecialMain)の代わりに、完全修飾されたメインメソッド名のみを指定できたかもしれませんが、IDEでの自動検出がより難しくなりますプロジェクト内の起動可能なクラス。


66
+1:非常に魅力的(特にカスタムの作成に関する部分java.exe
Adam Paynter

9
興味深いことに、「これは単なる慣習です」には同意しません。答えの一部。OPの主な質問は、宣言の静的な理由でした。宣言では慣習のためだけstaticではないと思いますmain()。ただし、それが「main()」であり、他のものではないという事実は実現可能です。
Jared

2
@Davidだからそうしました。私は実際には元々関与していた人々の1人からの回答を好んだでしょう–しかし、それは非常に遠いショットでした。他の回答のほとんどは、残念ながらその場しのぎの推論です。これは非常に興味深い詳細を提供しますが、(おそらく)非技術的な原因を推論するために間違った技術的な詳細を発明しないという謙虚さを持っています。
コンラートルドルフ

2
@Jared-引数なしのパブリックコンストラクターが必要で、main静的ではなく、言語の境界内に収まる可能性があります。デザイナーからの連絡がなければ、同意しないことに同意する必要があります。:)
デビッド・ハークネス2012

4
@BenVoigt LoadLibrary()を呼び出して、jvm dllを取得します。次に、getprocaddress( "JNI_CreateJavaVM")を呼び出してから、JNI_CreateJavaVM関数(docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/…)を呼び出します。VMがロードされたら、標準のJNI呼び出しを使用して正しいクラスを見つけ、静的メインメソッドをロードして呼び出します。そこには誤解の余地はあまりありません。JNIは絶対にVMをロードする方法です。ネイティブキーワードのjavah -jniなどを使用してクライアント側のJNIのみを作成するのに慣れているかもしれませんが、それはJNIの半分にすぎません。
ケビン日

188

、およびのmain()メソッドは静的です。これらのオブジェクトは、オブジェクトをインスタンス化する必要なしに ランタイムエンジンによって呼び出すことができるため、の本体のコードが残りを実行します。C++C#Java
main()


1
ランタイムはクラスの1つのオブジェクトをインスタンス化できませんでしたか?そして、Mainメソッドを呼び出しますか?どうして?
AndreiRînea2008

12
メインクラスにオーバーロードされたコンストラクターがある場合、JVMはどのコンストラクターを呼び出すかをどのようにして知るでしょうか?どのパラメーターを渡しますか?
Jacob Krall

1
@Noah親クラスと言うときは、メインメソッドを含むクラスを意味しますか?もしそうなら、「親クラス」という用語はここではやや紛らわしく、そうでなければ私には意味がありません。また、慣例によりを使用する場合public static void main...、アプリケーションのエントリポイントクラスにデフォルトのパブリックコンストラクターが必要であるという規則を採用できないのはなぜですか?
エドウィンダロルゾ

2
@Jacob JVMはどのオーバーロードstatic void mainを呼び出すかをどのようにして知るのでしょうか?全く問題ありません。
Konrad Rudolph、

4
@ナムラタ:はい、あなたは何かを逃しています。「静的メソッドが非静的メソッドを参照できない」というのは本当ではありません。正しい文は、「すべての静的メソッドは、非静的メソッドを使用するときにオブジェクトを提供する必要がある」です。そして見て、そのようなオブジェクトを作成するために頻繁に使用されるstaticようなメソッド。mainnew
Ben Voigt

38

なぜ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仕様

第2章Javaプログラミング言語の概念-セクション2.17実行を確認してください。

Java仮想マシンは、指定されたクラスのメソッドmainを呼び出し、文字列の配列である単一の引数をそれに渡すことにより、実行を開始します。これにより、指定されたクラスがロードされ(§2.17.2)、使用される他の型にリンクされ(§2.17.3)、初期化されます(§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);

... ...

4
ここでの問題は、これは実際には元の形式での質問に対する非常に良い回答であり、参照がたくさんある(+1)ことです。ただし、コンストラクターやインスタンスメソッドではなく、静的メソッドをエントリポイントにするという設計上の決定の根拠について知りたいと思います。
Konrad Rudolph

1
@KonradRudolph、言語およびJVM仕様設計に関する質問については、おそらくOracleの元のソースに連絡して、正のフィードバックを得ることができるかどうかを確認することができます。
ニューヨーク

2
一般的に言えば、メソッドの結果の計算がそのパラメータにのみ依存する場合、オブジェクトインスタンスの内部状態に依存しないため、静的である可能性があります。また、コードの保守性/再利用性のために静的に設定することをお勧めします。メソッドmainが静的でなかった場合は、クラスインスタンスの状態がわかっている必要があり、どのコンストラクタを最初に使用するかなど、定義がはるかに複雑になります。
Yves Martin

@KonradRudolph興味深いことに、Oak(Javaの前身)は、同じようなプロトタイプを持つmainメソッドをすでに必要としていました。- public static void main(String arguments[])参照:Oak 0.2 Spec
assylias

2
@Yves It はすることできます。別のデザインが理にかなっている場合は必要ありません。私はここのコメントでいくつかの良い議論を聞いたことがありますが、プロセスは事実上スレッドと非常によく似ています(それ)、そしてJavaのスレッドは通常のインスタンスとして表されますRunnable。プロセス全体を同じ方法で(つまりRunnable.Run、エントリポイントとして持つことで)表すことは、Javaでは間違いなく理にかなっています。もちろん、Runnableそれ自体は間違いなく設計上の欠陥であり、Javaには(まだ)匿名メソッドがないために発生します。しかし、すでにそこにあるので…
コンラッドルドルフ

36

単純にstatic、アプリケーションのエントリポイントとして必要ないふりをしましょう。

アプリケーションクラスは次のようになります。

class MyApplication {
    public MyApplication(){
        // Some init code here
    }
    public void main(String[] args){
        // real application code here
    }
}

コンストラクタコードとの違い mainオブジェクト指向ではコンストラクタはインスタンスが適切に初期化されていることを確認するだけなので、メソッドが必要です。初期化後、インスタンスは目的の「サービス」に使用できます。完全なアプリケーションコードをコンストラクターに入れると、それが台無しになります。

したがって、このアプローチでは3、アプリケーションに異なる契約されます。

  • そこ デフォルトのコンストラクタ必要です。そうしないと、JVMはどのコンストラクターを呼び出すか、どのパラメーターを指定する必要があるかを認識できません。
  • メソッドが必要ですmain 1。OK、これは驚くべきことではありません。
  • クラスabstract。それ以外の場合、JVMはそれをインスタンス化できませんでした。

static一方、アプローチは、必要と一つ契約を:

  • mainメソッドが必要です1

ここにも abstractのコンストラクタも重要ん。

Javaはユーザーにとって単純な言語になるように設計されているので、アプリケーションのエントリポイントも次のように簡単な方法で設計されているのは当然です。 1つのコントラクトを 3つの独立したもろいコントラクト。

注意:この引数は、JVM内またはJRE内の単純さに関するものではありません。この議論は、ユーザーにとっての単純さについてです。


1ここでは、完全な署名が1つの契約として数えられます。


1
実際には、要求はより複雑である:が存在しなければならないmainある方法publicstaticおよび署名を有しますvoid main(String[])。メソッドがインスタンスメソッドである場合、JREは少し多くの作業を必要としますが、作業の種類は同じであり、複雑度はそれほど高くありません(前の回答のコメントの説明を参照)。特に、インスタンスメソッドの解決に必要なメソッドが存在し、すぐに使用できるため、この違いがエントリポイントを静的にする決定の原因とは思われません。
Konrad Rudolph

3
@KonradRudolph:私のポイントは、JREが実行する必要がある作業についてではありません。私のポイントは、言語のすべてのユーザーが必要に応じてより多くの契約に従うことを強制することです。この意味で、static public main(String[])メソッドは1つの署名であり、したがって1つの契約です。それ以外の場合は、3つの独立した契約に従う必要があります。
AH

1
ああ。ただし、これによって違いが生じることはまだありません。エントリポイントクラスは適切に実装できますRunnable。明らかに、Javaは開発者が常にその契約に従うことを期待していますが、アプリケーションのエントリポイントとしては多すぎるのはなぜですか?それは意味がありません。
Konrad Rudolph

3
@KonradRudolph:矛盾はありません:1つのケースでは、システムはユーザーに3つの契約を強制します。疑わしいコントラクト、コンパイラを介してチェックできないコントラクト、およびユーザーの観点からは独立したコントラクト。通常ではThreadRunnableケース何もユーザーから隠されていない、彼は明らかに何が起こっているのか見ることができると彼は実装するために変更があるだけで、彼に合うそれらの契約を-彼は、システム、コントロールではありません。
AH

2
これがここでの最良の答えです。多くのユーザーがページのトップ2または3の回答のみを読むのは残念です。そして、これはすぐにそこに到達する可能性は低いです。これは、初期化のみを目的とするコンストラクターの重要なポイントについて言及しているため、コンストラクターがアプリケーション全体を実行するスタイルでコーディングしても意味がありません。
Dawood ibnカリーム2014年

14

そうでない場合、複数のコンストラクタがある場合、どのコンストラクタを使用する必要がありますか?

Java言語仕様には、Javaプログラムの初期化と実行に関する詳細情報があります。


12

mainメソッドが呼び出される前は、オブジェクトはインスタンス化されていません。staticキーワードを使用すると、最初にオブジェクトを作成せずにメソッドを呼び出すことができます。


違う。または、少なくとも非常に不正確です。public class Main {static Object object = new Object(){{System.out.println( "object created"); }}; public static void main(String [] args){System.out.println( "in main"); }}
eljenso 2009年

公正なコメント。技術的には、Mainメソッドが呼び出される前に、mainメソッドを含むクラスがインスタンス化されないことを述べておかなければなりません。
BlackWasp 2009年

12

それ以外の場合は、オブジェクトのインスタンスを実行する必要があるためです。ただし、通常はmain()関数(ブートストラップ)のタスクであるため、通常はこれらの引数/プログラムパラメーターを使用して引数を解析し、オブジェクトを構築するため、最初にオブジェクトを構築せずに、最初から呼び出す必要があります。


10

これらのことをもっと簡単な方法で説明しましょう。

public static void main(String args[])

アプレットを除くすべてのJavaアプリケーションは、から実行を開始しmain()ます。

キーワードpublicは、メンバーをクラスの外部から呼び出せるようにするアクセス修飾子です。

staticこれはmain()、そのクラスの特定のインスタンスをインスタンス化することなく呼び出すことができるためです。

voidmain()値を返さないことを示します。


9

の意味はpublic static void main(String args[])何ですか?

  1. public アクセス指定子であり、JVM(Java Virtual Machineなど)はだれでもアクセス/起動できます。
  2. staticmain()クラスのオブジェクトが作成される前に呼び出すことができます。main()オブジェクトが作成される前に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を使用することがあります。

  3. voidmain()宣言されているメソッドが値を返さないことを示します。

  4. String[] argsメソッド内の唯一のパラメーターを指定しますmain()

    args-クラス型のオブジェクトの配列を含むパラメータString


6

さまざまな種類のアプレット、ミッドレット、サーブレット、およびBeanが構築され、ライフサイクルメソッドが呼び出されます。mainを呼び出すだけで、メインクラスに対して行われる処理がすべて完了するため、複数回呼び出されるオブジェクトに状態を保持する必要はありません。mainを別のクラスにピン留めするのはごく普通のことです(ただし、すばらしいアイデアではありません)。これは、クラスを使用してメインオブジェクトを作成する際に邪魔になります。


5

これは単なる慣例ですが、おそらく他の方法より便利です。静的メインの場合、Javaプログラムを呼び出すために知っておく必要があるのはクラスの名前と場所だけです。静的でない場合は、そのクラスをインスタンス化する方法を知っているか、クラスに空のコンストラクターが必要であることも必要です。


慣習ではありません。言語仕様の一部です。ランタイムは、静的なmainメソッドのないクラスを有効なエントリポイントとして認識しません。
Rob

2
言語仕様自体は規約に従います。Java設計者が静的メインを要求することを選択したという実際の要件はありません。ただし、ローガンが説明するように、代替案はより複雑です。
デビッドアルノ

@DavidArno規約は言語仕様に従っていると言った方が理にかなっています。
ローン侯爵

5

mainメソッドが静的でない場合は、プログラムの外部からメインクラスのオブジェクトを作成する必要があります。どうしますか?


5

java次のコマンドでJava仮想マシン(JVM)を実行すると、

java ClassName argument1 argument2 ...

アプリケーションを実行するときは、上記のように、javaコマンドの引数としてそのクラス名を指定します

JVMは、指定したクラスのメインメソッドを呼び出そうとします

-この時点では、クラスのオブジェクトは作成されていません。

クラスのを主に作成するために、JVMをmain静的として宣言します。allowsinvokewithoutinstance

コマンドに戻りましょう

ClassNamecommand-line argument実行するためにどのクラスにそれを伝えるJVMに。ClassNameに続いlist of Stringsて、JVMがアプリケーションに渡すコマンドライン引数として(スペースで区切られた)を指定することもできます。-このような引数は、アプリケーションを実行するためのオプション(ファイル名など)を指定するために使用される可能性があります。これがString[] args、メインで呼び出されるパラメーターがある理由です。

参考資料:Java™How To Program(Early Objects)、第10版


4

最近、同様の質問がProgrammers.SEに投稿されました。

TL;受け入れられた答えのDR部分は、

Javaでは、その理由public static void main(String[] args)

  1. ゴスリングが欲しかった
  2. C(Javaではない)の経験者が作成したコード
  3. 誰かによって実行されるように実行するように使用のPostScriptをニュース

http://i.stack.imgur.com/qcmzP.png

 
C#の場合、推論は、一言で言えば推移的に似ています。言語設計者は、Javaから来たプログラマーにとって馴染みのあるプログラムエントリポイント構文を維持しました。C#アーキテクトのAnders Hejlsbergが言うように

... C#を使用したアプローチは、Javaプログラマーに代替手段を提供することです...

...


3

キーワード 'static'はメインメソッドをクラスメソッドにし、クラスメソッドはそのコピーを1つだけ持ち、すべてが共有できると思います。また、参照用のオブジェクトを必要としません。そのため、ドライバークラスがコンパイルされると、メインメソッドを呼び出すことができます。(私はジャバのアルファベットレベルにいるので、間違っているとすみません)


すべてのメソッドは「そのコピーを1つだけ持っています」。
ローンの侯爵

3

main()は静的です。アプリケーションのライフサイクルのその時点では、インスタンス化されているオブジェクトがないため、アプリケーションスタックは本質的に手続き型です。

白紙の状態です。オブジェクトが宣言されていなくても、アプリケーションはこの時点で実行されています(手続き型およびOOコーディングパターンがあることに注意してください)。開発者は、オブジェクトのインスタンスを作成し、コンパイルされたコードに応じて、アプリケーションをオブジェクト指向のソリューションに変換します。

オブジェクト指向は、何百万もの明らかな理由で優れています。ただし、ほとんどのVB開発者がコードで "goto"などのキーワードを定期的に使用していた時代は終わりました。"goto"はVBの手続き型コマンドで、それに対応するOOのメソッド呼び出しによって置き換えられています。

静的エントリポイント(メイン)を純粋な自由として見ることもできます。Javaがオブジェクトをインスタンス化して実行時にそのインスタンスのみを提示するほど十分に異なっていた場合、手続き型アプリを作成する選択肢はありません。Javaの場合とは思えないほど想像できないほど、手続き型のアプローチを必要とする多くのシナリオが考えられます。

これはおそらく非常にあいまいな応答です。「クラス」は相互に関連するコードのコレクションにすぎないことを覚えておいてください。「インスタンス」は、そのクラスの孤立した、生きている、呼吸する自律的な世代です。


7
これは誤りです。main到達する前に、多くのオブジェクトがインスタンス化されます。また、mainを含むクラスに静的コンストラクターを含めると、main同じように前に実行されます。
Konrad Rudolph

2

それは単なる慣習です。それが慣習であったならば、JVMは確かに非静的メインメソッドを処理することができます。結局のところ、クラスに静的初期化子を定義し、main()メソッドに到達する前にzillionオブジェクトをインスタンス化できます。


2

プロトタイプpublic static void main(String[])は、JLSで定義された規則です。

mainメソッドはpublic、static、およびvoidで宣言する必要があります。宣言された型が文字列の配列である仮パラメーター(8.4.1)を指定する必要があります。

JVM仕様 5.2。読み取り可能な仮想マシンの起動

Java仮想マシンは、ブートストラップクラスローダー(§5.3.1)を使用して、実装依存の方法で指定された初期クラスを作成することによって起動します。次に、Java仮想マシンは初期クラスをリンクし、初期化して、パブリッククラスメソッドvoid main(String [])。このメソッドの呼び出しにより、以降のすべての実行が駆動されます。mainメソッドを構成するJava仮想マシン命令を実行すると、追加のクラスとインターフェースのリンク(および結果として作成)が発生し、追加のメソッドが呼び出される場合があります。

おかしなことに、JVM仕様では、メインメソッドが静的でなければならないことについては触れられていません。しかし、この仕様では、Java仮想マシンは2つのステップを以前に実行することも述べています。

クラスまたはインターフェースの初期化は、そのクラスまたはインターフェースの初期化メソッドの実行で構成されます。

では2.9。特別な方法

クラスまたはインタフェースの初期化方法が定義されます。

クラスまたはインターフェースには、最大で1つのクラスまたはインターフェース初期化メソッドがあり、そのメソッドを呼び出すことによって初期化されます(§5.5)。クラスまたはインターフェースの初期化メソッドは特別な名前<clinit>を持ち、引数を取らず、無効です。

そしてクラスまたはインタフェースの初期化方法は、異なるインスタンスの初期化方法、次のように定義されます。

Java仮想マシンのレベルでは、Javaプログラミング言語(JLS§8.8)で記述されたすべてのコンストラクターは、特別な名前を持つインスタンス初期化メソッドとして表示されます<init>

したがって、JVMはクラスまたはインターフェースの初期化メソッド初期化し、実際にはコンストラクターであるインスタンス初期化メソッド初期化しません。したがって、メインメソッドを呼び出す前にインスタンスが作成されないという事実によって暗示されるため、JVM仕様ではメインメソッドが静的である必要があることを言及する必要はありません。


2

publicキーワードは、プログラマがクラスメンバーの可視性を制御することを可能にするアクセス修飾子です。クラスメンバーの前にpublic場合、そのメンバーは、それが宣言されているクラス外のコードからアクセスできます。

publicis の反対はprivate、メンバーがクラスの外部で定義されたコードによって使用されるのを防ぎます。

この場合は、プログラムの起動時にクラス外のコードから呼び出す必要があるため、main()として宣言publicする必要があります。

キーワードをstatic使用 main()すると、クラスの特定のインスタンスをインスタンス化せずに呼び出すことができます。main()オブジェクトが作成される前にJavaインタープリターによって呼び出されるため、これは必要です。

このキーワードvoidは、main()値を返さないようコンパイラーに指示するだけです。


1

アプリケーションへの真のエントリポイントは、静的メソッドです。Java言語がインスタンスメソッドを「エントリポイント」としてサポートしている場合、ランタイムは、オブジェクトのインスタンスを作成した静的メソッドとして内部的に実装し、その後インスタンスメソッドを呼び出す必要があります。

それが邪魔にならないように、次の3つのオプションの特定の1つを選択する根拠を調べます。

  1. A static void main()今日見ます。
  2. void main()新しく作成されたオブジェクトで呼び出されるインスタンスメソッド。
  3. タイプのコンストラクタをエントリポイントとして使用します(たとえば、エントリクラスが呼び出されたProgram場合、実行は事実上で構成されますnew Program())。

壊す:

static void main()

  1. 包含するクラスの静的コンストラクターを呼び出します。
  2. 静的メソッドを呼び出しますmain()

void main()

  1. 包含するクラスの静的コンストラクターを呼び出します。
  2. を効果的に呼び出して、囲んでいるクラスのインスタンスを構築しますnew ClassName()
  3. インスタンスメソッドを呼び出しますmain()

new ClassName()

  1. 包含するクラスの静的コンストラクターを呼び出します。
  2. クラスのインスタンスを作成します(その後、クラスに対して何もせず、単に戻ります)。

根拠:

これは逆の順序で行います。

Javaの設計目標の1つは、優れたオブジェクト指向プログラミングの実践を強調(可能な場合は必須)することでした。このコンテキストでは、オブジェクトのコンストラクターがオブジェクトを初期化しますが、オブジェクトの動作に責任を持つべきではありません。したがって、エントリポイントを指定した仕様は、new ClassName()すべてのアプリケーションの「理想的な」コンストラクタの設計に例外を強制することにより、新しいJava開発者の状況を混乱させます。

main()インスタンスメソッドを作成することで、上記の問題は確実に解決されます。ただし、エントリクラスのコンストラクタのシグネチャとmain()メソッドのシグネチャをリストするように指定する必要があるため、複雑になります。

要約すると、a static void main()を指定すると、動作をメソッドに配置するという原則に従いながら、最小の複雑さで仕様が作成されます。main()それ自体がクラスのインスタンスを作成してインスタンスメソッドを呼び出すメソッドを実装するのがいかに簡単かを考えると、インスタンスメソッドmain()として指定することには実際的な利点はありません。


1
これは問題を引き起こしているだけです。Javaは、とにかく呼び出す前に重い処理を行うアプリケーションローダーを必要としますmainmain初心者には複雑すぎるというあなたの理論的根拠は信じられないようです。実際、static mainは初心者にとって非常に混乱します。コンストラクターはもっと混乱するでしょう。「コンストラクタはオブジェクトの動作に責任を負うべきではない」とあなたは言う。これは面白そうに聞こえますが、私が同意するかどうかはわかりません。なぜそれはありませんか?これを防ぐものは何ですか?
Konrad Rudolph

1

static-JVMがmainメソッドを呼び出すとき、呼び出されるクラスに存在するオブジェクトがないため、クラスからの呼び出しを可能にする静的メソッドが必要です。


1

オブジェクトがインスタンス化される前にJVMがmainメソッドを呼び出すかどうかはわかりません...しかし、main()メソッドが静的である理由ははるかに強力です... JVMがクラスのmainメソッドを呼び出すとき(たとえば、人)。「Person.main()」で呼び出します。ご覧のとおり、JVMはクラス名でそれを呼び出します。そのため、JVMからアクセスできるように、main()メソッドは静的かつパブリックである必要があります。

お役に立てば幸いです。もしそうなら、コメントで知らせてください。


0

静的メソッドはオブジェクトを必要としません。直接実行されるため、メインが直接実行されます。


0

mainメソッドではインスタンス化が行われないため、mainメソッドの静的キーワードが使用されます。しかし、結果として、メインメソッドで静的キーワードを使用するため、呼び出しではなくオブジェクトが構築されます。jvmコンテキストでは、クラスが読み込まれるとメモリが作成されます。すべての静的メンバーがそのメモリに存在します。ここでmainを静的にすると、メモリ内にあり、jvm(class.main(..))にアクセスできるため、ヒープを作成する必要さえなくてもmainメソッドを呼び出すことができます。


0

ここに見られるように、これは単なる規則です。

メソッドはpublicおよびstaticとして宣言する必要があり、値を返さないようにする必要があります。また、String配列をパラメーターとして受け入れる必要があります。デフォルトでは、最初の非オプション引数は、呼び出されるクラスの名前です。完全修飾クラス名を使用する必要があります。-jarオプションが指定されている場合、最初の非オプション引数は、アプリケーションのクラスおよびリソースファイルを含むJARアーカイブの名前であり、スタートアップクラスはMain-Classマニフェストヘッダーで示されます。

http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description


言語のルール、ということです。
ローン侯爵

0

public static voidキーワードは、Java仮想マシン(JVM)インタープリターがプログラムのメインメソッドを呼び出して、クラス(静的)のインスタンスを作成せずにプログラム(パブリック)を開始でき、プログラムがJava VMインタープリターにデータを返さないことを意味します(void)終了したとき。

ソース: Essentials、パート1、レッスン2:アプリケーションの構築


0

基本的に、オブジェクトに関連するタスクを実行しないDATA MEMBERSおよびMEMBER FUNCTIONSをSTATICとして作成します。また、mainメソッドの場合、オブジェクトを作成するかどうかに関係なくmainメソッドが常に実行されるため、オブジェクトとは関係がないため、静的メソッドとして作成しています。


0

Javaで静的として宣言されたメソッドはすべて、クラス自体に属します。繰り返しますが、特定のクラスの静的メソッドは、次のようなクラスを参照することによってのみアクセスできますClass_name.method_name();

そのため、静的メソッドにアクセスする前にクラスをインスタンス化する必要はありません。

したがって、main()メソッドは次のように宣言されます static、そのクラスのオブジェクトを作成せずにアクセスできるようにています。

mainメソッドが存在するクラスの名前で(またはプログラムが実行を開始する場所から、main()method()(Advanced Level)のないクラスに適用可能)プログラムを保存するため。したがって、上記の方法で:

Class_name.method_name();

mainメソッドにアクセスできます。

簡単に言うと、プログラムがコンパイルされると、次のような引数main()を持つメソッドが検索されます。言及されたクラス(つまり、プログラムの名前)で、最初からそのクラスをインスタンス化するスコープがないため、main()メソッドは静的として宣言されています。Stringmain(String args[])


これは、コンパイルされずにプログラムが実行されたときに発生します。
ローン侯爵

0

java.sun.comから(サイトに詳細情報があります):

mainメソッドは静的で、Java VMインタープリターが、最初にコントロールクラスのインスタンスを作成せずにクラスを開始する方法を提供します。コントロールクラスのインスタンスは、プログラムの起動後にmainメソッドで作成されます。

私の理解では、メインメソッドは、静的メソッドと同様に、関連付けられたクラスのインスタンスを作成せずに呼び出すことができ、プログラム内の他のどのメソッドよりも先に実行できるというだけでした。静的でない場合は、オブジェクトを呼び出す前にインスタンス化する必要があります。これは、メインのメソッドが通常、プログラムの最初にオブジェクトをインスタンス化するために使用するものであるため、「鶏と卵」の問題を引き起こします。


しかし、それは「プログラムの他の何よりも前に」実行されませ。議論全体は誤りであり、さらに、これはそれを言及する最初の答えでも、2番目または3番目の答えでもありません。
Konrad Rudolph

私の答えが他の人が言ったことを繰り返して申し訳ありません。私は私の理解とオンラインで見つけたものから最善を尽くして回答しました。私が見てきた結果から、メインメソッドが静的である理由は他にありません。どこかに深く隠されているものがない限り、おそらくそれが唯一の答えです。Javaについての私の理解はかなり基本的ですが、上記の理由(教授、教科書などから)を聞いたことがあり、他の理由は聞いたことがありません。
Jesse M

@Jesse Mあなたのコメントは、他の回答を最初に読むことさえ考えなかった場合にのみ意味があります。ちなみに、どちらを実行するのはそれほど難しいことではありません。あなた自身が言ったように、あなたの理解はかなり基本的なので、誰かがすでにより有能に質問に答えた可能性が非常に高いです。そして、あなたのコメントはあなたの答えをより良く見せるために合理化されているようです。あなたが主張することを考えるJavaの教科書や教授がいて、率直に言って私は彼らがそうはしないと信じているのは、並はずれた主張です。(参考文献はありますか?)
LeoR

1
@KonradRudolphトップコメントはかなり合理的だ。main()はプログラムへのエントリポイントとして使用されます。JavaWebサイトには、C / C ++がmain()関数を持っている方法に類似していると想定されているとの言及がいくつかあります。Javaはすべてオブジェクトであるため、オブジェクトのインスタンス化を回避するには静的である必要があります。静的にすると、実行時にJVMにロードして実行できるようになります。私は以前の答えを逆流しているだけですが、あなたが満足のいく答えとは何だと思いますか。あなたが得る最高のものは「それが彼らがそれを望んでいた方法だ」だと思います。Javaが作成された日付を覚えておいてください。
trevor-e 12/07/13

1
@ジェシースポットオン。それが単なる慣習の問題である可能性は十分にあります(そうではないと私は願っていますが、それはそのような退屈な答えになるでしょう)。この質問に最初に興味を持ったのは、適切なインスタンスを使用してオブジェクト「実行中のアプリケーション」を表し、エントリポイントをこのクラスのメソッド(またはコンストラクタ)にすることは、Javaは最初からオブジェクト指向になるように設計されており、一見RunnableJavaの類似オブジェクト(スレッド、経由)からこの設計使用されています。なぜ(見かけ上の)例外がここにあるのですか?
Konrad Rudolph
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.