Почему основной метод Java статичен?

сигнатура метода Java main () метод:

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

есть ли причина, по которой этот метод должен быть статическим?

30 ответов


метод статичен, потому что в противном случае будет неоднозначность: какой конструктор следует вызвать? Особенно если ваш класс выглядит так:

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

если вызов JVM new JavaClass(int)? Что это должно сойти за x?

если нет, должен ли экземпляр JVMJavaClass без выполнения каких-либо метод-конструктор? Я думаю, что это не должно, потому что это будет особый случай всего вашего класса-иногда у вас есть экземпляр, который не был инициализирован, и вы должны проверьте его в каждом методе, который может быть вызван.

существует слишком много крайних случаев и двусмысленностей, чтобы иметь смысл для JVM создавать экземпляр класса до вызова точки входа. Вот почему main Это статическое.

Я понятия не имею, почему main всегда отмечены public хотя.


Это просто условность. Фактически, даже имя main () и аргументы, переданные в нем, являются чисто условными.

при запуске java.exe (или javaw.exe в Windows), что на самом деле происходит, это несколько вызовов Java Native Interface (JNI). Эти вызовы загружают DLL, которая действительно является JVM (это правильно-java.exe не является JVM). JNI-это инструмент, который мы используем, когда нам нужно соединить мир виртуальных машин и мир C, C++ и т. д... Верно и обратное - это не так. возможно (по крайней мере, насколько мне известно) фактически запустить JVM без использования JNI.

в основном, java.exe-это супер простое приложение C, которое анализирует командную строку, создает новый массив строк в 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)-но это просто затрудняет автоматическое обнаружение классов "launchable" в проекте.


метод main () в C++, C# и Java статичен, потому что они могут быть вызваны механизмом выполнения без создания экземпляра родительского класса.


почему public static void main(String[] args) ?

это, как язык Java разработан и Java виртуальная машина разработана и написана.

Спецификация Языка Oracle Java

проверить Глава 12 Выполнение-Раздел 12.1.4 Вызов Теста.главная:

наконец, после завершения инициализации для теста класса (во время которого другая последующая загрузка, связывание и инициализация могут произошли), вызывается метод main теста.

метод main должен быть объявлен public, static и void. Он должен принимать один аргумент, представляющий собой массив строк. Этот метод может быть объявлен как

public static void main(String[] args)

или

public static void main(String... args)

Спецификация Виртуальной Машины Oracle Java

проверить Глава 2 Концепции Языка Программирования Java-Раздел 2.17 Выполнение:

виртуальная машина Java начинает выполнение, вызывая метод main некоторого указанного класса и передавая ему один аргумент, который является массивом строк. Это заставляет указанный класс загружаться (§2.17.2), связываться (§2.17.3) с другими типами, которые он использует, и инициализироваться (§2.17.4). Метод main должен быть объявлен public, static и void.

Oracle OpenJDK Source

Загрузите и извлеките исходную банку и посмотрите, как 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 speak конструктор должен только убедиться, что экземпляр инициализации правильно. После инициализации экземпляр можно использовать для предполагаемой "службы". Установка полного кода приложения в конструкторе это испортило бы.

таким образом, этот подход заставит три различные контракты по заявке:

  • здесь должны быть конструктор по умолчанию. В противном случае JVM не будет знать, какой конструктор вызывать и какие параметры должны быть предоставлены.
  • здесь должны быть main метод1. Ладно, это неудивительно.
  • класс должны не быть abstract. В противном случае JVM не сможет создать его экземпляр.

на static подход с другой стороны требует только один договора:

  • должно быть main метод1.
ни abstract ни несколько конструкторов не имеет значения.

так как Java был разработан, чтобы быть простым языком для неудивительно, что также запись приложения point был разработан простым способом, используя один контракт, а не сложным способом с использованием три независимые и хрупкие контракты.

обратите внимание: этот аргумент не о простоте внутри JVM или внутри JRE. Этот аргумент касается простоты для пользователей.


1здесь полная подпись считается только одним контрактом.

Если это не так, какой конструктор следует использовать, если их больше одного?

существует больше информации об инициализации и выполнении программ Java, доступных в Спецификация Языка Java.


