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

java static main

493447 просмотра

30 ответа

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

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

Есть ли причина для этого метода быть статичным?

Автор: Alotor Источник Размещён: 30.10.2019 06:21

Ответы (30)


331 плюса

Решение

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

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

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

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

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

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

Автор: Jacob Krall Размещён: 28.09.2008 08:28

388 плюса

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

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

По сути, java.exe - это очень простое приложение C, которое анализирует командную строку, создает новый массив String в 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' запускаемые классы в проекте.

Автор: Kevin Day Размещён: 30.09.2008 03:32

186 плюса

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

Автор: Noah Goodrich Размещён: 28.09.2008 07:48

38 плюса

Почему открытая статическая пустота main (String [] args)?

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

Oracle Java Language Specification

Ознакомьтесь с главой 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 Virtual Machine

Ознакомьтесь с Главой 2 Основные понятия языка программирования Java - Раздел 2.17 Выполнение :

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

Oracle OpenJDK Source

Скачайте и распакуйте исходный файл jar и посмотрите, как написана JVM, ознакомьтесь с исходным кодом ../launcher/java.cC команды 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);

... ...
Автор: yorkw Размещён: 12.07.2012 04:05

35 плюса

Давайте просто притворимся, что 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 Здесь полная подпись считается только одним договором.

Автор: A.H. Размещён: 15.07.2012 12:20

14 плюса

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

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

Автор: Hank Размещён: 28.09.2008 07:51

12 плюса

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

Автор: BlackWasp Размещён: 28.09.2008 07:48

12 плюса

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

Автор: PhiLho Размещён: 28.09.2008 07:48

9 плюса

В чем смысл 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.

Автор: Isabella Engineer Размещён: 08.07.2013 12:11

9 плюса

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

public static void main(String args[])

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

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

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

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

Автор: Lordferrous Размещён: 09.05.2015 01:31

6 плюса

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

Автор: Tom Hawtin - tackline Размещён: 28.09.2008 08:04

5 плюса

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

Автор: Logan Размещён: 28.09.2008 07:47

5 плюса

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

Автор: micro Размещён: 28.09.2008 10:09

5 плюса

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

java ClassName argument1 argument2 ...

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

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

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

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

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

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

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

Автор: Basheer AL-MOMANI Размещён: 21.02.2017 09:56

3 плюса

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

Автор: Aysha Размещён: 12.06.2012 12:48

3 плюса

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

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

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

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

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

Автор: hellaciousprogger Размещён: 10.07.2012 02:37

3 плюса

Прототип 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 (§8.8 JLS), отображается как метод инициализации экземпляра со специальным именем <init>.

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

Автор: alain.janinm Размещён: 13.07.2012 03:15

3 плюса

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

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

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

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

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

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

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

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

... наш подход к C # просто предлагал альтернативу ... программистам на Java ...

...

Автор: gnat Размещён: 25.07.2012 05:58

2 плюса

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

Автор: Tom Размещён: 28.09.2008 08:15

2 плюса

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

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

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

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

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

Автор: Abhishek Размещён: 30.04.2011 11:39

1 плюс

Истинной точкой входа в любое приложение является статический метод. Если бы язык 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()метода.

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

Автор: Sam Harwell Размещён: 10.07.2012 10:43

1 плюс

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

Автор: Kero Fawzy Размещён: 08.12.2016 10:04

1 плюс

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

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

Автор: Vamsi Sangam Размещён: 03.06.2015 07:16

0 плюса

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

Автор: c k ravi Размещён: 01.06.2010 12:49

0 плюса

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

Автор: eagles Размещён: 18.01.2012 11:51

0 плюса

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

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

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

Автор: Francisco Spaeth Размещён: 11.07.2012 06:13

0 плюса

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

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

Автор: user1515855 Размещён: 11.07.2012 08:03

0 плюса

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

Автор: Varun Vashista Размещён: 10.07.2015 11:06

0 плюса

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

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

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

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

Class_name.method_name();

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

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

Автор: Sourav Saha Размещён: 22.01.2015 10:02

0 плюса

С java.sun.com (есть больше информации на сайте):

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

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

Автор: Jesse M Размещён: 12.07.2012 12:43
Вопросы из категории :
32x32