[java] Java 기본 메소드가 정적 이유는 무엇입니까?

Java main () 메소드 의 메소드 서명 은 다음과 같습니다.

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

이 방법이 정적 인 이유가 있습니까?



답변

그렇지 않으면 모호성이 있기 때문에이 메소드는 정적입니다. 어떤 생성자를 호출해야합니까? 특히 수업이 다음과 같은 경우 :

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

JVM이 호출해야합니까 new JavaClass(int)? 무엇을 통과해야 x합니까?

그렇지 않은 경우 JavaClass생성자 메서드를 실행하지 않고 JVM을 인스턴스화해야 합니까? 나는 그것이 전체 클래스를 특별하게 만들 것이기 ​​때문에 그렇게해서는 안된다고 생각합니다. 때때로 초기화되지 않은 인스턴스가 있고 호출 할 수있는 모든 메소드에서 확인해야합니다.

엔트리 포인트가 호출되기 전에 JVM이 클래스를 인스턴스화해야하는 경우를 이해하기에는 너무 많은 경우와 모호함이 있습니다. 그게 main정적 인 이유 입니다.

main항상 표시되어 있는지 모르겠습니다public .


답변

이것은 단지 관습입니다. 사실 main ()이라는 이름과 전달 된 인수조차도 전적으로 관례입니다.

java.exe (또는 Windows의 경우 javaw.exe)를 실행할 때 실제로 발생하는 것은 몇 가지 JNI (Java Native Interface) 호출입니다. 이러한 호출은 실제로 JVM 인 DLL을로드합니다 (즉, java.exe는 JVM이 아님). JNI는 가상 머신 세계와 C, C ++ 등의 세계를 연결해야 할 때 사용하는 도구입니다. 그 반대도 마찬가지입니다. (적어도 내 지식으로는) 실제로는 얻을 수 없습니다. JNI를 사용하지 않고 실행중인 JVM.

기본적으로 java.exe는 명령 행을 구문 분석하고 JVM에서 새 문자열 배열을 작성하여 해당 인수를 보유하고 main ()을 포함하도록 지정한 클래스 이름을 구문 분석하고 JNI 호출을 사용하여 main () 메소드 자체가 main () 메소드를 호출하여 새로 작성된 문자열 배열을 매개 변수로 전달합니다. 이것은 자바에서 리플렉션을 사용할 때하는 것과 매우 흡사합니다. 대신 혼란스러운 이름의 네이티브 함수 호출을 사용합니다.

자신의 버전의 java.exe (소스는 JDK와 함께 배포 됨)를 작성하고 완전히 다른 방식으로 작업하는 것이 완벽하게 합법적입니다. 사실, 그것은 우리가 모든 Java 기반 앱으로하는 일입니다.

각 Java 앱에는 자체 실행기가 있습니다. 우리는 주로이 작업을 수행하여 자체 아이콘과 프로세스 이름을 얻지 만, 일반적인 main () 호출 이외의 작업을 수행하려는 다른 상황에서 유용합니다 (예를 들어, 어떤 경우에는 COM 상호 운용성, 실제로는 문자열 핸들 대신 main ()에 COM 핸들을 전달합니다.

그래서 길고 짧습니다 : 정적 인 이유는 b / c가 편리합니다. 그것이 ‘main’이라고 불리는 이유는 그것이 무언가 여야했기 때문이며 main ()은 C의 옛날 시절에했던 일입니다 (그리고 그 당시에는 함수의 이름 중요했습니다). java.exe를 사용하면 클래스 (java com.mycompany.Foo.someSpecialMain) 대신 정규화 된 기본 메소드 이름을 지정할 수 있다고 생각하지만 IDE에서 ‘ 프로젝트에서 실행 가능한 클래스.


답변

main()의 방법 C++, C#그리고 Java정적
들이 다음 런타임 엔진에 의해 호출 될 수 있기 때문에 하지 않고 본문에 다음 코드를 어떤 객체를 인스턴스화하는 데 main()나머지를 할 것입니다.


답변

왜 public static void main (String [] args)입니까?

Java 언어가 설계되고 Java Virtual Machine이 설계되고 작성되는 방식입니다.

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 장 자바 프로그래밍 언어의 개념 – 섹션 2.17 실행 :

JVM (Java Virtual Machine)은 지정된 클래스의 메소드 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);

... ...


답변

단순히 static응용 프로그램 진입 점으로 필요하지 않은 척하자 .

응용 프로그램 클래스는 다음과 같습니다.

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

생성자 코드와 main메소드 의 구분은 OO에서 생성자가 인스턴스가 올바르게 초기화 되었는지 확인해야하기 때문에 필요 합니다. 초기화 후 인스턴스는 의도 한 “서비스”에 사용될 수 있습니다. 완전한 응용 프로그램 코드를 생성자에 넣으면 그것을 망칠 것입니다.

따라서이 접근법은 응용 프로그램에 대해 세 가지 다른 계약을 강요 합니다.

  • 기본 생성자 가 있어야합니다 . 그렇지 않으면 JVM은 호출 할 생성자와 어떤 매개 변수를 제공해야하는지 알 수 없습니다.
  • 있어야합니다main방법 1 . 좋아, 이것은 놀라운 일이 아니다.
  • 수업 이 아니어야 합니다 abstract. 그렇지 않으면 JVM이 인스턴스화 할 수 없습니다.

반면 static에이 접근법은 하나의 계약 만 필요합니다 .

  • main방법 1 이 있어야합니다 .

여기서도 abstract여러 생성자가 중요 하지 않습니다.

Java는 사용자를 위해 간단한 언어 로 설계되었으므로 응용 프로그램 진입 점도 하나의 계약을 사용하여 간단한 방식으로 설계되었지만 세 개의 독립적이고 취약한 계약을 사용하는 복잡한 방식이 아니라는 점은 놀라운 일이 아닙니다 .

참고 :이 인수는 JVM 내부 또는 JRE 내부의 단순성에 관한 것이 아닙니다 . 이 주장은 사용자의 단순성에 관한 것 입니다.


1 여기서 완전한 서명은 하나의 계약으로 만 간주됩니다.


답변

그렇지 않은 경우 둘 이상이있는 경우 어떤 생성자를 사용해야합니까?

Java 언어 사양 에서 사용 가능한 Java 프로그램의 초기화 및 실행에 대한 자세한 정보가 있습니다 .


답변

main 메소드가 호출되기 전에 오브젝트가 인스턴스화되지 않습니다. 정적 키워드를 사용하면 객체를 먼저 만들지 않고도 메서드를 호출 할 수 있습니다.