потому что в противном случае ему понадобится экземпляр объекта для выполнения. Но он должен быть вызван с нуля, без предварительного построения объекта, поскольку обычно задача функции main () (bootstrap) состоит в том, чтобы проанализировать аргументы и построить объект, обычно используя эти аргументы/параметры программы.


перед вызовом метода main экземпляры объектов не создаются. Наличие ключевого слова static означает, что метод может быть вызван без создания каких-либо объектов.


что означает public static void main(String args[])?

  1. public - спецификатор доступа, означающий, что любой может получить доступ/вызвать его, например JVM (виртуальная машина Java.
  2. static позволяет main() вызывается до создания объекта класса. Это необходимо, потому что 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 */
        }
    }
    

    аналогично, мы используем статические иногда для пользовательских методов, чтобы нам не нужно было создавать объекты.

  3. void указывает, что main() объявляется метод не возвращает значение.

  4. String[] args указывает единственный параметр в main() метод.

    args - параметр, содержащий массив объектов класса type String.


позвольте мне объяснить эти вещи гораздо проще:

public static void main(String args[])

все Java-приложения, кроме апплетов, начинают выполнение с main().

ключевое слово public является модификатором доступа, который позволяет члену вызываться извне класса.

static используется, потому что это позволяет main() вызывается без необходимости создания экземпляра определенного экземпляра этого класса.

void указывает, что main() не возвращает значение.


апплеты, мидлеты, сервлеты и бобы различных видов строятся, а затем на них вызываются методы жизненного цикла. Вызов main-это все, что когда-либо делается для основного класса, поэтому нет необходимости удерживать состояние в объекте, который вызывается несколько раз. Вполне нормально закрепить main на другом классе (хотя и не отличная идея), что помешает использовать класс для создания основного объекта.


Это просто конвенция, но, вероятно, более удобная, чем альтернатива. С помощью статического main все, что вам нужно знать, чтобы вызвать программу Java, - это имя и местоположение класса. Если бы он не был статическим, вам также нужно было бы знать, как создать экземпляр этого класса или потребовать, чтобы класс имел пустой конструктор.


Если основной метод не будет статическим, вам нужно будет создать объект вашего основного класса извне программы. Как бы вы хотели это сделать?


при выполнении виртуальной машины Java (JVM) с ,

java ClassName argument1 argument2 ...

при выполнении приложения вы указываете его имя класса в качестве аргумента для команды java, как указано выше

JVM пытается вызвать основной метод указанного вами класса

-на данный момент объекты класса не были созданы.

объявления main как статические allows JVM to invoke main without творящий Ан instance класса.

вернемся к команде

ClassName это command-line argument к JVM, который сообщает ему, какой класс выполнить. После ClassName, вы также можете указать list of Strings (разделенные пробелами) в качестве аргументов командной строки, которые JVM передаст вашему приложению. - Такие аргументы могут использоваться для указания параметров (например, имя файла) для запуска приложения - вот почему существует параметр String[] args в главном

ссылки:На Java Как Программировать (Ранние Объекты), Десятое Издание


Я думаю, что ключевое слово "static" делает основной метод методом класса, а методы класса имеют только одну его копию и могут совместно использоваться всеми, а также не требуют объекта для ссылки. Поэтому, когда класс драйвера скомпилирован, можно вызвать метод main. (Я просто на уровне алфавита java, извините, если я ошибаюсь)


main () является статическим, потому что; на этом этапе жизненного цикла приложения стек приложений является процедурным по своей природе из-за отсутствия объектов, которые еще не созданы.

Это чистый лист. Ваше приложение работает в этот момент, даже без каких-либо объявленных объектов (помните, что есть процедурные и OO шаблоны кодирования). Вы, как разработчик, превращаете приложение в объектно-ориентированное решение, создавая экземпляры ваших объектов и в зависимости от кода составлено внутри.

объектно-ориентированный отлично подходит для миллионов очевидных причин. Однако прошли те дни, когда большинство разработчиков VB регулярно использовали ключевые слова, такие как "goto" в своем коде. "goto" - это процедурная команда в VB, которая заменяется ее аналогом OO: вызов метода.

вы также можете посмотреть на статическую точку входа (main) как чистой свободы. Если бы Java была достаточно другой, чтобы создать экземпляр объекта и представить вам только этот экземпляр при запуске, у вас не было бы выбор, но написать процедурное приложение. Как бы невообразимо это ни звучало для Java, возможно, есть много сценариев, которые требуют процедурных подходов.

