Вопрос

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

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

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

Это было полезно?

Решение

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

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

Если JVM вызовет new JavaClass(int)?За что это должно пройти x?

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

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

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

Другие советы

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

Когда вы запускаете java.exe (или javaw.exe в Windows), на самом деле происходит пара вызовов собственного интерфейса Java (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() вместо массива строк).

Итак, длинно и коротко:причина, по которой он статичен, заключается в том, что это удобно.Причина, по которой она называется «main», заключается в том, что она должна была быть чем-то, а main() — это то, что делали в старые времена C (и в те времена имя функции был важный).Я полагаю, что java.exe мог бы позволить вам просто указать полное имя основного метода, а не только класс (java com.mycompany.Foo.someSpecialMain) - но это только усложняет автоматическое обнаружение в IDE ' запускаемые классы в проекте.

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

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

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

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

Проверить Глава 12. Выполнение. Раздел 12.1.4. Вызов Test.main:

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

Метод 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

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

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

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

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

  • Должно быть main метод1.

Здесь ни abstract ни несколько конструкторов не имеют значения.

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

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


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

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

Более подробную информацию об инициализации и выполнении программ Java можно найти в Спецификация языка Java.

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

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

Каково значение 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 */
        }
    }
    

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

  3. void указывает на то, что main() ДЕКАРНЫЙ МЕТОД не возвращает значение.

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

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

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

public static void main(String args[])

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

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

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

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

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

Это всего лишь условность, но, вероятно, более удобная, чем альтернатива.При использовании статического main все, что вам нужно знать для вызова программы Java, — это имя и расположение класса.Если бы он не был статическим, вам также нужно было бы знать, как создать экземпляр этого класса, или потребовать, чтобы у класса был пустой конструктор.

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

Когда вы запускаете виртуальную машину Java (JVM) с помощью java команда,

java ClassName argument1 argument2 ...

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

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

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

Объявление main как статический allows JVM для invoke основной without Создание instance класса.

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

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

Использованная литература:Как программировать на Java™ (ранние объекты), десятое издание

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

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

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

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

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

Вероятно, это очень неясный ответ.Помните, что «класс» — это всего лишь набор взаимосвязанного кода.«Экземпляр» — это изолированное, живое и дышащее автономное поколение этого класса.

Прототип public static void main(String[]) это соглашение, определенное в JLS :

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

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

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

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

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

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

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

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

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

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

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

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

ТЛ;ДР часть принятого ответа такова:

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

  1. Гослинг в розыске
  2. код, написанный кем-то, имеющим опыт работы на C (не на Java)
  3. быть казненным кем-то, привыкшим бегать Постскриптум на Новости

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

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

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

...

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

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

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

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

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

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

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

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

  1. А 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() как метод экземпляра.

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

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

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

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

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

Это просто соглашение, как мы видим здесь:

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

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

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

Источник:Основы, часть 1, урок 2:Создание приложений

По сути, мы делаем эти ЧЛЕНЫ ДАННЫХ и ФУНКЦИИ-ЧЛЕНЫ СТАТИЧЕСКИМИ, которые не выполняют никаких задач, связанных с объектом.А в случае основного метода мы делаем его STATIC, потому что он не имеет ничего общего с объектом, поскольку основной метод всегда выполняется независимо от того, создаем мы объект или нет.

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

Таким образом, не требуется создавать экземпляр класса перед доступом к статическому методу.

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

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

Class_name.method_name();

доступен основной метод.

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

От java.sun.com (подробнее на сайте):

Основной метод является статическим, что дает интерпретатору виртуальной машины Java возможность запустить класс без предварительного создания экземпляра класса управления.Экземпляры класса управления создаются в основном методе после запуска программы.

Я всегда понимал, что основной метод, как и любой статический метод, можно вызвать без создания экземпляра связанного класса, что позволяет ему запускаться раньше всего остального в программе.Если бы он не был статическим, вам пришлось бы создать экземпляр объекта перед его вызовом, что создает проблему «курицы и яйца», поскольку основной метод обычно используется для создания экземпляров объектов в начале программы.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top