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

505

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

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

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

Alotor
источник
1
в этом случае мы не должны произносить сигнатуру метода , потому что этот термин относится только к именам методов и их параметрам
Андрей Тобилко
Java специально разработана, чтобы выглядеть знакомой программисту на Си. Это очень близко к С конвенции.
Турбьёрн Равн Андерсен

Ответы:

337

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

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
источник
4
Реализация интерфейса не решает проблему создания экземпляров.
Джейкоб Кралл
26
Мне лично нравится, что это public static void mainслужит маркером точки входа - открытый конструктор без параметров не кричит "Это, вероятно, точка входа!" таким же образом.
Джейкоб Кралл
5
@EdwinDalorzo - Что получится, если принудительно создать экземпляр класса точки входа? Вызов статического метода накладывает на класс наименьшее количество нагрузки. Это бесплатно создавать себя, если это имеет больше смысла для вашего дизайна.
Дэвид Харкнесс
18
«Какой конструктор должен быть вызван?» Как это вообще возможно проблема? Та же самая «проблема» существует для решения, которое mainнужно назвать. Как ни странно (для вас) JVM справляется с этим просто отлично.
Конрад Рудольф
9
Основной метод всегда общедоступен, потому что к нему должен обращаться механизм выполнения, JVM.
Gthm
398