Это, вероятно, очень неясный ответ. Помните, что "class" -это только коллекция взаимосвязанного кода. "Экземпляр" - это изолированное, живое и дышащее автономное поколение этого класса.


В protoype public static void main(String[]) конвенция определена в JLS :

метод main должен быть объявлен public, static и void. Он должен указать формальный параметр (§8.4.1), объявленный тип которого является массивом строк.

в спецификации JVM 5.2. Запуск виртуальной машины мы можем прочитать:

виртуальная машина Java запускается путем создания начального класса, который указан в зависящим от реализации способом, используя загрузчик класса начальной загрузки (§5.3.1). Затем виртуальная машина Java связывает исходный класс, инициализирует его и вызывает метод открытого класса void main (String[]). Вызов этого метода приводит к дальнейшему выполнению. Выполнение инструкций виртуальной машины Java, составляющих основной метод, может привести к связыванию (и, следовательно, созданию) дополнительных классов и интерфейсов, а также вызову дополнительных методы.

забавная вещь, в спецификации JVM не упоминается, что основной метод должен быть статическим. Но спецификация также говорит, что виртуальная машина Java выполняет 2 шага до:

инициализация класса или интерфейса состоит из выполнения его класса или интерфейса метод инициализации.

на 2.9. Специальные Методы :

A класс или метод инициализации интерфейса определено :

класс или интерфейс имеет не более одного метода инициализации класса или интерфейса и инициализируется (§5.5) путем вызова этого метода. Метод инициализации класса или интерфейса имеет специальное имя <clinit>, не принимает аргументов и является пустым.

и a класс или метод инициализации интерфейса отличается от метод инициализации экземпляра определена следующим образом :

на уровне виртуальной машины Java каждый конструктор, написанный на языке программирования Java (JLS §8.8), появляется как метод инициализации экземпляра, который имеет специальное имя <init>.

таким образом, JVM инициализирует класс или метод инициализации интерфейса и не метод инициализации экземпляра это на самом деле конструктор. Поэтому им не нужно упоминать, что метод main должен быть статическим в спецификации JVM, потому что это подразумевается тем фактом, что ни один экземпляр не создается перед вызовом метода main.


недавно аналогичный вопрос был опубликован у программистов.SE

  • почему статический основной метод в Java и C#, а не конструктор?

    поиск окончательного ответа от первичного или вторичного источника для того, почему (в частности) Java и C# решили иметь статический метод в качестве точки входа, а не представлять экземпляр приложения экземпляром Application класс, причем точка входа является подходящей конструктор?

TL; DR часть принятого ответа:

в Java, причина public static void main(String[] args) это

  1. Гослинг хотел
  2. код, написанный кем-то опытным в C (не на Java)
  3. для выполнения кем-то, кто привык работать PostScript on Новости

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


Для C# аргументация транзитивно похожие так сказать. Языковые дизайнеры сохранили точка входа программы синтаксис, знакомый программистам с Java. Как C# архитектор Андерс Хейльсберг ставит его,

...наш подход с C# был просто предложить альтернативу... для Java-программистов...

...


Это просто соглашение. СПМ, безусловно, могла бы заниматься нестатическими основными методами, если бы речь шла о Конвенции. В конце концов, вы можете определить статический инициализатор в своем классе и создать экземпляр zillion объектов, прежде чем добраться до Метода main ().


истинная точка входа в любое приложение является статическим методом. Если язык Java поддерживает метод экземпляра как "точку входа", то среда выполнения должна будет реализовать его внутренне как статический метод, который построил экземпляр объекта с последующим вызовом метода экземпляра.

с этим из пути, я рассмотрю обоснование выбора конкретного одного из следующих трех вариантов:

  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 было подчеркнуть (требовать, когда это возможно) хорошие объектно-ориентированные методы программирования. В этом контексте, конструктор объекта инициализирует объект, но не должен отвечать за поведение объекта. Поэтому спецификация, которая дала точку входа new ClassName() запутает ситуацию для новых разработчиков Java, заставляя исключение к дизайну "идеального" конструктора на каждом приложении.

делая main() метод экземпляра, вышеуказанная проблема, безусловно, решена. Однако это создает сложность, требуя от спецификации перечислить подпись конструктора класса записи, а также подпись main() метод.

