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

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

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

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

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

Andrew Tobilko 03.04.2016 01:18

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

Thorbjørn Ravn Andersen 07.05.2016 12:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
514
2
507 122
37
Перейти к ответу Данный вопрос помечен как решенный

Ответы 37

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

Это не условность; это часть спецификации языка; среда выполнения не распознает класс без статического метода main как допустимую точку входа.

Rob 28.09.2008 23:51

Сама спецификация языка следует соглашению. Для разработчиков Java нет фактического требования выбирать статический файл main. Однако, как объясняет Логан, альтернативы более сложны.

David Arno 28.09.2008 23:55

@DavidArno Было бы разумнее сказать, что соглашение следует спецификации языка.

user207421 24.04.2016 05:34

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

Хорошо, но не могла ли среда выполнения создать экземпляр одного объекта класса? А затем вызвать метод Main? Почему?

Andrei Rînea 30.09.2008 00:30

Как JVM узнает, какой конструктор вызвать, если у вашего основного класса есть перегруженные конструкторы? Какие параметры он передаст?

Jacob Krall 30.09.2008 02:41

@ Нет, когда вы говорите родительский класс, вы имеете в виду класс, содержащий основной метод? Потому что, если это так, термин «родительский класс» здесь довольно сбивает с толку, и в противном случае он не имел бы для меня никакого смысла. Кроме того, если по соглашению мы используем public static void main..., почему не может быть договоренности о том, что класс точки входа приложения должен иметь общедоступный конструктор по умолчанию?

Edwin Dalorzo 12.05.2012 15:48

@Jacob Как JVM узнает, какой перегруженный static void main следует вызвать? Без проблем.

Konrad Rudolph 17.07.2012 02:00

Поскольку main должен быть статическим методом, что, если мне придется вызывать foo () и bar () из main? Они тоже должны быть статичными, верно? Поскольку статический метод не может ссылаться на нестатический метод. Теперь, если foo и bar по очереди вызывают какие-то другие функции, то они тоже должны быть статичными! Таким образом, мы закончим тем, что все функции будут статичными. Но я чувствую, что здесь чего-то не хватает. Потому что этого не может быть.

Namratha 24.09.2012 13:24

@ Намрата: Да, тебе что-то не хватает. Это просто неправда, что «статический метод не может ссылаться на нестатический метод». Правильное утверждение: «Каждый статический метод должен предоставлять объект при использовании любого нестатического метода». И посмотрите, методы static, такие как main, часто используют new для создания такого объекта.

Ben Voigt 04.12.2012 04:12

В C++static int main не компилируется: cannot declare '::main' to be static. С другой стороны, в C он будет компилироваться, а затем выйдет из строя компоновщик, когда он попытается понять ссылку ОС на main: In function _start: (.text+0x20): undefined reference to 'main'. Потому что вы сделали его статичным, что сделало его невозможным для внешнего модуля компиляции.

Braden Best 21.08.2016 21:50

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

Неправильный. Или, по крайней мере, очень неточно. открытый класс Main {статический объект объекта = новый объект () {{System.out.println ("объект создан"); }}; public static void main (String [] args) {System.out.println ("в основном"); }}

eljenso 12.01.2009 15:27

Справедливый комментарий. Технически я должен был сказать, что до вызова метода Main класс, содержащий основной метод, не создается.

BlackWasp 29.03.2009 23:12

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

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

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

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

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

Ответ принят как подходящий

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

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

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

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

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

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

Конечно, вы правы. открытый класс JavaClass {частный статический JavaClass initme = новый JavaClass (); public void main (String [] args) {}} initme инициализируется перед вызовом main (). Однако основная часть моего ответа все еще остается в силе.

Jacob Krall 30.09.2008 02:40

Почему бы не использовать интерфейс точки входа для решения этих проблем; любой основной объект должен был бы реализовать интерфейс.

Peter 13.11.2011 09:37

Реализация интерфейса не решает проблему создания экземпляра.

Jacob Krall 15.11.2011 22:59

Что ж, если по соглашению мы используем public static void main..., почему не может быть договоренности о том, что класс точки входа приложения должен иметь общедоступный конструктор по умолчанию?

Edwin Dalorzo 12.05.2012 15:45

Мне лично нравится, что public static void main служит маркером точки входа - общедоступный конструктор без параметров не кричит: «Вероятно, это точка входа!» таким же образом.