Это просто соглашение. На самом деле, даже имя 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
источник
66
+1: очень увлекательно (особенно часть о написании кастома java.exe)
Адам Пейнтер
9
Интересно, что я не согласен с «Это просто соглашение». Часть ответа. Основной вопрос ОП был причиной статичности в декларации. Я не думаю, что staticв main()декларации просто ради соглашения. Однако факт, что это `main () ', а не что-то еще, возможно.
Джаред
2
@ Давид Так и сделал. Я бы на самом деле предпочел бы ответ от одного из первоначально вовлеченных людей - но это было очень далеко. К сожалению, большинство других ответов являются упражнением в рассуждениях ad-hoc. Этот дает довольно интересные детали, помимо того, что он смиренен, чтобы не придумывать неправильные технические детали, чтобы обосновать (вероятно) нетехническую причину.
Конрад Рудольф
2
@Jared - Им мог потребоваться общедоступный конструктор без аргументов, и он должен быть mainнестатичным и все еще вписываться в границы языка. Не слыша от дизайнеров, мы просто должны согласиться не согласиться. :)
Дэвид Харкнесс
4
@BenVoigt Вы вызываете LoadLibrary (), чтобы получить jvm dll. Затем вы вызываете getprocaddress («JNI_CreateJavaVM»), затем вызываете функцию JNI_CreateJavaVM ( docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/… ). После загрузки виртуальной машины вы используете стандартные вызовы JNI, чтобы найти правильный класс, загрузить статический метод main и вызвать его. Там не так много места для неправильного толкования. JNI - это абсолютно то, как вы загружаете виртуальную машину. Возможно, вы привыкли писать только JNI на стороне клиента, используя ключевое слово native, javah -jni и т. Д., Но это только половина JNI.
Кевин Дэй
188

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

Ноа Гудрич
источник
1
Хорошо, но разве среда выполнения не может создать экземпляр одного объекта класса? А потом вызывать метод Main? Почему?
Андрей Ринея
12
Как JVM узнает, какой конструктор вызывать, если у вашего основного класса перегружены конструкторы? Какие параметры это передало бы?
Джейкоб Кралл
1
@ Нет, когда вы говорите, родительский класс, вы имеете в виду класс, содержащий метод main? Потому что если так, то термин «родительский класс» здесь довольно запутанный, и в противном случае он не будет иметь никакого смысла для меня. Кроме того, если по соглашению мы используем public static void main..., почему не может быть соглашения о том, что класс точки входа приложения должен иметь открытый конструктор по умолчанию?
Эдвин Далорсо
2
@Jacob Как JVM узнает, какой перегружен static void mainдля вызова? Без проблем.
Конрад Рудольф
4
@Namratha: Да, вы что-то упустили. Это просто неправда, что «статический метод не может ссылаться на нестатический метод». Правильное утверждение: «Каждый статический метод должен предоставлять объект при использовании любого нестатического метода». И посмотрите, staticметоды, которые mainчасто используются newдля создания такого объекта.
Бен Фойгт
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);

... ...
оборота йорк
источник
4
Проблема здесь в том, что это действительно очень хороший ответ на вопрос в его первоначальном виде, с большим количеством ссылок (+1). Тем не менее, я хотел бы узнать об обосновании принятия решения о создании статического метода в качестве точки входа, а не метода конструктора или экземпляра.
Конрад Рудольф
1
@KonradRudolph. По вопросам, связанным с языком и спецификацией JVM, возможно, вы можете обратиться к первоисточнику из Oracle и посмотреть, сможете ли вы получить какие-либо положительные отзывы.
Йорк
2
Вообще говоря, когда вычисление результата метода зависит только от его параметров, так что оно не зависит от внутреннего состояния экземпляра объекта, оно может быть статическим. И рекомендуется установить его как статический для удобства сопровождения / повторного использования кода. Если метод mainне был статическим, это означает, что состояние экземпляра класса должно быть известно, и его гораздо сложнее определить, например, какой конструктор использовать первым.
Ив Мартин
@KonradRudolph Интересно, что Oak (предшественник Java) уже требовал, чтобы основной метод имел аналогичный прототип: public static void main(String arguments[])- Ссылка: Oak 0.2 Spec .
assylias
2
@ Да, это может быть. Это не нужно, если другой дизайн имеет смысл. Я услышал несколько хороших аргументов в комментариях здесь, но я все еще думаю, что процесс по сути очень похож на поток (так оно и есть ), и поток в 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методом необходимо, потому что в ОО конструктор должен только убедиться, что экземпляр инициализирован должным образом. После инициализации экземпляр можно использовать для предполагаемой «услуги». Помещение полного кода приложения в конструктор испортило бы это.

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

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

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

  • Должен быть mainспособ 1 .

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

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

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


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

AH
источник
1
На самом деле, требования являются более сложными: там должен быть mainметод , который public, staticи имеет подпись void main(String[]). Я согласен с тем, что если бы этот метод был методом экземпляра, у JRE было бы немного больше работы, но вид работы был бы таким же, а сложность не значительно выше (см. Обсуждения в комментариях к предыдущему ответу). Я не верю, что это различие объясняет решение сделать статическую точку входа, в частности, потому что существуют необходимые методы для разрешения метода экземпляра, и их легко использовать.
Конрад Рудольф
3
@KonradRudolph: Моя точка зрения не о работе, которую JRE должен был бы сделать. Моя точка зрения заключается в том, чтобы заставить каждого пользователя языка выполнять больше контрактов по мере необходимости. В этом смысле static public main(String[])метод - это одна подпись и, следовательно, один контракт. В противном случае должны соблюдаться три независимых контракта.
AH
1
Ах. Я все еще не согласен, что это имеет какое-либо значение, хотя. Классы точки входа вполне могут быть реализованы Runnable. Ясно, что Java ожидает, что разработчики будут постоянно следовать этому контракту, почему он должен быть слишком большим для точки входа в приложение? Это бессмысленно.
Конрад Рудольф
3
@KonradRudolph: Нет противоречия: в одном случае система навязывает пользователю три контракта. Контракты, которые являются сомнительными, которые нельзя проверить с помощью компилятора и которые, с точки зрения пользователя, независимы. В обычном Threadи Runnableделе ничего не скрыто от пользователя, он может ясно видеть , что происходит , и у него есть изменения , чтобы реализовать только те контракты , которые подходят ему - он находится под контролем, а не система.
AH
2
Это лучший ответ здесь. Обидно, что многие пользователи будут только читать 2 или 3 верхних ответа на странице; и этот вряд ли попадет туда в ближайшее время. В нем упоминается, что важная точка конструктора - ТОЛЬКО для инициализации, и поэтому нет смысла кодировать в стиле, в котором конструктор запускает все приложение.
Дауд ибн Карим
14

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

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

моток
источник
12

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

BlackWasp
источник
Неправильно. Или, по крайней мере, очень неточно. public class Main {статический объект object = new Object () {{System.out.println («объект создан»); }}; public static void main (String [] args) {System.out.println ("in main"); }}
eljenso
Честный комментарий. Технически, я должен был сказать, что перед вызовом метода Main класс, содержащий метод main, не создается.
BlackWasp
12

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

PhiLho
источник
10

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

public static void main(String args[])

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

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

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

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

Lordferrous
источник
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.

Изабелла Инженер
источник
6

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

Tom Hawtin - tackline
источник
5

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

логан
источник
Это не соглашение; это часть спецификации языка; среда выполнения не распознает класс без статического метода main в качестве допустимой точки входа.
Роб
2
Сама спецификация языка следует соглашению. Нет фактического требования для разработчиков Java, чтобы они выбрали статический main. Однако, как объясняет Логан, альтернативы являются более сложными.
Дэвид Арно
@DavidArno Было бы более разумно сказать, что соглашение следует спецификации языка.
маркиз Лорн
5

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

микро
источник
5

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

java ClassName argument1 argument2 ...

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

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

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

Декларирование в mainкачестве статического allowsв JVM для invokeосновных withoutсоздавая instanceкласс.

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

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

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

Башир Аль-Момани
источник
4

Недавно аналогичный вопрос был опубликован на 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 ...

...

комара
источник
3

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

Айша
источник
Все методы «имеют только одну копию».
Маркиз Лорн
3

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

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

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

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

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

hellaciousprogger
источник
7
Это неверно Множество объектов создаются до того, mainкак они достигнуты. И если вы включите статический конструктор в класс, содержащий main, он также будет выполнен раньше main.
Конрад Рудольф
2

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

Том
источник
2

Прототип 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
источник
2

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

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

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

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

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

Абхишек
источник
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()метода экземпляра.

Сэм Харвелл
источник
1
Это только начало вопроса. В любом случае Java нуждается в загрузчике приложений, который выполняет тяжелую работу перед вызовом main. Ваше обоснование того, mainчто вы слишком сложны для начинающих, кажется невероятным. На самом деле, статический mainявляется очень запутанным для начинающих, я сомневаюсь, что конструктор будет больше. Вы говорите, что «конструктор не должен отвечать за поведение объекта». Это звучит интересно, но я не уверен, что согласился бы. Почему не так? Что мешает этому?
Конрад Рудольф
1

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

Керо Фавзи
источник
1

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

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

Vamsi Sangam
источник
0

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

ck ravi
источник
0

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

орлов
источник
0

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

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

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

Франсиско Спает
источник
Вы имеете в виду правило языка.
Маркиз Лорн
0

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

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

user1515855
источник
0

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

Варун Вашиста
источник
0

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

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

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

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

Class_name.method_name();

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

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

Sourav Saha
источник
Это происходит, когда программа выполняется, а не компилируется.
Маркиз Лорн
0

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

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

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

Jesse M
источник
Но он не запускается «прежде всего в программе». Весь аргумент - заблуждение, и более того, это не первый ответ, упоминающий его, ни даже второй или третий.
Конрад Рудольф
Мне жаль, что мой ответ повторяет то, что сказали другие; Я отвечал только в меру моего понимания и из того, что я мог найти в Интернете. Из результатов, на которые я смотрел, нет другой причины того, почему основной метод является статическим; если нет где-то глубоко спрятанного, возможно, это единственный ответ. Мое понимание Java довольно простое, но я слышал вышеупомянутую причину (от профессоров, из учебников и т. Д.) И никогда от других.
Джесси М
@Jesse M Ваш комментарий имеет смысл, только если вы даже не задумывались сначала о том, чтобы прочитать другие ответы. Что, кстати, не надумано. Как вы упомянули сами, ваше понимание довольно простое, поэтому весьма вероятно, что кто-то другой уже ответил на вопрос более компетентно. И ваш комментарий, кажется, является рационализацией, чтобы ваш ответ выглядел лучше. Это необычное утверждение, что у вас есть учебники по Java и профессора, которые думают, что вы заявляете, и, честно говоря, я не верю, что они это делают. (Есть ссылки?)
LeoR
1
@KonradRudolph Верхние комментарии кажутся довольно разумными. main () используется как точка входа в программу, и на веб-сайте Java есть несколько ссылок, говорящих о том, что она должна быть похожа на ту, что в C / C ++ имеет функция main (). Поскольку Java - это все Объекты, она должна быть статической, чтобы избежать создания объектов. Наличие статического кода также позволяет загружать и выполнять его в JVM во время выполнения. Я просто отрыгиваю предыдущие ответы, но мне интересно, что бы вы сочли удовлетворительным ответом. Я думаю, что лучшее, что вы получите, это «Вот как они этого хотели». Имейте в виду дату создания Java.
Тревор-э
1
@ Джесс Спот-на. Вполне возможно, что это просто вопрос соглашения (хотя я надеюсь, что это не так, это был бы такой скучный ответ). Мой первоначальный интерес к этому вопросу заключался в том, что я думал, что использование надлежащего экземпляра для представления объекта «запущенное приложение» и наличие точки входа в качестве метода (или конструктора) этого класса было бы гораздо более очевидным дизайном, поскольку Java был разработан, чтобы быть объектно-ориентированным с самого начала, и так как казалось бы аналогичные объекты (потоки, через Runnable) в Java действительно используют этот дизайн. Почему (очевидное) исключение здесь?
Конрад Рудольф