в целом, задание static void main() создает спецификацию с наименьшей сложностью в то время как придерживаясь принципа помещения поведения в методы. Учитывая, насколько просто реализовать main() метод, который сам создает экземпляр класса и вызывает метод экземпляра, нет никакого реального преимущества для указания main() как метод экземпляра.


на public ключевое слово-модификатор доступа, который позволяет программисту управлять видимость членов класса. Когда члену класса предшествует public, тогда что члены могут быть доступны извне класса, в котором он объявлен.

напротив public is private, что предотвращает использование члена кодом, определенным вне его класса.

в этом случае main() должен быть объявлен как public, Так как он должен называться по коду вне своего класса при запуске программы.

ключевое слово static позволяет main() вызывается без необходимости создания экземпляра определенного экземпляра класса. Это необходимо, так как main() вызывается интерпретатором Java до создания каких-либо объектов.

ключевое слово void просто сообщает компилятору, что main() не возвращает значение.


статический - когда JVM вызывает метод main не существует объекта, который существует для класса, поэтому он должен иметь статический метод, чтобы разрешить вызов из класса.


Я не знаю, вызывает ли JVM метод main до создания экземпляра объектов... Но есть гораздо более веская причина, почему метод main() статичен... Когда JVM вызывает основной метод класса (скажем, Person). он вызывает его "человек.main ()". Видите ли, JVM вызывает его по имени класса. Вот почему метод main () должен быть статическим и общедоступным, чтобы он мог быть доступен JVM.

надеюсь, что это помогло. Если да, дай мне знать. комментирование.


статические методы не требуют какого-либо объекта. Он работает напрямую, поэтому main работает напрямую.


статическое ключевое слово в основном методе используется, потому что в основном методе нет никакого экземпляра. Но объект построен, а не вызов, в результате мы используем статическое ключевое слово в основном методе. В JVM контекстная память создается при загрузке в нее класса.И все статические члены присутствуют в этой памяти. если мы сделаем основной статический сейчас, он будет в памяти и может быть доступен для jvm (class.главный.(.)) таким образом, мы можем вызвать основной метод без необходимости даже потребность в куче была создана.


Это просто конвенция, как мы можем видеть здесь:

метод должен быть объявлен как public и static, он не должен возвращать value, и он должен принимать строковый массив в качестве параметра. По умолчанию, первый аргумент non-option - это имя вызываемого класса. Следует использовать полное имя класса. Если параметр-jar указанный, первый аргумент non-option-это имя архива JAR содержащий файлы классов и ресурсов для приложение, с класс запуска, указанный заголовком манифеста Main-Class.

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


ключевые слова public static void означают, что интерпретатор виртуальной машины Java (JVM) может вызвать основной метод программы для запуска программы (public) без создания экземпляра класса (static), и программа не возвращает данные интерпретатору Java VM (void), когда он заканчивается.

источник: Основы, Часть 1, Урок 2: Построение Приложений


в основном мы делаем эти члены данных и функции-члены статическими, которые не выполняют никаких задач, связанных с объектом. И в случае основного метода мы делаем его статическим, потому что он не имеет ничего общего с объектом, поскольку основной метод всегда выполняется независимо от того, создаем мы объект или нет.


любой метод, объявленный как static в Java относится к самому классу . Опять же, статический метод определенного класса может быть доступен только со ссылкой на класс like Class_name.method_name();

таким образом, класс не должен быть создан перед доступом к статическому методу.

таким образом, метод main () объявляется как static чтобы к нему можно было получить доступ без создания объекта этого класса.

так как мы сохраняем программу с именем класса, где основной метод присутствует (или откуда программа должна начать свое выполнение, применимо для классов без main() method () (расширенный уровень)). Итак, вышеупомянутым способом:

Class_name.method_name();

основной метод может быть доступен.

вкратце, когда программа компилируется, она ищет main() метод с String аргументы: main(String args[]) в упомянутом классе (т. е. по имени программы), и поскольку в начале он не имеет возможности создать экземпляр этого класса, поэтому метод main() объявляется как статический.


существует простая причина этого, потому что object не требуется вызывать статический метод , если это был нестатический метод, виртуальная машина java сначала создает объект, а затем вызывает метод main (), который приведет к проблеме выделения дополнительной памяти.