Jacob Krall 12.05.2012 20:58

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

David Harkness 14.07.2012 23:48

«Какой конструктор следует вызвать?» В чем проблема с даже возможно? Та же «проблема» существует для решения, которое вызывает main. Как ни странно (для вас), JVM прекрасно справляется с этим.

Konrad Rudolph 17.07.2012 23:50

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

gthm 28.02.2013 22:48

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

Praveen Kumar 10.03.2013 13:52

Хм ... Совершенно верно, поэтому JVM не нужно создавать newInstance (), а просто использовать основной метод invike ().

Akhilesh Dhar Dubey 02.05.2014 15:19

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

Master 01.06.2014 18:39

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

Janac Meena 24.03.2016 03:51

Нет ничего плохого в том, чтобы определить, что основной точкой входа является заданный конструктор класса (с аргументом String []), но разработчики Java просто приняли другое решение.

Thorbjørn Ravn Andersen 07.05.2016 12:25

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

Sudheesh 12.01.2017 11:22

@Sudheesh: JVM - это как раз то, что обеспечивает применение модификаторов доступа. Он может делать все, что захочет, с помощью частных методов.

Jacob Krall 03.08.2017 19:59

@gthm: JVM может получить доступ ко всем методам, как частным, так и общедоступным. Как иначе он мог бы их казнить?

Jacob Krall 03.08.2017 20:00

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

Это просто условность. Фактически, даже имя 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 автоматическое обнаружение ' запускаемые классы в проекте.

+1: Очень интересно (особенно часть о написании нестандартного java.exe)

Adam Paynter 01.05.2011 13:15

Честно говоря, хотя ответы Джейкоба и Ноя логичны и, вероятно, частично то, что приходило в голову Гослингу и др. При разработке языка, я думаю, что «удобство» и «соглашение о C», упомянутые в последнем абзаце, составляют 99,9% того, почему значение по умолчанию - использовать общедоступный статический метод с именем main. Подробности использования исполняемым файлом JNI для начальной загрузки JVM, обработки аргументов и передачи их любому методу, который он хочет, должны выиграть этот ответ в награду.

David Harkness 15.07.2012 00:00

