Підпис методу Java main () методу:
public static void main(String[] args){
...
}
Чи є причина цього методу статичним?
Підпис методу Java main () методу:
public static void main(String[] args){
...
}
Чи є причина цього методу статичним?
Відповіді:
Метод є статичним, оскільки в іншому випадку виникає неоднозначність: якого конструктора слід викликати? Особливо, якщо ваш клас виглядає так:
public class JavaClass{
protected JavaClass(int x){}
public void main(String[] args){
}
}
Чи повинен дзвонити JVM new JavaClass(int)
? Що має пройти x
?
Якщо ні, то чи слід JavaClass
створювати JVM без використання будь-якого конструкторського методу? Я думаю, що це не повинно, тому що це буде мати особливий випадок для всього вашого класу - іноді у вас є екземпляр, який не був ініціалізований, і вам доведеться перевірити це у кожному методі, який можна було б викликати.
Для цього є занадто багато крайніх випадків і неоднозначностей, щоб мати сенс для JVM, щоб створити екземпляр класу до виклику точки входу. Ось чому main
статична.
Я поняття не маю, чому main
завжди позначений public
.
public static void main
служить маркером точки входу - громадський конструктор без параметрів не кричить "Це, мабуть, точка входу!" таким же чином.
main
потрібно закликати. Як не дивно (для вас), 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 () замість рядкового масиву).
Отже, довге і коротке: причина статичної - це зручність, що зручно. Причина, яку називають "головною", полягає в тому, що це повинно було бути щось, а головне () - це те, що вони робили за старих часів С (а в ті часи назва функції була важливою). Я припускаю, що java.exe міг би дозволити вам просто вказати повністю кваліфіковане основне ім’я методу, а не просто клас (java com.mycompany.Foo.someSpecialMain) - але це просто ускладнює IDE автоматичним виявленням ' старти 'класів у проекті.
java.exe
)
static
що main()
декларація - це лише заради конвенції. Однак те, що це "main ()", а не щось інше, можливо.
main
нестатичним і все ще вписуватися в межі мови. Не чуючи дизайнерів, нам просто доведеться погодитися не погодитися. :)
main()
Метод C++
, C#
і Java
є статичним
Оскільки вони потім можуть бути викликані з допомогою середовища виконання двигуна без необхідності створення екземпляра які - або об'єктів , то код в тілі main()
буде робити все інше.
public static void main...
, чому не може бути умовою, що клас точки введення додатка повинен мати публічний конструктор за замовчуванням?
static void main
дзвінками? Зовсім не проблема.
static
такі методи, як main
часто використовують new
для створення такого об’єкта.
Ось так створена мова Java і створена та написана віртуальна машина Java.
Перевірте Розділ 12 Виконання - Розділ 12.1.4 Викликати тест. Головна :
Нарешті, після завершення ініціалізації для класу Test (під час якого можуть відбуватися інші послідовні завантаження, зв'язування та ініціалізація), викликається головний метод Test.
Метод основний повинен бути оголошений загальнодоступним, статичним та недійсним. Він повинен прийняти єдиний аргумент, який є масивом рядків. Цей метод можна оголосити як будь-яким
public static void main(String[] args)
або
public static void main(String... args)
Перевірте Розділ 2 Концепції мови програмування Java - Розділ 2.17 Виконання :
Віртуальна машина Java запускає виконання шляхом виклику методу main деякого визначеного класу та передачі йому єдиного аргументу, який є масивом рядків. Це призводить до завантаження зазначеного класу (§2.17.2), пов'язаного (§2.17.3) з іншими типами, який він використовує, та ініціалізованого (§2.17.4). Метод основний повинен бути оголошений загальнодоступним, статичним та недійсним.
Завантажте та витягніть джерельну банку і подивіться, як написано 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);
... ...
main
не був статичним, це означає, що стан екземпляра класу необхідно знати, і визначити, який конструктор використовувати перший, набагато складніше.
public static void main(String arguments[])
- Довідка: Дуб 0,2 Spec .
Runnable
. Представляти весь процес однаковим чином (тобто мати Runnable.Run
вхідну точку), безумовно, має сенс у Java. Звичайно, Runnable
сам по собі є, мабуть, недоліком дизайну, викликаним тим, що у Java немає анонімних методів (поки що). Але оскільки це вже є…
Давайте просто зробимо вигляд, що static
це не потрібно в якості точки введення програми.
Клас програми тоді виглядатиме так:
class MyApplication {
public MyApplication(){
// Some init code here
}
public void main(String[] args){
// real application code here
}
}
Розрізнення коду конструктора та main
методу є необхідним, оскільки в OO говорять, конструктор повинен лише переконатися, що екземпляр ініціалізується належним чином. Після ініціалізації екземпляр може бути використаний для призначеної "послуги". Внесення повного коду програми в конструктор це зіпсує.
Таким чином, такий підхід змушує застосувати три різні договори після заявки:
main
метод 1 . Гаразд, це не дивно.abstract
. В іншому випадку JVM не міг його створити.З static
іншого боку, підхід вимагає лише одного контракту:
main
метод 1 .Тут не має значення abstract
ні багато конструкторів.
Оскільки Java була розроблена для простої мови для користувача , не дивно, що також точка входу програми була розроблена просто, використовуючи один контракт, а не складно, використовуючи три незалежні та крихкі контракти.
Зверніть увагу: Цей аргумент не стосується простоти всередині JVM або всередині JRE. Цей аргумент стосується простоти для користувача .
main
метод , який public
, static
і має підпис void main(String[])
. Я погоджуюсь, що якби метод був методом екземпляра, JRE мала б трохи більше роботи, але вид роботи був би однаковий, а складність не значно більша (див. Дискусії в коментарях попередньої відповіді). Я не вірю, що ця різниця пояснює рішення про те, щоб стати пунктом вступу статичним, зокрема, оскільки необхідні методи для вирішення методу екземпляра існують і вони легко застосовні.
static public main(String[])
метод - це один підпис, а отже, один договір. В іншому випадку потрібно дотримуватися трьох незалежних договорів.
Runnable
. Зрозуміло, Java очікує, що розробники постійно дотримуватимуться цього контракту, чому це повинно бути занадто великим для точки введення програми? Це безглуздя.
Thread
і Runnable
справі нічого не приховано від користувача, він може ясно бачити , що відбувається , і у нього є зміни , щоб реалізувати тільки ті контракти , які підходять йому - він знаходиться під контролем, а не система.
Якщо це не так, який конструктор слід використовувати, якщо їх більше?
Більше інформації про ініціалізацію та виконання програм Java доступно у специфікації мови Java .
Перед тим, як викликати основний метод, жодні об'єкти не інстанціюються. Наявність статичного ключового слова означає, що метод можна викликати, не створюючи спочатку жодних об'єктів.
Тому що в іншому випадку знадобиться екземпляр об'єкта для виконання. Але його потрібно викликати з нуля, не будуючи спочатку об'єкта, оскільки зазвичай це завдання main () функції (bootstrap), щоб проаналізувати аргументи та побудувати об'єкт, як правило, використовуючи ці параметри / параметри програми.
Дозвольте мені пояснити ці речі набагато простіше:
public static void main(String args[])
Усі програми Java, крім аплетів, починають їх виконання з main()
.
Ключове слово public
- це модифікатор доступу, який дозволяє викликати учасника поза класом.
static
використовується тому, що дозволяє main()
викликати без необхідності інстанціювати певний екземпляр цього класу.
void
вказує, що main()
не повертає жодного значення.
У чому сенс public static void main(String args[])
?
public
- це специфікатор доступу, який означає, що кожен може отримати доступ до нього або викликати його, наприклад, JVM (Java Virtual Machine.static
дозволяє main()
викликати до того, як був створений об’єкт класу. Це не обов'язково, оскільки main()
викликається СВМ до того, як будуть зроблені будь-які об'єкти. Оскільки він статичний, його можна безпосередньо викликати через клас.
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 */
}
}
Аналогічно, ми використовуємо статичні колись для визначених користувачем методів, так що нам не потрібно робити об’єкти.
void
вказує, що оголошений main()
метод не повертає значення.
String[] args
вказує єдиний параметр у main()
методі.
args
- параметр, який містить масив об'єктів класового типу String
.
Аплети, міді, серветки та боби різних видів будуються, а потім застосовуються методи життєвого циклу. Invoking main - це все, що коли-небудь робиться для основного класу, тому немає необхідності утримувати стан в об'єкті, який викликається кілька разів. Цілком нормально закріплювати основний на іншому класі (хоча це не чудова ідея), який би перешкоджав використанню класу для створення основного об'єкта.
Це просто умовність, але, мабуть, зручніше, ніж альтернатива. Зі статичним основним, все, що потрібно знати, щоб викликати програму Java, - це ім'я та місцезнаходження класу. Якщо він не був статичним, ви також повинні знати, як інстанціювати цей клас, або вимагати, щоб у класу був порожній конструктор.
Коли ви виконуєте команду віртуальної машини Java (JVM) за допомогою java
команди,
java ClassName argument1 argument2 ...
Під час виконання програми ви вказуєте назву її класу як аргумент команди java, як зазначено вище
JVM намагається викликати основний метод вказаного вами класу
—Від цього моменту, жодних об’єктів класу не було створено.
Оголошення
main
статичнимallows
JVMinvoke
основнимwithout
створеннямinstance
класу.
повернемося до команди
ClassName
- це command-line argument
JVM, який повідомляє, який клас виконувати. Дотримуючись ClassName, ви також можете вказати list of Strings
(розділені пробілами) як аргументи командного рядка, які JVM передасть вашій програмі. -Такі аргументи можуть використовуватися для вказівки параметрів (наприклад, імені файлу) для запуску програми. Ось чому String[] args
в основному є параметр, який називається
Посилання: Java ™ Як програмувати (ранні об’єкти), десяте видання
Нещодавно подібне запитання було розміщено на Programmers.SE
Шукаючи остаточну відповідь від первинного чи вторинного джерела, чому (особливо) Java та C # вирішили використовувати статичний метод в якості точки входу, а не представляти екземпляр програми екземпляром
Application
класу, при цьому точка входу є відповідний конструктор?
TL; DR частина прийнятої відповіді:
Причиною Java
public static void main(String[] args)
є те, що
- Гослінг хотів
- код, написаний людиною, що має досвід C (не на Java)
- виконуватиметься хтось, хто звик працювати з PostScript на NeWS
Для C # міркування транзитивно схожі, так би мовити. Мовні дизайнери зберегли синтаксис точки введення програми, знайомий програмістам, що надходять з Java. Як стверджує архітектор C # Андерс Хейльсберг ,... наш підхід із C # просто запропонував альтернативу ... програмістам Java ...
...
Я думаю, що ключове слово "статичний" робить основний метод методом класу, а методи класів мають лише одну його копію і можуть бути спільними для всіх, а також не потребує об'єкта для посилання. Тож, коли складено клас драйверів, можна використовувати основний метод. (Я просто в алфавіті рівня Java, вибачте, якщо я помиляюся)
main () є статичним, тому що; в цей момент життєвого циклу програми стек додатків має процедурний характер, оскільки немає об'єктів, які ще не знайдені.
Це чистий шифер. Ваша програма працює в цей момент, навіть не оголошуючи жодних об'єктів (пам’ятайте, що існують процедурні та схеми кодування OO). Ви, як розробник, перетворите додаток в об'єктно-орієнтоване рішення, створивши екземпляри своїх об'єктів і залежно від коду, складеного всередині.
Об'єктно-орієнтоване чудово підходить для мільйонів очевидних причин. Однак минули дні, коли більшість розробників VB регулярно використовували в своєму коді такі ключові слова, як "goto". "goto" - це процедурна команда в VB, яка замінюється на його аналог OO: метод виклику.
Ви також можете дивитися на статичну точку входу (головну) як на чисту свободу. Якби Java була достатньо різною, щоб створювати об'єкт і представляти вам лише цей екземпляр під час запуску, у вас не було б вибору АЛЕ написати процедурний додаток. Як би немислимо це не звучало для Java, можливо, існує багато сценаріїв, які вимагають процедурних підходів.
Це, мабуть, дуже незрозуміла відповідь. Пам'ятайте, що "клас" - це лише сукупність взаємопов'язаних кодів. "Екземпляр" - це ізольоване, живе і дихаюче автономне покоління цього класу.
main
буде досягнуто. І якщо ви включите статичний конструктор до класу, що містить main, він виконується і раніше main
.
Прототип public static void main(String[])
- це конвенція, визначена в JLS :
Метод основний повинен бути оголошений загальнодоступним, статичним та недійсним. Він повинен вказати формальний параметр (§ 8.4.1), декларований тип якого є масив String.
У специфікації JVM 5.2. Запуск віртуальної машини ми можемо читати:
Віртуальна машина Java запускається шляхом створення початкового класу, який задається залежним від реалізації способом, використовуючи завантажувач класів завантаження (§5.3.1). Потім віртуальна машина Java пов'язує початковий клас, ініціалізує його та викликає метод void main публічного класу (String []) . Викликання цього методу приводить до подальшого виконання. Виконання інструкцій віртуальної машини Java, що складають основний метод, може спричинити зв'язок (і, отже, створення) додаткових класів та інтерфейсів, а також виклик додаткових методів.
Цікаво, що в специфікації JVM не зазначається, що основний метод повинен бути статичним. Але специфікація також говорить, що віртуальна машина Java виконує 2 кроки раніше:
Ініціалізація класу або інтерфейсу складається з виконання його класу або методу ініціалізації інтерфейсу.
Метод класу або ініціалізації інтерфейсу визначається:
Клас або інтерфейс має максимум один метод ініціалізації класу або інтерфейсу і ініціалізується (§5.5) шляхом виклику цього методу. Метод ініціалізації класу або інтерфейсу має спеціальну назву
<clinit>
, не бере аргументів і недійсний.
І метод ініціалізації класу або інтерфейсу відрізняється від методу ініціалізації екземпляра, визначеного наступним чином:
На рівні віртуальної машини Java кожен конструктор, написаний мовою програмування Java (JLS § 8.8), виступає як метод ініціалізації екземпляра, який має спеціальну назву
<init>
.
Отже, JVM ініціалізує метод ініціалізації класу чи інтерфейсу, а не an метод ініціалізації екземпляра, який насправді є конструктором. Тому їм не потрібно згадувати, що основний метод повинен бути статичним у специфікації JVM, оскільки це мається на увазі через те, що жоден екземпляр не створюється перед викликом основного методу.
public
Ключове слово є модифікатором доступу, який дозволяє програмісту управляти видимістю членів класу. Коли члену класу передує public
, то до нього може бути доступний код за межами класу, в якому він оголошений.
Протилежність public
є private
, що не дозволяє користувачеві використовувати код, визначений поза його класом.
В цьому випадку, main()
повинен бути оголошений як public
, оскільки він повинен бути викликаний кодом поза його класом при запуску програми.
Ключове слово static
дозволяє
main()
викликати без необхідності інстанціювати певний екземпляр класу. Це необхідно, оскільки main()
викликає інтерпретатор Java до того, як будуть зроблені будь-які об'єкти.
Ключове слово void
просто повідомляє компілятору, що 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()
методу.
Підсумовуючи, вказівка a static void main()
створює специфікацію з найменшою складністю, дотримуючись принципу розміщення поведінки у методах . З огляду на те, наскільки просто реалізувати main()
метод, який сам будує екземпляр класу та викликає метод екземпляра, немає реальної переваги вказувати main()
як метод екземпляра.
main
. Ваше обгрунтування main
надто складного для початківців видається неймовірним. Насправді, статичний main
є дуже заплутаним для початківців, я сумніваюся, що конструктор буде більше. Ви кажете, що "конструктор не повинен відповідати за поведінку об'єкта". Це звучить цікаво, але я не впевнений, що згоден. Чому ні? Що це заважає?
статичний - Коли JVM робить виклик до основного методу, для об'єкта, який викликається, немає об'єкта, тому він повинен мати статичний метод, щоб дозволити виклик з класу.
Я не знаю, чи JVM викликає основний метод перед тим, як об'єкти ініціюються ... Але є набагато більш потужна причина, чому метод main () є статичним ... Коли JVM викликає основний метод класу (скажімо , Особа). він викликає його " Person.main () ". Розумієте, JVM викликає його за назвою класу. Ось чому головний () метод повинен бути статичним і загальнодоступним, щоб до нього можна було отримати доступ.
Сподіваюся, це допомогло. Якщо це було так, повідомте мене, коментуючи.
Статичне ключове слово в основному методі використовується тому, що в основному методі немає жодної інстанції. Але об'єкт побудований, а не виклик, в результаті ми використовуємо статичне ключове слово в основному методі. У контексті jvm пам'ять створюється, коли клас завантажується в неї. І всі статичні члени присутні в цій пам'яті. якщо ми зробимо головну статику зараз, вона буде в пам’яті і може бути доступною jvm (class.main (..)), тому ми можемо викликати основний метод з необхідністю навіть створити купу.
Це просто умова, як ми можемо бачити тут:
Метод повинен бути оголошений загальнодоступним та статичним , він не повинен повертати жодного значення, і він повинен приймати масив String як параметр. За замовчуванням перший аргумент необов'язковий - це ім'я класу, до якого слід викликати. Слід використовувати повноцінне ім'я класу. Якщо вказано параметр -jar, перший аргумент, що не відповідає параметру, - це ім'я архіву JAR, що містить файли класів та ресурсів для програми, із класом запуску, вказаним заголовком маніфесту Main-Class.
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description
Публічні статичні недійсні ключові слова означають, що інтерпретатор віртуальної машини Java (JVM) може викликати основний метод програми для запуску програми (public) без створення екземпляра класу (статичного), і програма не повертає дані інтерпретатору Java VM (пустота), коли вона закінчується.
В основному ми робимо ті ЧЛЕНИ ДАНИХ і ФУНКЦІЇ ЧЛЕНА як СТАТИЧНІ, які не виконують жодного завдання, пов'язаного з об'єктом. І у випадку головного методу ми робимо це як СТАТИЧНИЙ, оскільки це не має нічого спільного з об'єктом, оскільки основний метод завжди працює, створюємо ми об’єкт чи ні.
Будь-який метод, оголошений статичним в Java, належить до самого класу. Знову статичний метод певного класу можна отримати, лише звернувшись до класу типуClass_name.method_name();
Таким чином, клас не повинен бути екземпляром, перш ніж отримати доступ до статичного методу.
Отже, метод main () оголошується static
таким, що до нього можна отримати доступ, не створюючи об'єкт цього класу.
Оскільки ми зберігаємо програму з назвою класу, де присутній основний метод (або з того, звідки програма повинна розпочати його виконання, застосовна для класів без main()
методу () (Розширений рівень)). Отже, вищезгаданим способом:
Class_name.method_name();
До головного методу можна отримати доступ.
Якщо коротко, коли програма складається, вона шукає main()
метод, що має String
такі аргументи: main(String args[])
у згаданому класі (тобто за назвою програми), і оскільки на початку у нього немає можливості інстанціювати цей клас, тому main () метод оголошено статичним.
Від java.sun.com (на сайті є додаткова інформація):
Основний метод - статичний, щоб дати інтерпретатору Java VM спосіб запустити клас, не створюючи спочатку екземпляр класу управління. Екземпляри класу управління створюються в основному методі після запуску програми.
Моє розуміння завжди полягало в тому, що основний метод, як і будь-який статичний метод, можна викликати без створення примірника асоційованого класу, що дозволяє йому запускатись перед будь-чим іншим у програмі. Якби це не було статичним, вам доведеться інстанціювати об'єкт перед тим, як викликати його - що створює проблему "курка та яйце", оскільки головний метод, як правило, те, що ви використовуєте для інстанцізації об'єктів на початку програми.
Runnable
) в Java справді використовують цей дизайн. Чому тут (очевидний) виняток?