เมธอดลายเซ็นต์ของเมธอด 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
ไง?
ถ้าไม่ใช่ JVM ควรสร้างอินสแตนซ์JavaClass
โดยไม่เรียกใช้เมธอด Constructor ใด ๆ ? ฉันคิดว่ามันไม่ควรเพราะมันจะเป็นกรณีพิเศษสำหรับทั้งชั้นเรียนของคุณ - บางครั้งคุณมีอินสแตนซ์ที่ยังไม่ได้รับการเริ่มต้นและคุณต้องตรวจสอบในทุกวิธีที่สามารถเรียกได้
มีกรณีขอบและความคลุมเครือจำนวนมากเกินไปที่จะทำให้เหมาะสมสำหรับ 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 ที่ง่ายมากที่แยกวิเคราะห์บรรทัดคำสั่งสร้างอาร์เรย์สตริงใหม่ใน JVM เพื่อเก็บอาร์กิวเมนต์เหล่านั้นแยกวิเคราะห์ชื่อคลาสที่คุณระบุว่ามี main () ใช้การเรียก JNI เพื่อค้นหา main () วิธีการของตัวเองจากนั้นจะเรียกวิธีการหลัก () ผ่านในอาร์เรย์สตริงที่สร้างขึ้นใหม่เป็นพารามิเตอร์ นี่เป็นสิ่งที่เหมือนกับสิ่งที่คุณทำเมื่อคุณใช้การสะท้อนจาก Java - เพียงแค่ใช้การเรียกฟังก์ชันเนทีฟแบบสับสนแทน
มันจะถูกกฎหมายอย่างสมบูรณ์แบบสำหรับคุณที่จะเขียน java.exe เวอร์ชันของคุณเอง (ซอร์สถูกแจกจ่ายด้วย JDK) และให้มันทำสิ่งที่แตกต่างอย่างสิ้นเชิง อันที่จริงแล้วนั่นคือสิ่งที่เราทำกับแอพ Java-based ทั้งหมดของเรา
แอป Java ของเราแต่ละตัวมีตัวเรียกใช้งานของตัวเอง เราทำสิ่งนี้เป็นหลักเพื่อให้เราได้รับไอคอนและชื่อกระบวนการของเราเอง แต่มันมีประโยชน์ในสถานการณ์อื่น ๆ ที่เราต้องการทำอะไรนอกเหนือจากการเรียก main () ปกติเพื่อให้สิ่งต่าง ๆ เกิดขึ้น (ตัวอย่างเช่นในกรณีที่เรากำลังทำอยู่ ความสามารถในการทำงานร่วมกันของ COM และเราผ่านการจัดการ COM ไปยัง main () แทน array string)
ดังนั้นยาวและสั้น: เหตุผลที่เป็นสถิตคือ b / c ที่สะดวก เหตุผลที่เรียกว่า 'main' ก็คือมันต้องเป็นอะไรซักอย่างและ main () คือสิ่งที่พวกเขาทำในสมัยก่อนของ C (และในสมัยนั้นชื่อของฟังก์ชั่นมีความสำคัญ) ฉันคิดว่า java.exe อาจอนุญาตให้คุณระบุชื่อเมธอดหลักที่ผ่านการรับรองอย่างสมบูรณ์แทนที่จะเป็นคลาส (java com.mycompany.Foo.someSpecialMain) - แต่นั่นทำให้ IDEs ตรวจจับอัตโนมัติ ' เปิดตัวคลาส 'ในโครงการ
java.exe
)
static
ในการmain()
ประกาศเป็นเพียงเพื่อประโยชน์ของการประชุม ความจริงที่ว่ามันเป็น `main () 'และไม่ใช่สิ่งอื่นที่เป็นไปได้อย่างไรก็ตาม
main
ไม่คงที่และยังคงพอดีภายในขอบเขตของภาษา หากไม่ได้ยินจากนักออกแบบเราจะต้องเห็นด้วยไม่เห็นด้วย :)
main()
วิธีการในC++
, C#
และJava
จะคงที่
เพราะพวกเขานั้นจะสามารถเรียกโดยเครื่องยนต์รันไทม์โดยไม่ต้องยกตัวอย่างวัตถุใด ๆ แล้วรหัสในร่างกายของmain()
จะไม่เหลือ
public static void main...
จะไม่สามารถใช้การประชุมได้เนื่องจากคลาสการเข้าใช้แอปพลิเคชันควรมีตัวสร้างค่าเริ่มต้นสาธารณะ
static void main
โทรศัพท์ใดที่มีการโทรมากเกินไป? ไม่มีปัญหาเลย
static
วิธีการต่าง ๆ เช่นmain
ใช้บ่อยnew
ในการสร้างวัตถุดังกล่าว
นี่คือวิธีการออกแบบภาษา Java และ Java Virtual Machine ได้รับการออกแบบและเขียน
ลองดูบทที่ 12 การดำเนินการ - ส่วนที่ 12.1.4 เรียกใช้ Test.main :
ในที่สุดหลังจากเสร็จสิ้นการเริ่มต้นสำหรับการทดสอบในชั้นเรียน (ในระหว่างที่การโหลดการเชื่อมโยงและการเริ่มต้นอื่นอาจเกิดขึ้น) วิธีการหลักของการทดสอบจะถูกเรียกใช้
วิธีการหลักจะต้องประกาศสาธารณะคงที่และเป็นโมฆะ จะต้องยอมรับอาร์กิวเมนต์เดียวที่เป็นอาร์เรย์ของสตริง วิธีนี้สามารถประกาศเป็นอย่างใดอย่างหนึ่ง
public static void main(String[] args)
หรือ
public static void main(String... args)
ลองดูบทที่ 2 แนวคิดภาษาการเขียนโปรแกรม Java - ส่วนที่ 2.17 การดำเนินการ :
เครื่องเสมือน Java เริ่มต้นการดำเนินการโดยเรียกใช้เมธอด main ของคลาสที่ระบุและส่งผ่านอาร์กิวเมนต์ตัวเดียวซึ่งเป็นอาร์เรย์ของสตริง สิ่งนี้ทำให้คลาสที่ระบุถูกโหลด (§2.17.2), linked (§2.17.3) กับประเภทอื่นที่ใช้และเริ่มต้น ((2.17.4) วิธีการหลักจะต้องประกาศสาธารณะคงที่และเป็นโมฆะ
ดาวน์โหลดและแตกซอร์ส jar และดูวิธีเขียน JVM เช็กเอา../launcher/java.c
ต์ซึ่งมีคำสั่ง Native code behind 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
ไม่คงที่ก็หมายความว่าจะต้องรู้สถานะของอินสแตนซ์ของคลาสและมีความซับซ้อนในการกำหนดเช่นเดียวกับตัวสร้างที่จะใช้ก่อน
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 1ตกลงนี้ไม่น่าแปลกใจabstract
เป็น มิฉะนั้น JVM ไม่สามารถสร้างอินสแตนซ์ได้static
วิธีการในมืออื่น ๆ เพียง แต่ต้องใช้อย่างใดอย่างหนึ่งสัญญา:
main
วิธีการ 1ที่นี่ทั้งสองabstract
หรือไม่ก่อสร้างหลายเรื่อง
ตั้งแต่จาวาถูกออกแบบมาให้เป็นภาษาที่เรียบง่ายสำหรับผู้ใช้จึงไม่น่าแปลกใจที่จุดเข้าใช้งานของแอปพลิเคชันได้รับการออกแบบในวิธีที่ง่ายโดยใช้สัญญาเดียวและไม่ได้ใช้อย่างซับซ้อนสามสัญญาอิสระและเปราะ
โปรดทราบ: อาร์กิวเมนต์นี้ไม่ได้เกี่ยวกับความเรียบง่ายภายใน 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()
ถูกเรียกใช้โดย 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 */
}
}
ในทำนองเดียวกันเราใช้สแตติกบางครั้งสำหรับวิธีการที่ผู้ใช้กำหนดดังนั้นเราไม่จำเป็นต้องสร้างวัตถุ
void
บ่งชี้ว่าmain()
วิธีการประกาศไม่คืนค่า
String[] args
ระบุพารามิเตอร์เท่านั้นในmain()
วิธีการ
args
- String
พารามิเตอร์ที่มีอาร์เรย์ของวัตถุชนิดระดับเกรด
Applets, midlets, servlets และ beans หลายชนิดถูกสร้างขึ้นและมีเมธอดวงจรชีวิตที่เรียกใช้ การเรียกใช้ main คือสิ่งที่เคยทำกับคลาสหลักดังนั้นจึงไม่จำเป็นต้องมีสถานะที่จะถูกเก็บไว้ในวัตถุที่เรียกว่าหลายครั้ง เป็นเรื่องปกติที่จะปักหมุดบนชั้นอื่น (แม้ว่าจะไม่ใช่ความคิดที่ดี) ซึ่งจะเป็นการใช้ชั้นเรียนเพื่อสร้างวัตถุหลัก
มันเป็นเพียงแค่การประชุม แต่อาจจะสะดวกกว่าทางเลือกอื่น ด้วยหลักคงที่สิ่งที่คุณต้องรู้เพื่อเรียกใช้โปรแกรม Java คือชื่อและที่ตั้งของชั้นเรียน ถ้ามันไม่คงที่คุณต้องรู้วิธีสร้างอินสแตนซ์ของคลาสนั้นหรือต้องการให้คลาสนั้นมี Constructor ว่างเปล่า
หากวิธีการหลักจะไม่คงที่คุณจะต้องสร้างวัตถุของคลาสหลักของคุณจากนอกโปรแกรม คุณต้องการทำอย่างไร
เมื่อคุณรัน Java Virtual Machine (JVM) ด้วยjava
คำสั่ง
java ClassName argument1 argument2 ...
เมื่อคุณเรียกใช้แอปพลิเคชันของคุณคุณจะต้องระบุชื่อคลาสเป็นอาร์กิวเมนต์สำหรับคำสั่ง java ดังกล่าวข้างต้น
JVM พยายามเรียกใช้เมธอดหลักของคลาสที่คุณระบุ
- ณ จุดนี้ไม่มีการสร้างวัตถุของชั้นเรียน
ประกาศ
main
เป็นallows
JVM แบบสแตติกเพื่อสร้างinvoke
main ของคลาสwithout
instance
กลับไปที่คำสั่ง
ClassName
คือcommand-line argument
การ JVM ที่บอกคลาสที่จะดำเนินการ หลังจาก ClassName คุณสามารถระบุlist of Strings
(คั่นด้วยช่องว่าง) เป็นอาร์กิวเมนต์บรรทัดคำสั่งที่ JVM จะส่งผ่านไปยังแอ็พพลิเคชันของคุณ - อาร์กิวเมนต์ดังกล่าวอาจถูกใช้เพื่อระบุตัวเลือก (เช่นชื่อไฟล์) เพื่อเรียกใช้แอปพลิเคชัน - นี่คือสาเหตุที่มีพารามิเตอร์ที่เรียกว่าString[] args
ใน main
ข้อมูลอ้างอิง: Java ™วิธีการโปรแกรม (Early Objects), Tenth Edition
เมื่อเร็ว ๆ นี้มีการโพสต์คำถามที่คล้ายกันที่ Programmers.SE
กำลังมองหาคำตอบที่ชัดเจนจากแหล่งที่มาหลักหรือรองว่าทำไม (และสะดุดตา) Java และ C # ตัดสินใจที่จะมีวิธีการคงที่เป็นจุดเริ่มต้นของพวกเขา - แทนที่จะเป็นตัวแทนอินสแตนซ์ของแอปพลิเคชันโดยอินสแตนซ์ของ
Application
คลาส คอนสตรัคที่เหมาะสม?
TL; DRส่วนหนึ่งของคำตอบที่ยอมรับคือ
ใน Java เหตุผล
public static void main(String[] args)
ก็คือ
- ลูกห่านที่ต้องการ
- รหัสที่เขียนโดยคนที่มีประสบการณ์ใน C (ไม่ใช่ใน Java)
- จะถูกประหารโดยใครบางคนที่เคยใช้งานPostScriptบนNeWS
สำหรับ C # เหตุผลคล้ายคลึงกันในลักษณะทรานซิทจึงจะพูด นักออกแบบภาษาใช้ไวยากรณ์จุดเข้าใช้งานโปรแกรมที่คุ้นเคยสำหรับโปรแกรมเมอร์ที่มาจาก Java ในฐานะที่เป็น C # สถาปนิกAnders Hejlsberg ทำให้มัน ,... แนวทางของเรากับ C # เป็นเพียงการนำเสนอทางเลือก ... แก่โปรแกรมเมอร์ Java ...
...
ฉันคิดว่าคำหลัก 'คงที่' ทำให้วิธีการหลักเป็นวิธีการเรียนและวิธีการเรียนมีเพียงหนึ่งสำเนาของมันและสามารถใช้ร่วมกันโดยทั้งหมดและยังไม่จำเป็นต้องมีวัตถุสำหรับการอ้างอิง ดังนั้นเมื่อมีการคอมไพล์คลาสไดรเวอร์เมธอดหลักสามารถเรียกใช้ได้ (ฉันแค่อยู่ในระดับตัวอักษรของจาวาขอโทษถ้าฉันผิด)
main () เป็นแบบคงที่เพราะ; ณ จุดนั้นในวงจรชีวิตของแอปพลิเคชันสแต็กของแอปพลิเคชันเป็นขั้นตอนตามธรรมชาติเนื่องจากยังไม่มีวัตถุที่อินสแตนซ์
มันเป็นกระดานชนวนที่สะอาด แอปพลิเคชันของคุณกำลังทำงานที่จุดนี้แม้ว่าจะไม่มีการประกาศวัตถุใด ๆ ก็ตาม (โปรดจำไว้ว่ามีรูปแบบการเข้ารหัสและขั้นตอนการ OO) คุณในฐานะนักพัฒนาเปลี่ยนแอปพลิเคชันให้เป็นโซลูชันเชิงวัตถุโดยการสร้างอินสแตนซ์ของวัตถุของคุณและขึ้นอยู่กับโค้ดที่รวบรวมภายใน
การวางวัตถุนั้นยอดเยี่ยมด้วยเหตุผลหลายล้านอย่างที่ชัดเจน อย่างไรก็ตามไปแล้วเป็นวันที่นักพัฒนา VB ส่วนใหญ่ใช้คำหลักเช่น "goto" ในรหัสของพวกเขาเป็นประจำ "goto" เป็นคำสั่งขั้นตอนใน VB ที่ถูกแทนที่ด้วย OO คู่กัน: การเรียกใช้เมธอด
นอกจากนี้คุณยังสามารถดูที่จุดเข้าใช้งานแบบคงที่ (หลัก) ว่าเป็นอิสระอย่างแท้จริง หาก Java แตกต่างกันพอที่จะยกตัวอย่างวัตถุและแสดงเฉพาะอินสแตนซ์นั้นให้คุณทำงานคุณจะไม่มีทางเลือก แต่จะเขียนแอปตามขั้นตอน เป็นไปไม่ได้ราวกับว่ามันอาจฟังดูสำหรับ Java เป็นไปได้มีหลายสถานการณ์ที่เรียกว่าวิธีการขั้นตอน
นี่อาจเป็นคำตอบที่คลุมเครือมาก โปรดจำไว้ว่า "class" เป็นเพียงชุดของรหัสที่เกี่ยวข้องกัน "อินสแตนซ์" เป็นรุ่นที่แยกตัวอยู่อาศัยและหายใจอิสระในชั้นเรียนนั้น
main
จะถึง และถ้าคุณรวม Constructor แบบคงที่ในคลาสที่มี main สิ่งนั้นจะถูกดำเนินการก่อนหน้าmain
เช่นเดียวกัน
มันเป็นเพียงแค่การประชุม JVM สามารถจัดการกับวิธีการแบบไม่คงที่ได้แน่นอนหากเป็นแบบแผน ท้ายที่สุดคุณสามารถกำหนด initializer คงที่ในชั้นเรียนของคุณและยกตัวอย่างวัตถุ zillion ก่อนที่จะไปยังวิธีการหลัก () ของคุณ
protoype public static void main(String[])
เป็นแบบแผนที่กำหนดไว้ในJLS :
วิธีการหลักจะต้องประกาศสาธารณะคงที่และเป็นโมฆะ มันจะต้องระบุพารามิเตอร์ที่เป็นทางการ (§8.4.1) ซึ่งมีประเภทประกาศเป็นอาร์เรย์ของสตริง
ในข้อกำหนด JVM 5.2 Virtual Machine Start-up ที่เราอ่านได้:
เครื่องเสมือน Java เริ่มต้นขึ้นโดยการสร้างคลาสเริ่มต้นซึ่งระบุไว้ในลักษณะที่ขึ้นอยู่กับการนำไปใช้งานโดยใช้ตัวโหลดคลาส bootstrap (§5.3.1) ชวาเครื่องเสมือนแล้วเชื่อมโยงคลาสเริ่มต้นเริ่มต้นนั้นและเรียกวิธีการระดับโมฆะสาธารณะ main (String []) การเรียกใช้เมธอดนี้ผลักดันการดำเนินการทั้งหมด การเรียกใช้งานคำสั่งเครื่องเสมือน Java ที่ประกอบไปด้วยวิธีการหลักอาจทำให้เกิดการเชื่อมโยง (และการสร้างขึ้น) ของคลาสและอินเตอร์เฟสเพิ่มเติมรวมถึงการเรียกใช้เมธอดเพิ่มเติม
สิ่งที่ตลกในข้อกำหนด JVM ไม่ได้กล่าวถึงว่าวิธีการหลักจะต้องคงที่ แต่สเป็คยังบอกว่าเครื่องเสมือน Java ดำเนินการ 2 ขั้นตอนก่อน:
การเริ่มต้นของคลาสหรืออินเทอร์เฟซประกอบด้วยการดำเนินการวิธีการเริ่มต้นคลาสหรืออินเทอร์เฟซของ
ใน2.9 วิธีพิเศษ :
มีการกำหนดวิธีการกำหนดค่าเริ่มต้นของคลาสหรืออินเตอร์เฟส :
คลาสหรืออินเทอร์เฟซมีอย่างน้อยหนึ่งคลาสหรือวิธีการกำหนดค่าเริ่มต้นของอินเทอร์เฟซและมีการเตรียมใช้งาน (§5.5) โดยเรียกใช้วิธีนั้น วิธีการเตรียมใช้งานของคลาสหรืออินเทอร์เฟซมีชื่อพิเศษ
<clinit>
ไม่มีอาร์กิวเมนต์และเป็นโมฆะ
และวิธีการกำหนดค่าเริ่มต้นของคลาสหรืออินเตอร์เฟสนั้นแตกต่างจากวิธีการกำหนดค่าเริ่มต้นอินสแตนซ์ที่กำหนดดังนี้:
ในระดับของเครื่องเสมือนชวาคอนสตรัคทุกเขียนในการเขียนโปรแกรมภาษา Java (JLS §8.8)
<init>
จะปรากฏขึ้นเป็นวิธีการเริ่มต้นอินสแตนซ์ที่มีชื่อพิเศษ
ดังนั้น JVM เริ่มต้นวิธีการเริ่มต้นคลาสหรืออินเตอร์เฟสและไม่ใช่วิธีการเริ่มต้นอินสแตนซ์ที่เป็นตัวสร้าง ดังนั้นพวกเขาไม่จำเป็นต้องพูดถึงว่าวิธีการหลักจะต้องมีการคงที่ในสเป็ค 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()
วิธีการ
โดยสรุประบุstatic void main()
สร้างสเปคที่มีความซับซ้อนน้อยในขณะที่การยึดมั่นในหลักการของพฤติกรรมการวางลงในวิธีการ เมื่อพิจารณาว่าตรงไปตรงมาคือการใช้main()
เมธอดที่สร้างอินสแตนซ์ของคลาสและเรียกใช้เมธอดอินสแตนซ์ไม่มีประโยชน์จริง ๆ ในการระบุmain()
เป็นวิธีอินสแตนซ์
main
ต้องการอยู่แล้วสำหรับรถตักดินปพลิเคชันที่ไม่ยกของหนักก่อนที่จะเรียก เหตุผลของคุณเกี่ยวกับmain
ความซับซ้อนเกินไปสำหรับผู้เริ่มต้นดูเหมือนไม่น่าเชื่อ ในความเป็นจริงคงmain
เป็นอย่างมากทำให้เกิดความสับสนสำหรับผู้เริ่มต้นผมสงสัยนวกรรมิกจะมีมากขึ้นดังนั้น คุณพูดว่า“ ผู้สร้างไม่ควรรับผิดชอบต่อพฤติกรรมของวัตถุ” ฟังดูน่าสนใจ แต่ฉันไม่แน่ใจว่าฉันเห็นด้วย ทำไมไม่เป็นเช่นนั้น? จะป้องกันสิ่งนี้ได้อย่างไร
คงที่ - เมื่อ JVM ทำให้การเรียกวิธีการหลักไม่มีวัตถุที่มีอยู่สำหรับชั้นเรียนที่ถูกเรียกดังนั้นมันจะต้องมีวิธีการแบบคงที่เพื่อให้สามารถเรียกใช้จากชั้นเรียน
ฉันไม่รู้ว่า JVM เรียกใช้วิธีการหลักก่อนที่วัตถุจะถูกสร้างอินสแตนซ์ ... แต่มีเหตุผลที่ทรงพลังกว่าทำไมเมธอด main () นั้นคงที่ ... เมื่อ JVM เรียกเมธอดหลักของคลาส (พูด คน) มันเรียกใช้โดย " Person.main () " คุณเห็น JVM เรียกใช้โดยชื่อคลาส นั่นคือเหตุผลที่เมธอด main () ควรจะเป็นแบบสแตติกและเป็นแบบสาธารณะเพื่อให้สามารถเข้าถึงได้โดย JVM
หวังว่ามันจะช่วย ถ้าเป็นเช่นนั้นแจ้งให้เราทราบโดยแสดงความคิดเห็น
วิธีการคงที่ไม่ต้องใช้วัตถุใด ๆ มันวิ่งโดยตรงดังนั้นวิ่งหลักโดยตรง
คำสำคัญคงที่ในวิธีการหลักจะใช้เพราะไม่มีการสร้างตัวอย่างที่เกิดขึ้นในวิธีการหลัก แต่วัตถุนั้นถูกสร้างขึ้นแทนที่จะเรียกใช้ดังนั้นเราจึงใช้คำสำคัญคงที่ในวิธีการหลัก ในหน่วยความจำบริบท jvm จะถูกสร้างขึ้นเมื่อโหลดคลาสลงไปและสมาชิกสแตติกทั้งหมดจะอยู่ในหน่วยความจำนั้น หากเราสร้างสแตติกหลักตอนนี้มันจะอยู่ในหน่วยความจำและสามารถเข้าถึงได้โดย jvm (class.main (.. )) ดังนั้นเราสามารถเรียกเมธอดหลักโดยไม่จำเป็นต้องสร้างฮีปได้
มันเป็นเพียงการประชุมที่เราสามารถดูได้ที่นี่:
วิธีการจะต้องประกาศสาธารณะและคงที่จะต้องไม่ส่งกลับค่าใด ๆ และจะต้องยอมรับอาร์เรย์สตริงเป็นพารามิเตอร์ โดยค่าเริ่มต้นอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกแรกคือชื่อของชั้นที่จะเรียก ควรใช้ชื่อคลาสที่ผ่านการรับรองโดยสมบูรณ์ หากระบุอ็อพชัน -jar อาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกแรกคือชื่อของไฟล์เก็บถาวร JAR ที่มีคลาสและไฟล์รีซอร์สสำหรับแอ็พพลิเคชันโดยมีคลาสเริ่มต้นที่ระบุโดยส่วนหัวรายการคลาสหลัก
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html#description
คำหลักโมฆะสาธารณะคงที่หมายถึงล่าม Java virtual machine (JVM) สามารถเรียกวิธีการหลักของโปรแกรมเพื่อเริ่มโปรแกรม (สาธารณะ) โดยไม่ต้องสร้างอินสแตนซ์ของคลาส (คงที่) และโปรแกรมไม่ส่งคืนข้อมูลไปยังล่าม 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
) ในชวาทำใช้การออกแบบนี้ ทำไมข้อยกเว้น (ชัดเจน) ที่นี่?