Интересно, что я не согласен с утверждением «Это просто условность». Часть ответа. Основной вопрос OP был причиной статичности в объявлении. Я не думаю, что static в декларации main() предназначен только для условности. Однако тот факт, что это `main () ', а не что-то еще, возможен.

Jared 15.07.2012 05:15

@ Дэвид Так оно и было. На самом деле я бы предпочел ответ от одного из людей, изначально участвовавших в этом, но это было очень далеко. К сожалению, большинство других ответов - это упражнение в произвольных рассуждениях. Это дает довольно интересные детали, помимо того, что у него есть смирение, чтобы не придумывать неправильные технические детали, чтобы урезонить (вероятно) нетехническую причину.

Konrad Rudolph 17.07.2012 23:45

@Jared - Статические методы настолько близки к функциям языка C, насколько это возможно. Нестатический метод потребует создания экземпляра класса, который не требуется в C.

David Harkness 18.07.2012 00:08

@DavidHarkness Я в курсе. Я говорю, что статика, требующаяся в объявлении main(), соответствует требованиям языка, а не "просто соглашению".

Jared 18.07.2012 00:42

@Jared - Им мог потребоваться общедоступный конструктор без аргументов и сделать main нестатичным и по-прежнему соответствовать рамкам языка. Не получив ответа от дизайнеров, мы просто должны согласиться, чтобы не согласиться. :)

David Harkness 18.07.2012 00:58

@ Джеймс С удовольствием. Если у вас когда-нибудь появится возможность написать небольшую программу запуска JNI, я настоятельно рекомендую ее - это несложно сделать (в Интернете есть множество примеров), и это даст вам почувствовать часть мира Java, которую мы обычно принимаем за предоставляется.

Kevin Day 09.08.2012 07:10

Почему JNI должен быть здесь задействован? java.exe - это собственное приложение. JVM - это собственная библиотека с собственной точкой входа. Собственное приложение, вызывающее родную точку входа в собственной библиотеке, не требует JNI. Сервисы JNI предоставляются JVM - поэтому должно быть очевидно, что JNI нельзя использовать для загрузки JVM, поскольку это может создать проблему с курицей и яйцом.

Ben Voigt 04.12.2012 04:14

@BenVoigt JNI используется для обоих направлений (native -> JVM и JVM -> native). Вы используете JNI для загрузки JVM, инструктируете его загрузить класс, определяете местонахождение основного метода и вызываете этот метод. Это очень много JNI. Вопреки распространенному мнению, java.exe - это виртуальная машина Java нет - это тонкая оболочка, которая просто загружает JNI DLL и вызывает в ней методы.

Kevin Day 04.12.2012 07:38

@Kevin: Но ни java.exe, ни загружаемая им библиотека JVM не являются байт-кодом Java. JNI не участвует в загрузке JVM, потому что нет Java, пока JVM не будет загружена.

Ben Voigt 04.12.2012 09:21

@BenVoigt Вы вызываете LoadLibrary (), чтобы получить jvm dll. Затем вы вызываете getprocaddress ("JNI_CreateJavaVM"), затем вызываете функцию JNI_CreateJavaVM (docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/…). После загрузки виртуальной машины вы используете стандартные вызовы JNI, чтобы найти правильный класс, загрузить статический основной метод и вызвать его. Здесь не так много места для неправильного толкования. JNI - это абсолютно то, как вы загружаете виртуальную машину. Возможно, вы привыкли писать JNI только на стороне клиента, используя ключевое слово native, javah -jni и т. д., Но это только половина JNI.

Kevin Day 05.12.2012 08:04

@Kevin: Умм LoadLibrary - это встроенная функция.

Ben Voigt 05.12.2012 08:12

@BenVoigt Я не думаю, что это продуктивно на данный момент. Не стесняйтесь верить в то, что вы об этом хотите.

Kevin Day 05.12.2012 08:14

Это ответ, который я искал. Я подозревал, что причина того, что основной метод статичен, имеет какое-то отношение к JNI, но Google не особо придумал условия поиска, которые я использовал.

searchengine27 14.11.2014 22:13

Полезный и интересный ответ, но не отвечает на вопрос ОП.

golimar 18.01.2017 13:39

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

Dawood ibn Kareem 01.10.2017 07:35

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

Ответ вводит в заблуждение.

joey rohan 10.11.2015 01:03

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

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

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

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

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

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

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

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

Часто задаваемый вопрос, почему main () статичен в Java.

Отвечать: Мы знаем, что в Java выполнение начинается с main () JVM. Когда JVM выполняет main () в это время, класс, содержащий main (), не создается, поэтому мы не можем вызвать нестатический метод без ссылки на его объект. Чтобы вызвать его, мы сделали его статическим, из-за чего загрузчик классов загружает все статические методы в пространство памяти контекста JVM, откуда JVM может их напрямую вызывать.

Этот ответ был впервые дан в сентябре 2008 года. На вопрос был дан ответ. Вы не добавляете здесь никакой ценности.

user207421 02.07.2011 08:00

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

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

Все методы «имеют только одну копию».

user207421 24.04.2016 05:35

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

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

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

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

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

Это неверно. До достижения main создается множество объектов. И если вы включите статический конструктор в класс, содержащий main, он также будет выполняться до main.

Konrad Rudolph 11.07.2012 11:01

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

Это просто напрашивается вопрос. Java в любом случае нужен загрузчик приложений, который выполняет тяжелую работу перед вызовом main. Ваше объяснение того, что main слишком сложен для новичков, кажется невероятным. Фактически, статический main сбивает с толку новичков, я сомневаюсь, что конструктор был бы более сложным. Вы говорите, что «конструктор не должен отвечать за поведение объекта». Звучит интересно, но я не уверен, что согласен. Почему нет? Что этому мешает?

Konrad Rudolph 11.07.2012 11:03

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

The method must be declared public and static, it must not return any value, and it must accept a String array as a parameter. By default, the first non-option argument is the name of the class to be invoked. A fully-qualified class name should be used. If the -jar option is specified, the first non-option argument is the name of a JAR archive containing class and resource files for the application, with the startup class indicated by the Main-Class manifest header.

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

Вы имеете в виду правило языка.

user207421 24.04.2016 05:41

The public static void keywords mean the Java virtual machine (JVM) interpreter can call the program's main method to start the program (public) without creating an instance of the class (static), and the program does not return data to the Java VM interpreter (void) when it ends.

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

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

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

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

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

Finally, after completion of the initialization for class Test (during which other consequential loading, linking, and initializing may have occurred), the method main of Test is invoked.

The method main must be declared public, static, and void. It must accept a single argument that is an array of strings. This method can be declared as either

public static void main(String[] args)

or

public static void main(String... args)

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

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

The Java virtual machine starts execution by invoking the method main of some specified class and passing it a single argument, which is an array of strings. This causes the specified class to be loaded (§2.17.2), linked (§2.17.3) to other types that it uses, and initialized (§2.17.4). The method main must be declared public, static, and 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);

... ...

Проблема здесь в том, что это действительно хороший ответ очень на вопрос в его первоначальной форме с большим количеством ссылок (+1). Однако мне бы хотелось узнать о обоснование для проектного решения о том, чтобы сделать статический метод точкой входа, а не конструктором или методом экземпляра.

Konrad Rudolph 12.07.2012 10:57

@KonradRudolph, по вопросам, касающимся языка и дизайна спецификации JVM, возможно, вы могли бы попробовать связаться с исходным кодом от Oracle и посмотреть, сможете ли вы получить какие-либо положительные отзывы.

yorkw 12.07.2012 13:27

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

Yves Martin 16.07.2012 01:38

@KonradRudolph Интересно, что Oak (предшественник Java) уже требовал, чтобы у основного метода был аналогичный прототип: public static void main(String arguments[]) - Ссылка: Дуб 0.2 Spec.

assylias 16.07.2012 16:19

@Yves Это может быть. В этом нет необходимости, если другой дизайн имеет смысл. Я слышал здесь несколько хороших аргументов в комментариях, но я все еще думаю, что процесс очень похож на поток (это является), а поток в Java обычно представлен как экземпляр Runnable. Представление всего процесса одним и тем же способом (т.е. имея Runnable.Run в качестве точки входа) определенно имеет смысл в Java. Конечно, сам Runnable, возможно, является недостатком дизайна, вызванным тем фактом, что в Java нет анонимных методов (пока). Но раз уж он там ...

Konrad Rudolph 16.07.2012 19:30

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

The main method is static to give the Java VM interpreter a way to start the class without creating an instance of the control class first. Instances of the control class are created in the main method after the program starts.

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

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

Konrad Rudolph 12.07.2012 17:40

Мне жаль, что мой ответ повторяет то, что сказали другие; Я ответил только в меру моего понимания и из того, что я смог найти в Интернете. Судя по результатам, которые я просмотрел, нет другой причины, почему основной метод статичен; если где-то глубоко не спрятано одно, возможно, это единственный ответ. Мое понимание Java довольно базовое, но я слышал вышеупомянутую причину (от профессоров, из учебников и т. д.) И никогда не слышал ничего другого.

Jesse M 12.07.2012 17:49

@Jesse M Ваш комментарий имеет смысл только в том случае, если вы даже не думали сначала прочитать другие ответы. Что, кстати, не надумано. Как вы сами упомянули, ваше понимание довольно базовое, поэтому весьма вероятно, что кто-то уже ответил на вопрос более компетентно. И ваш комментарий кажется рационализацией, чтобы ваш ответ выглядел лучше. Поразительно, что у вас есть учебники по Java и профессора, которые думают так, как вы, и, честно говоря, я не верю, что они думают. (Есть ссылки?)

LeoR 13.07.2012 17:13

@KonradRudolph Верхние комментарии кажутся вполне разумными. main () используется как точка входа в программу, и на веб-сайте Java есть несколько ссылок, в которых говорится, что он должен быть похож на то, как в C / C++ есть функция main (). Поскольку Java - это все объекты, он должен быть статическим, чтобы избежать создания экземпляров объекта. Статический статус также позволяет загружать его и выполнять в JVM во время выполнения. Я просто извергаю предыдущие ответы, но мне интересно, какой ответ вы бы сочли удовлетворительным. Я думаю, лучшее, что вы получите, это «Вот как они этого хотели». Помните дату создания Java.

trevor-e 14.07.2012 01:39

@Atlos Ваши причины на самом деле не являются объяснением: вы говорите, что «он должен быть статическим, чтобы избежать создания экземпляра объекта», но почему вы вообще хотите избежать создания экземпляра объекта? Этот - вот настоящий вопрос.

Konrad Rudolph 15.07.2012 00:14

@KonradRudolph Избежать создания экземпляров объекта сегодня не составляет особой проблемы, но когда вышла Java, я увидел, что это проблема памяти и скорости. Изначально Java была предназначена для потребительской цифровой электроники в начале 90-х, и я мог представить себе ограничения, с которыми им пришлось столкнуться. Именно на этом рынке Java конкурировала с C / C++. Я просто соединяю обе идеи вместе, так что никаких «веских доказательств», как вы хотите, но я думаю, что это имеет наибольший смысл. Лучше всего написать в Sun Microsystems по электронной почте и спросить инженера-проектировщика.

trevor-e 15.07.2012 01:02

@ Атлос, я на это не куплюсь. Это один раз, это занимает меньше микросекунды. Даже когда вышла Java. Вероятно, это даже невозможно измерить.

Konrad Rudolph 15.07.2012 01:03

@LeoR Я признаю, что был виноват, не прочитав сначала все остальные ответы; Я не знал, в какой степени повторялся мой ответ. Причина, по которой я чувствовал себя достаточно уверенно, чтобы ответить на вопрос, заключалась в том, что мне никогда раньше не приходилось «глубоко» думать об этой проблеме; Когда я сказал, что слышал заявление профессоров, я передал тот факт, что это было просто тем, чему меня учили. Я не могу процитировать, когда и где именно я узнал об этом, по той же причине, по которой я не могу сказать вам, когда узнал о циклах for; Я всегда принимал рассуждения как должное.

Jesse M 16.07.2012 19:06

Я также не понимаю, почему это такое экстраординарное заявление. Вы сами сказали, что все остальные ответы были такими же, как у меня; Так почему же неразумно, что это широко распространенное мнение, которому многие люди научились или чему их научили? У меня нет причин лгать о том, что я узнал, если только я не так отчаянно нуждался в щедрости Конрада - которую я знал, что не получу, поскольку многие ответы были длиннее и сложнее, чем мои. Это вызывает основную причину, по которой я вообще ответил на вопрос:

Jesse M 16.07.2012 19:10

@KonradRudolph Возможно ли, что ответа, который вы ищете, просто не существует? Да, создание экземпляра объекта занимает очень мало времени, но означает ли это, что есть смысл заставлять программистов делать это, когда в этом нет необходимости? Почему рассуждение не может быть таким же, как и с любым другим статическим методом? Насколько мне известно, вы можете достичь тех же целей, не используя статические методы, как используя их в любой программе. Но когда метод логически не связан с определенным классом, есть возможность не связывать его с классом.

Jesse M 16.07.2012 19:13

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

Jesse M 16.07.2012 19:14

@ Джесси Спот-он. Вполне возможно, что это всего лишь вопрос условности (хотя я надеюсь, что это не так, это был бы такой скучный ответ). Мой первоначальный интерес к этому вопросу был вызван тем, что я думал, что использование подходящего экземпляра для представления объекта «запущенное приложение» и использование точки входа в качестве метода (или конструктора) этого класса было бы гораздо более очевидным решением, поскольку Java был разработан как объектно-ориентированный с самого начала, и поскольку аналогичные объекты (потоки, через Runnable) в Java, делать используют этот дизайн. Почему здесь (очевидное) исключение?

Konrad Rudolph 16.07.2012 19:25

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

The method main must be declared public, static, and void. It must specify a formal parameter (§8.4.1) whose declared type is array of String.

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

The Java virtual machine starts up by creating an initial class, which is specified in an implementation-dependent manner, using the bootstrap class loader (§5.3.1). The Java virtual machine then links the initial class, initializes it, and invokes the public class method void main(String[]). The invocation of this method drives all further execution. Execution of the Java virtual machine instructions constituting the main method may cause linking (and consequently creation) of additional classes and interfaces, as well as invocation of additional methods.

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

Initialization of a class or interface consists of executing its class or interface initialization method.

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

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

A class or interface has at most one class or interface initialization method and is initialized (§5.5) by invoking that method. The initialization method of a class or interface has the special name <clinit>, takes no arguments, and is void.

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

At the level of the Java virtual machine, every constructor written in the Java programming language (JLS §8.8) appears as an instance initialization method that has the special name <init>.

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

Давайте просто сделаем вид, что static не потребуется в качестве точки входа в приложение.

Тогда класс приложения будет выглядеть так:

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

Различие между кодом конструктора и методом main необходимо, потому что в OO-режиме конструктор должен только следить за тем, чтобы экземпляр был инициализирован должным образом. После инициализации экземпляр можно использовать для предполагаемой «службы». Помещение полного кода приложения в конструктор испортит это.

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

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

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

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

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

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

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


1Here the complete signature counts as only one contract.

На самом деле требования более сложные: должен быть метод main, который является public, static и имеет подпись void main(String[]). Я согласен с тем, что, если бы метод был методом экземпляра, JRE имел бы немного больше работы, но Добрый работы был бы таким же, а сложность не намного выше (см. Обсуждения в комментариях к предыдущему ответу). Я не верю, что это различие объясняет решение сделать точку входа статической, в частности, поскольку требуемые методы для разрешения метода экземпляра существуют и легко могут быть использованы.

Konrad Rudolph 15.07.2012 16:23

@KonradRudolph: Моя точка зрения не связана с работой, которую должна будет выполнить JRE. Моя точка зрения заключается в том, чтобы заставить каждый пользователь языка выполнять больше контрактов по мере необходимости. В этом смысле метод static public main(String[]) - это подпись один и, следовательно, контракт один. В противном случае должны выполняться три контракта независимый.

A.H. 15.07.2012 16:28

Ах. Я все еще не согласен с тем, что это имеет значение. Классы точек входа вполне могут реализовать Runnable. Ясно, что Java ожидает, что разработчики будут все время следовать этому контракту, почему это должно быть слишком много для точки входа в приложение? Это бессмысленно.

Konrad Rudolph 15.07.2012 16:37

@KonradRudolph: Потому что экземпляр Runnable создается пользователем, а не системой. Следовательно, для Runnable контракты №1 и №3 не требуются.

A.H. 15.07.2012 16:40

@KonradRudolph Даже если степень сложности невелика, метод экземпляра более сложен. В этом случае сложность - разумное оправдание для выбора static.

Czar Pino 15.07.2012 16:40

@ A.H. Теперь вы сами себе противоречите, я думал, вы возражали против того, что Пользователь, а не система, должна работать против фиксированных контрактов. Как бы то ни было, требования в обоих случаях одинаковы как для системы, так и для пользователя: пользователь должен соблюдать контракты, система должна обеспечивать их выполнение.

Konrad Rudolph 15.07.2012 17:15

@KonradRudolph: Нет противоречия: в одном случае система заставила бы пользователя заключить три контракта. Сомнительные контракты, которые нельзя проверить через компилятор и которые, с точки зрения пользователя, независимы. В обычном случае Thread и Runnable от пользователя ничего не скрывается, он может четко видеть, что происходит, и у него есть возможность реализовать Только тех контрактов, которые ему подходят - все контролирует он, а не система.

A.H. 15.07.2012 17:21

@ A.H. Теперь я понимаю, о чем вы говорите. Мне нужно подумать, убедит ли это меня.

Konrad Rudolph 15.07.2012 17:24

Это лучший ответ здесь. Жаль, что многие пользователи прочитают только 2 или 3 первых ответа на странице; а этот вряд ли скоро туда попадет. В нем упоминается важный момент, когда конструктор предназначен ТОЛЬКО для инициализации - и поэтому нет смысла кодировать в стиле, в котором конструктор запускает все приложение.

Dawood ibn Kareem 31.10.2014 08:19

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

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

In Java, the reason of public static void main(String[] args) is that

  1. Gosling wanted
  2. the code written by someone experienced in C (not in Java)
  3. to be executed by someone used to running PostScript on NeWS

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

 
For C#, the reasoning is transitively similar so to speak. Language designers kept the program entry point syntax familiar for programmers coming from Java. As C# architect Anders Hejlsberg puts it,

...our approach with C# has simply been to offer an alternative... to Java programmers...

...

Что означает 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.

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

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

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

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

Class_name.method_name();

можно получить доступ к основному методу.

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

Это случается, когда программа выполняется, а не компилируется.

user207421 24.04.2016 05:40

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

public static void main(String args[])

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

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

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

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

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

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

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

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

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

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

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

java ClassName argument1 argument2 ...

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

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

—at this point, no objects of the class have been created.

Declaring main as static allows the JVM to invoke main without creating an instance of the class.

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

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

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

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

для получения дополнительной информации посетите это видео: https://thewikihow.com/video_Z7rPNwg-bfk&feature=youtu.be

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