



Это просто условность, но, вероятно, более удобная, чем альтернатива. При использовании статического main все, что вам нужно знать для вызова Java-программы, - это имя и расположение класса. Если бы он не был статическим, вам также нужно было бы знать, как создать экземпляр этого класса, или потребовать, чтобы у класса был пустой конструктор.
Это не условность; это часть спецификации языка; среда выполнения не распознает класс без статического метода main как допустимую точку входа.
Сама спецификация языка следует соглашению. Для разработчиков Java нет фактического требования выбирать статический файл main. Однако, как объясняет Логан, альтернативы более сложны.
@DavidArno Было бы разумнее сказать, что соглашение следует спецификации языка.
Метод main() в C++, C# и Java статичен.
Поскольку они затем могут быть вызваны механизмом выполнения без, которому необходимо создавать экземпляры любых объектов, все остальное сделает код в теле main().
Хорошо, но не могла ли среда выполнения создать экземпляр одного объекта класса? А затем вызвать метод Main? Почему?
Как JVM узнает, какой конструктор вызвать, если у вашего основного класса есть перегруженные конструкторы? Какие параметры он передаст?
@ Нет, когда вы говорите родительский класс, вы имеете в виду класс, содержащий основной метод? Потому что, если это так, термин «родительский класс» здесь довольно сбивает с толку, и в противном случае он не имел бы для меня никакого смысла. Кроме того, если по соглашению мы используем public static void main..., почему не может быть договоренности о том, что класс точки входа приложения должен иметь общедоступный конструктор по умолчанию?
@Jacob Как JVM узнает, какой перегруженный static void main следует вызвать? Без проблем.
Поскольку main должен быть статическим методом, что, если мне придется вызывать foo () и bar () из main? Они тоже должны быть статичными, верно? Поскольку статический метод не может ссылаться на нестатический метод. Теперь, если foo и bar по очереди вызывают какие-то другие функции, то они тоже должны быть статичными! Таким образом, мы закончим тем, что все функции будут статичными. Но я чувствую, что здесь чего-то не хватает. Потому что этого не может быть.
@ Намрата: Да, тебе что-то не хватает. Это просто неправда, что «статический метод не может ссылаться на нестатический метод». Правильное утверждение: «Каждый статический метод должен предоставлять объект при использовании любого нестатического метода». И посмотрите, методы static, такие как main, часто используют new для создания такого объекта.
В C++static int main не компилируется: cannot declare '::main' to be static. С другой стороны, в C он будет компилироваться, а затем выйдет из строя компоновщик, когда он попытается понять ссылку ОС на main: In function _start: (.text+0x20): undefined reference to 'main'. Потому что вы сделали его статичным, что сделало его невозможным для внешнего модуля компиляции.
Перед вызовом основного метода экземпляры объектов не создаются. Наличие ключевого слова static означает, что метод может быть вызван без предварительного создания каких-либо объектов.
Неправильный. Или, по крайней мере, очень неточно. открытый класс Main {статический объект объекта = новый объект () {{System.out.println ("объект создан"); }}; public static void main (String [] args) {System.out.println ("в основном"); }}
Справедливый комментарий. Технически я должен был сказать, что до вызова метода Main класс, содержащий основной метод, не создается.
Потому что в противном случае для выполнения потребуется экземпляр объекта. Но он должен вызываться с нуля, без предварительного создания объекта, поскольку обычно это задача функции 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 (). Однако основная часть моего ответа все еще остается в силе.
Почему бы не использовать интерфейс точки входа для решения этих проблем; любой основной объект должен был бы реализовать интерфейс.
Реализация интерфейса не решает проблему создания экземпляра.
Что ж, если по соглашению мы используем public static void main..., почему не может быть договоренности о том, что класс точки входа приложения должен иметь общедоступный конструктор по умолчанию?
Мне лично нравится, что public static void main служит маркером точки входа - общедоступный конструктор без параметров не кричит: «Вероятно, это точка входа!» таким же образом.
@EdwinDalorzo - Что можно получить, если принудительно создать экземпляр класса точки входа? Вызов статического метода создает наименьшую нагрузку на класс. Вы можете создать экземпляр самого себя бесплатно, если это имеет больше смысла для вашего дизайна.
«Какой конструктор следует вызвать?» В чем проблема с даже возможно? Та же «проблема» существует для решения, которое вызывает main. Как ни странно (для вас), JVM прекрасно справляется с этим.
Основной метод всегда является общедоступным, потому что к нему должен обращаться механизм выполнения, JVM.
Возможно, эту неоднозначность можно разрешить, просто вызвав конструктор по умолчанию, хотя в этом случае конструктора по умолчанию не существует, но это можно было бы пометить как исключение, но тогда были бы накладные расходы на выделение памяти. Кроме того, используется public, чтобы JVM могла получить к нему доступ, конечно, поставщик доступа по умолчанию не будет работать.
Хм ... Совершенно верно, поэтому JVM не нужно создавать newInstance (), а просто использовать основной метод invike ().
main становится общедоступным статическим, поэтому, когда вы запускаете класс из командной строки, компилятор внутренне вызывает YourClass.main (args).
Этот ответ приобрел для меня смысл, когда я понял, что, поскольку main не является статическим в этом примере, единственный способ вызвать его - это создать экземпляр объекта JavaClass и вызвать main для этого объекта. Это означает, что мы должны вызвать конструктор для JavaClass, но какой именно, поскольку у нас еще не было возможности указать какой-либо код.
Нет ничего плохого в том, чтобы определить, что основной точкой входа является заданный конструктор класса (с аргументом String []), но разработчики Java просто приняли другое решение.
Основной метод вызывается JVM. JVM выходит за рамки проекта. Поэтому, если основная функция не является общедоступной, JVM не сможет вызвать эту функцию.
@Sudheesh: JVM - это как раз то, что обеспечивает применение модификаторов доступа. Он может делать все, что захочет, с помощью частных методов.
@gthm: JVM может получить доступ ко всем методам, как частным, так и общедоступным. Как иначе он мог бы их казнить?
Если основной метод не будет статическим, вам нужно будет создать объект вашего основного класса вне программы. Как бы вы хотели это сделать?
Это просто условность. Фактически, даже имя 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)
Честно говоря, хотя ответы Джейкоба и Ноя логичны и, вероятно, частично то, что приходило в голову Гослингу и др. При разработке языка, я думаю, что «удобство» и «соглашение о C», упомянутые в последнем абзаце, составляют 99,9% того, почему значение по умолчанию - использовать общедоступный статический метод с именем main. Подробности использования исполняемым файлом JNI для начальной загрузки JVM, обработки аргументов и передачи их любому методу, который он хочет, должны выиграть этот ответ в награду.
Интересно, что я не согласен с утверждением «Это просто условность». Часть ответа. Основной вопрос OP был причиной статичности в объявлении. Я не думаю, что static в декларации main() предназначен только для условности. Однако тот факт, что это `main () ', а не что-то еще, возможен.
@ Дэвид Так оно и было. На самом деле я бы предпочел ответ от одного из людей, изначально участвовавших в этом, но это было очень далеко. К сожалению, большинство других ответов - это упражнение в произвольных рассуждениях. Это дает довольно интересные детали, помимо того, что у него есть смирение, чтобы не придумывать неправильные технические детали, чтобы урезонить (вероятно) нетехническую причину.
@Jared - Статические методы настолько близки к функциям языка C, насколько это возможно. Нестатический метод потребует создания экземпляра класса, который не требуется в C.
@DavidHarkness Я в курсе. Я говорю, что статика, требующаяся в объявлении main(), соответствует требованиям языка, а не "просто соглашению".
@Jared - Им мог потребоваться общедоступный конструктор без аргументов и сделать main нестатичным и по-прежнему соответствовать рамкам языка. Не получив ответа от дизайнеров, мы просто должны согласиться, чтобы не согласиться. :)
@ Джеймс С удовольствием. Если у вас когда-нибудь появится возможность написать небольшую программу запуска JNI, я настоятельно рекомендую ее - это несложно сделать (в Интернете есть множество примеров), и это даст вам почувствовать часть мира Java, которую мы обычно принимаем за предоставляется.
Почему JNI должен быть здесь задействован? java.exe - это собственное приложение. JVM - это собственная библиотека с собственной точкой входа. Собственное приложение, вызывающее родную точку входа в собственной библиотеке, не требует JNI. Сервисы JNI предоставляются JVM - поэтому должно быть очевидно, что JNI нельзя использовать для загрузки JVM, поскольку это может создать проблему с курицей и яйцом.
@BenVoigt JNI используется для обоих направлений (native -> JVM и JVM -> native). Вы используете JNI для загрузки JVM, инструктируете его загрузить класс, определяете местонахождение основного метода и вызываете этот метод. Это очень много JNI. Вопреки распространенному мнению, java.exe - это виртуальная машина Java нет - это тонкая оболочка, которая просто загружает JNI DLL и вызывает в ней методы.
@Kevin: Но ни java.exe, ни загружаемая им библиотека JVM не являются байт-кодом Java. JNI не участвует в загрузке JVM, потому что нет Java, пока JVM не будет загружена.
@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: Умм LoadLibrary - это встроенная функция.
@BenVoigt Я не думаю, что это продуктивно на данный момент. Не стесняйтесь верить в то, что вы об этом хотите.
Это ответ, который я искал. Я подозревал, что причина того, что основной метод статичен, имеет какое-то отношение к JNI, но Google не особо придумал условия поиска, которые я использовал.
Полезный и интересный ответ, но не отвечает на вопрос ОП.
Это интересный и информативный ответ, но я считаю, что на самом деле он в корне неверен. Истинная причина очень проста - main - это static, поэтому JVM не нужно создавать объект перед его вызовом. Это не имеет ничего общего с условностями.
потому что статические члены не являются частью какого-либо конкретного класса, и этот основной метод не требует создания своего объекта, но может ссылаться на все другие классы.
Ответ вводит в заблуждение.
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 года. На вопрос был дан ответ. Вы не добавляете здесь никакой ценности.
Статическое ключевое слово в основном методе используется, потому что в основном методе не выполняется никаких экземпляров. Но объект создается, а не вызывается, в результате мы используем статическое ключевое слово в основном методе. В контексте jvm память создается при загрузке в нее класса, и все статические члены присутствуют в этой памяти. если мы сделаем основной статический объект сейчас, он будет в памяти и будет доступен для jvm (class.main (..)), поэтому мы сможем вызвать основной метод без необходимости создания кучи.
Я думаю, что ключевое слово static делает основной метод методом класса, а методы класса имеют только одну его копию и могут использоваться всеми, а также не требуют объекта для ссылки. Поэтому, когда класс драйвера скомпилирован, можно вызвать основной метод. (Я просто на уровне алфавита java, извините, если я ошибаюсь)
Все методы «имеют только одну копию».
main () статичен, потому что; на этом этапе жизненного цикла приложения стек приложения носит процедурный характер из-за отсутствия объектов, которые еще не созданы.
Это чистый лист. В этот момент ваше приложение работает даже без объявления каких-либо объектов (помните, что существуют процедурные шаблоны кодирования AND OO). Вы, как разработчик, превращаете приложение в объектно-ориентированное решение, создавая экземпляры своих объектов и в зависимости от кода, скомпилированного внутри.
Объектно-ориентированный подход хорош по миллионам очевидных причин. Однако прошли те времена, когда большинство разработчиков VB регулярно использовали в своем коде такие ключевые слова, как «goto». "goto" - это процедурная команда в VB, которая заменяется ее объектно-ориентированным аналогом: вызов метода.
Вы также можете рассматривать статическую точку входа (главную) как чистую свободу. Если бы Java была достаточно разной, чтобы создать экземпляр объекта и представить вам только этот экземпляр при запуске, у вас не было бы другого выбора, НО написать процедурное приложение. Каким бы невообразимым это ни звучало для Java, вполне возможно, что существует множество сценариев, требующих процедурных подходов.
Вероятно, это очень непонятный ответ. Помните, что «класс» - это всего лишь набор взаимосвязанного кода. «Экземпляр» - изолированное, живое и дышащее автономное поколение этого класса.
Это неверно. До достижения main создается множество объектов. И если вы включите статический конструктор в класс, содержащий main, он также будет выполняться до main.
Настоящая точка входа в любое приложение - статический метод. Если язык Java поддерживает метод экземпляра в качестве «точки входа», тогда среде выполнения потребуется реализовать его внутри как статический метод, который создает экземпляр объекта, за которым следует вызов метода экземпляра.
Разобравшись с этим, я исследую причины выбора одного из следующих трех вариантов:
static void main(), каким мы его видим сегодня.void main() вызвал только что созданный объект.Program, то выполнение фактически состояло бы из new Program()).static void main()
main().void main()
new ClassName().main().new ClassName()
Я сделаю это в обратном порядке.
Имейте в виду, что одной из целей разработки Java было подчеркнуть (по возможности, потребовать) хорошие методы объектно-ориентированного программирования. В этом контексте конструктор объекта инициализирует объект, но не должен нести ответственность за поведение объекта. Следовательно, спецификация, в которой была указана точка входа new ClassName(), запутала бы ситуацию для новых разработчиков Java, заставляя исключение при разработке «идеального» конструктора для каждого приложения.
Сделав main() методом экземпляра, указанная выше проблема определенно решена. Однако это создает сложность, требуя, чтобы в спецификации была указана подпись конструктора класса записи, а также подпись метода main().
Таким образом, указание static void main() создает спецификацию с наименьшей сложностью, придерживаясь принципа размещения поведения в методах. Учитывая, насколько просто реализовать метод main(), который сам создает экземпляр класса и вызывает метод экземпляра, нет никакого реального преимущества в указании main() в качестве метода экземпляра.
Это просто напрашивается вопрос. Java в любом случае нужен загрузчик приложений, который выполняет тяжелую работу перед вызовом main. Ваше объяснение того, что main слишком сложен для новичков, кажется невероятным. Фактически, статический main сбивает с толку новичков, я сомневаюсь, что конструктор был бы более сложным. Вы говорите, что «конструктор не должен отвечать за поведение объекта». Звучит интересно, но я не уверен, что согласен. Почему нет? Что этому мешает?
Это просто соглашение, как мы видим здесь:
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
Вы имеете в виду правило языка.
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.
Так разработан язык Java и создана и написана виртуальная машина 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)
Проверьте Глава 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.
Загрузите и извлеките исходный 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). Однако мне бы хотелось узнать о обоснование для проектного решения о том, чтобы сделать статический метод точкой входа, а не конструктором или методом экземпляра.
@KonradRudolph, по вопросам, касающимся языка и дизайна спецификации JVM, возможно, вы могли бы попробовать связаться с исходным кодом от Oracle и посмотреть, сможете ли вы получить какие-либо положительные отзывы.
Вообще говоря, когда вычисление результата метода зависит только от его параметров, поэтому оно не зависит от внутреннего состояния экземпляра объекта, оно может быть статическим. И рекомендуется установить его как статический для удобства сопровождения / повторного использования кода. Если метод main не был статическим, это означает, что состояние экземпляра класса должно быть известно, и его гораздо сложнее определить, например, какой конструктор использовать первым.
@KonradRudolph Интересно, что Oak (предшественник Java) уже требовал, чтобы у основного метода был аналогичный прототип: public static void main(String arguments[]) - Ссылка: Дуб 0.2 Spec.
@Yves Это может быть. В этом нет необходимости, если другой дизайн имеет смысл. Я слышал здесь несколько хороших аргументов в комментариях, но я все еще думаю, что процесс очень похож на поток (это является), а поток в Java обычно представлен как экземпляр Runnable. Представление всего процесса одним и тем же способом (т.е. имея Runnable.Run в качестве точки входа) определенно имеет смысл в Java. Конечно, сам Runnable, возможно, является недостатком дизайна, вызванным тем фактом, что в Java нет анонимных методов (пока). Но раз уж он там ...
Из 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.
Я всегда понимал, что основной метод, как и любой статический метод, может быть вызван без создания экземпляра связанного класса, что позволяет ему запускаться раньше всего в программе. Если бы он не был статическим, вам пришлось бы создать экземпляр объекта перед его вызовом, что создает проблему «курица и яйцо», поскольку основной метод обычно используется для создания экземпляров объектов в начале программы.
Но нет запускается «раньше всего в программе». Весь этот аргумент - заблуждение, и, более того, это не первый ответ, упоминающий об этом, и даже не второй или третий.
Мне жаль, что мой ответ повторяет то, что сказали другие; Я ответил только в меру моего понимания и из того, что я смог найти в Интернете. Судя по результатам, которые я просмотрел, нет другой причины, почему основной метод статичен; если где-то глубоко не спрятано одно, возможно, это единственный ответ. Мое понимание Java довольно базовое, но я слышал вышеупомянутую причину (от профессоров, из учебников и т. д.) И никогда не слышал ничего другого.
@Jesse M Ваш комментарий имеет смысл только в том случае, если вы даже не думали сначала прочитать другие ответы. Что, кстати, не надумано. Как вы сами упомянули, ваше понимание довольно базовое, поэтому весьма вероятно, что кто-то уже ответил на вопрос более компетентно. И ваш комментарий кажется рационализацией, чтобы ваш ответ выглядел лучше. Поразительно, что у вас есть учебники по Java и профессора, которые думают так, как вы, и, честно говоря, я не верю, что они думают. (Есть ссылки?)
@KonradRudolph Верхние комментарии кажутся вполне разумными. main () используется как точка входа в программу, и на веб-сайте Java есть несколько ссылок, в которых говорится, что он должен быть похож на то, как в C / C++ есть функция main (). Поскольку Java - это все объекты, он должен быть статическим, чтобы избежать создания экземпляров объекта. Статический статус также позволяет загружать его и выполнять в JVM во время выполнения. Я просто извергаю предыдущие ответы, но мне интересно, какой ответ вы бы сочли удовлетворительным. Я думаю, лучшее, что вы получите, это «Вот как они этого хотели». Помните дату создания Java.
@Atlos Ваши причины на самом деле не являются объяснением: вы говорите, что «он должен быть статическим, чтобы избежать создания экземпляра объекта», но почему вы вообще хотите избежать создания экземпляра объекта? Этот - вот настоящий вопрос.
@KonradRudolph Избежать создания экземпляров объекта сегодня не составляет особой проблемы, но когда вышла Java, я увидел, что это проблема памяти и скорости. Изначально Java была предназначена для потребительской цифровой электроники в начале 90-х, и я мог представить себе ограничения, с которыми им пришлось столкнуться. Именно на этом рынке Java конкурировала с C / C++. Я просто соединяю обе идеи вместе, так что никаких «веских доказательств», как вы хотите, но я думаю, что это имеет наибольший смысл. Лучше всего написать в Sun Microsystems по электронной почте и спросить инженера-проектировщика.
@ Атлос, я на это не куплюсь. Это один раз, это занимает меньше микросекунды. Даже когда вышла Java. Вероятно, это даже невозможно измерить.
@LeoR Я признаю, что был виноват, не прочитав сначала все остальные ответы; Я не знал, в какой степени повторялся мой ответ. Причина, по которой я чувствовал себя достаточно уверенно, чтобы ответить на вопрос, заключалась в том, что мне никогда раньше не приходилось «глубоко» думать об этой проблеме; Когда я сказал, что слышал заявление профессоров, я передал тот факт, что это было просто тем, чему меня учили. Я не могу процитировать, когда и где именно я узнал об этом, по той же причине, по которой я не могу сказать вам, когда узнал о циклах for; Я всегда принимал рассуждения как должное.
Я также не понимаю, почему это такое экстраординарное заявление. Вы сами сказали, что все остальные ответы были такими же, как у меня; Так почему же неразумно, что это широко распространенное мнение, которому многие люди научились или чему их научили? У меня нет причин лгать о том, что я узнал, если только я не так отчаянно нуждался в щедрости Конрада - которую я знал, что не получу, поскольку многие ответы были длиннее и сложнее, чем мои. Это вызывает основную причину, по которой я вообще ответил на вопрос:
@KonradRudolph Возможно ли, что ответа, который вы ищете, просто не существует? Да, создание экземпляра объекта занимает очень мало времени, но означает ли это, что есть смысл заставлять программистов делать это, когда в этом нет необходимости? Почему рассуждение не может быть таким же, как и с любым другим статическим методом? Насколько мне известно, вы можете достичь тех же целей, не используя статические методы, как используя их в любой программе. Но когда метод логически не связан с определенным классом, есть возможность не связывать его с классом.
Я не понимаю, почему это не может быть просто вопросом соглашения, удобочитаемости и выбора со стороны программиста. Если этого недостаточно, то, возможно, вам следует связаться с Sun, как рекомендовано Атлосом.
@ Джесси Спот-он. Вполне возможно, что это всего лишь вопрос условности (хотя я надеюсь, что это не так, это был бы такой скучный ответ). Мой первоначальный интерес к этому вопросу был вызван тем, что я думал, что использование подходящего экземпляра для представления объекта «запущенное приложение» и использование точки входа в качестве метода (или конструктора) этого класса было бы гораздо более очевидным решением, поскольку Java был разработан как объектно-ориентированный с самого начала, и поскольку аналогичные объекты (потоки, через Runnable) в Java, делать используют этот дизайн. Почему здесь (очевидное) исключение?
Прототип 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.
метод инициализации класса или интерфейса определяется:
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-режиме конструктор должен только следить за тем, чтобы экземпляр был инициализирован должным образом. После инициализации экземпляр можно использовать для предполагаемой «службы». Помещение полного кода приложения в конструктор испортит это.
Таким образом, этот подход заставит приложение три заключать разные контракты:
main1. Хорошо, это не удивительно.abstract. В противном случае JVM не сможет его создать.С другой стороны, подход static требует только контракта один:
main1.Здесь не имеет значения ни abstract, ни несколько конструкторов.
Поскольку Java была разработана как простой язык для пользователя, неудивительно, что точка входа в приложение также была спроектирована простым способом с использованием контракта один, а не сложным способом с использованием независимых и хрупких контрактов три.
Обратите внимание: это аргумент нет о простоте внутри JVM или внутри JRE. Этот аргумент касается простоты Пользователь.
На самом деле требования более сложные: должен быть метод main, который является public, static и имеет подпись void main(String[]). Я согласен с тем, что, если бы метод был методом экземпляра, JRE имел бы немного больше работы, но Добрый работы был бы таким же, а сложность не намного выше (см. Обсуждения в комментариях к предыдущему ответу). Я не верю, что это различие объясняет решение сделать точку входа статической, в частности, поскольку требуемые методы для разрешения метода экземпляра существуют и легко могут быть использованы.
@KonradRudolph: Моя точка зрения не связана с работой, которую должна будет выполнить JRE. Моя точка зрения заключается в том, чтобы заставить каждый пользователь языка выполнять больше контрактов по мере необходимости. В этом смысле метод static public main(String[]) - это подпись один и, следовательно, контракт один. В противном случае должны выполняться три контракта независимый.
Ах. Я все еще не согласен с тем, что это имеет значение. Классы точек входа вполне могут реализовать Runnable. Ясно, что Java ожидает, что разработчики будут все время следовать этому контракту, почему это должно быть слишком много для точки входа в приложение? Это бессмысленно.
@KonradRudolph: Потому что экземпляр Runnable создается пользователем, а не системой. Следовательно, для Runnable контракты №1 и №3 не требуются.
@KonradRudolph Даже если степень сложности невелика, метод экземпляра более сложен. В этом случае сложность - разумное оправдание для выбора static.
@ A.H. Теперь вы сами себе противоречите, я думал, вы возражали против того, что Пользователь, а не система, должна работать против фиксированных контрактов. Как бы то ни было, требования в обоих случаях одинаковы как для системы, так и для пользователя: пользователь должен соблюдать контракты, система должна обеспечивать их выполнение.
@KonradRudolph: Нет противоречия: в одном случае система заставила бы пользователя заключить три контракта. Сомнительные контракты, которые нельзя проверить через компилятор и которые, с точки зрения пользователя, независимы. В обычном случае Thread и Runnable от пользователя ничего не скрывается, он может четко видеть, что происходит, и у него есть возможность реализовать Только тех контрактов, которые ему подходят - все контролирует он, а не система.
@ A.H. Теперь я понимаю, о чем вы говорите. Мне нужно подумать, убедит ли это меня.
Это лучший ответ здесь. Жаль, что многие пользователи прочитают только 2 или 3 первых ответа на странице; а этот вряд ли скоро туда попадет. В нем упоминается важный момент, когда конструктор предназначен ТОЛЬКО для инициализации - и поэтому нет смысла кодировать в стиле, в котором конструктор запускает все приложение.
Недавно аналогичный вопрос был задан на сайте Programmers.SE
Looking for a definitive answer from a primary or secondary source for why did (notably) Java and C# decide to have a static method as their entry point – rather than representing an application instance by an instance of an
Applicationclass, with the entry point being an appropriate constructor?
TL; DR часть принятого ответа:
In Java, the reason of
public static void main(String[] args)is that
- Gosling wanted
- the code written by someone experienced in C (not in Java)
- to be executed by someone used to running PostScript on NeWS
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[])?
public - это спецификатор доступа, означающий, что любой может получить к нему доступ / вызвать его, например JVM (виртуальная машина Java.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 для пользовательских методов, чтобы нам не нужно было создавать объекты.
void указывает, что объявляемый метод main()
не возвращает значение.
String[] args определяет единственный параметр в методе main().
args - параметр, содержащий массив объектов типа String.
Любой метод, объявленный в Java как статический, принадлежит самому классу.
Опять же, к статическому методу определенного класса можно получить доступ, только обратившись к классу, например Class_name.method_name();.
Таким образом, нет необходимости создавать экземпляр класса перед доступом к статическому методу.
Таким образом, метод main () объявлен как static, поэтому к нему можно получить доступ без создания объекта этого класса.
Поскольку мы сохраняем программу с именем класса, в котором присутствует основной метод (или откуда программа должна начинать свое выполнение, применимо для классов без метода main() () (продвинутый уровень)). Итак, указанным выше способом:
Class_name.method_name();
можно получить доступ к основному методу.
Вкратце, когда программа компилируется, она ищет метод main(), имеющий аргументы String, такие как: main(String args[]) в упомянутом классе (то есть по имени программы), и поскольку вначале у него нет области для создания экземпляра этого класса, поэтому Метод main () объявлен как статический.
Это случается, когда программа выполняется, а не компилируется.
Позвольте мне объяснить эти вещи гораздо проще:
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
mainas staticallowsthe JVM toinvokemainwithoutcreating aninstanceof 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
в этом случае мы не должны говорить подпись метода, потому что термин относится только к именам методов и их параметрам.