ทำไมเมธอด Java หลักเป็นแบบคงที่?


505

เมธอดลายเซ็นต์ของเมธอด Java main ()คือ:

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

มีเหตุผลสำหรับวิธีนี้จะคงที่?


1
ในกรณีนี้เราไม่ควรพูดถึงวิธีการที่เป็นลายเซ็นเพราะคำที่อ้างถึงชื่อวิธีการและพารามิเตอร์ของมันเท่านั้น
Andrew Tobilko

Java ได้รับการออกแบบอย่างจงใจเพื่อให้คุ้นเคยกับโปรแกรมเมอร์ C นี่อยู่ใกล้กับการประชุม C
Thorbjørn Ravn Andersen

คำตอบ:


337

วิธีการคงที่เพราะมิฉะนั้นจะมีความกำกวม: คอนสตรัคที่ควรจะเรียกว่า? โดยเฉพาะอย่างยิ่งถ้าชั้นเรียนของคุณมีลักษณะเช่นนี้:

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

JVM ควรเรียกnew JavaClass(int)หรือไม่ มันควรผ่านไปยังxไง?

ถ้าไม่ใช่ JVM ควรสร้างอินสแตนซ์JavaClassโดยไม่เรียกใช้เมธอด Constructor ใด ๆ ? ฉันคิดว่ามันไม่ควรเพราะมันจะเป็นกรณีพิเศษสำหรับทั้งชั้นเรียนของคุณ - บางครั้งคุณมีอินสแตนซ์ที่ยังไม่ได้รับการเริ่มต้นและคุณต้องตรวจสอบในทุกวิธีที่สามารถเรียกได้

มีกรณีขอบและความคลุมเครือจำนวนมากเกินไปที่จะทำให้เหมาะสมสำหรับ JVM ที่จะต้องสร้างอินสแตนซ์ของคลาสก่อนที่จุดเข้าจะถูกเรียก นั่นเป็นเหตุผลที่mainคงที่

ผมมีความคิดว่าทำไมmainมีการทำเครื่องหมายเสมอpublicแม้ว่า


4
การใช้อินเทอร์เฟซไม่ได้แก้ปัญหาการสร้างอินสแตนซ์
Jacob Krall

26
โดยส่วนตัวฉันชอบที่public static void mainทำหน้าที่เป็นเครื่องหมายของจุดเริ่มต้น - คอนสตรัคเตอร์แบบไม่มีพารามิเตอร์สาธารณะไม่ได้กรีดร้องว่า "นี่อาจเป็นจุดเริ่มต้น!" ในทางเดียวกัน.
Jacob Krall

5
@EdwinDalorzo - สิ่งใดบ้างที่จะได้รับจากการบังคับให้คลาสจุดเริ่มต้นให้เป็นอินสแตนซ์? การเรียกใช้เมธอดแบบสแตติกจะทำให้เกิดภาระน้อยที่สุดในคลาส มีอิสระในการสร้างอินสแตนซ์ของตัวเองหากเหมาะสมสำหรับการออกแบบของคุณ
เดวิดฮาร์คเนส

18
“ คอนสตรัคเตอร์ใดที่ควรเรียก?” วิธีการก็คือว่าแม้กระทั่งกลัวปัญหาหรือไม่ "ปัญหา" เดียวกันมีอยู่สำหรับการตัดสินใจที่mainจะโทร JVM จัดการสิ่งนี้ได้ดีพอสมควร (สำหรับคุณ)
Konrad Rudolph

9
วิธีการหลักเป็นสาธารณะเสมอเพราะจะต้องมีการเข้าถึงได้โดยเครื่องยนต์รันไทม์ JVM
gthm

398

นี่เป็นเพียงการประชุม ในความเป็นจริงแม้แต่ชื่อ main () และข้อโต้แย้งที่ส่งผ่านนั้นเป็นแบบแผนล้วนๆ

เมื่อคุณเรียกใช้ java.exe (หรือ javaw.exe บน Windows) สิ่งที่เกิดขึ้นจริงคือการเรียก Java Native Interface (JNI) สองสามอย่าง การเรียกเหล่านี้โหลด DLL ที่เป็น JVM จริง ๆ (ถูกต้อง - java.exe ไม่ใช่ JVM) JNI เป็นเครื่องมือที่เราใช้เมื่อเราต้องเชื่อมโลกของเครื่องเสมือนและโลกของ C, C ++ ฯลฯ ... การย้อนกลับเป็นจริง - มันเป็นไปไม่ได้ (อย่างน้อยความรู้ของฉัน) จะได้รับ JVM ทำงานโดยไม่ใช้ JNI

โดยพื้นฐานแล้ว java.exe เป็นแอปพลิเคชั่น C ที่ง่ายมากที่แยกวิเคราะห์บรรทัดคำสั่งสร้างอาร์เรย์สตริงใหม่ใน 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 ตรวจจับอัตโนมัติ ' เปิดตัวคลาส 'ในโครงการ


66
+1: น่าสนใจมาก (โดยเฉพาะส่วนเกี่ยวกับการเขียนแบบกำหนดเองjava.exe)
Adam Paynter

9
น่าสนใจฉันไม่เห็นด้วยกับ "นี่เป็นเพียงการประชุม" ส่วนหนึ่งของคำตอบ คำถามหลักของ OP คือเหตุผลของการคงที่ในการประกาศ ฉันไม่คิดว่าstaticในการmain()ประกาศเป็นเพียงเพื่อประโยชน์ของการประชุม ความจริงที่ว่ามันเป็น `main () 'และไม่ใช่สิ่งอื่นที่เป็นไปได้อย่างไรก็ตาม
Jared

2
@ David ดังนั้นมันก็ทำเช่นนั้น จริง ๆ แล้วฉันอยากได้คำตอบจากหนึ่งในคนที่เกี่ยวข้อง - แต่นั่นเป็นช็อตที่ไกลมาก คำตอบอื่น ๆ ส่วนใหญ่น่าเสียดายที่เป็นการออกกำลังกายในการให้เหตุผลแบบเฉพาะกิจ สิ่งนี้ให้รายละเอียดที่น่าสนใจมากนอกจากการมีความถ่อมใจที่จะไม่ประดิษฐ์รายละเอียดทางเทคนิคที่ผิดเพื่อให้เหตุผลที่ไม่ใช่สาเหตุทางเทคนิค
Konrad Rudolph

2
@ Jared - พวกเขาอาจต้องการตัวสร้างแบบไม่มีอาร์กิวเมนต์สาธารณะและทำให้mainไม่คงที่และยังคงพอดีภายในขอบเขตของภาษา หากไม่ได้ยินจากนักออกแบบเราจะต้องเห็นด้วยไม่เห็นด้วย :)
David Harkness

4
@BenVoigt คุณเรียก LoadLibrary () เพื่อรับ jvm dll จากนั้นคุณเรียกใช้ getprocaddress ("JNI_CreateJavaVM") จากนั้นคุณเรียกใช้ฟังก์ชันJNI_CreateJavaVM ( docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/ เป็นต้น ) เมื่อโหลด VM คุณใช้การเรียก JNI มาตรฐานเพื่อค้นหาคลาสที่ถูกต้องให้โหลดเมธอดหลักแบบสแตติกและเรียกใช้ มีพื้นที่ไม่มากสำหรับการตีความที่ผิด JNI เป็นวิธีที่คุณโหลด VM อย่างแน่นอน คุณอาจใช้เพื่อเขียนเฉพาะฝั่งไคลเอ็นต์ JNI โดยใช้คีย์เวิร์ดเนทีฟ, javah -jni ฯลฯ ... แต่นั่นเป็นเพียงครึ่งหนึ่งของ JNI
Kevin Day

188

main()วิธีการในC++, C#และJavaจะคงที่
เพราะพวกเขานั้นจะสามารถเรียกโดยเครื่องยนต์รันไทม์โดยไม่ต้องยกตัวอย่างวัตถุใด ๆ แล้วรหัสในร่างกายของmain()จะไม่เหลือ


1
ไม่เป็นไร แต่ runtime ไม่สามารถยกตัวอย่างวัตถุหนึ่งของคลาสได้หรือไม่ แล้วเรียกวิธีการหลัก? ทำไม?
Andrei Rînea

12
JVM จะรู้ได้อย่างไรว่าคอนสตรัคเตอร์ตัวใดที่จะเรียกว่าหากคลาสหลักของคุณมีคอนสตรัคเตอร์มากเกินไป มันจะผ่านพารามิเตอร์อะไร
Jacob Krall

1
@Noah เมื่อคุณพูดว่าระดับผู้ปกครองคุณหมายถึงชั้นเรียนที่มีวิธีการหลักหรือไม่ เพราะถ้าเป็นเช่นนั้นคำว่า "ชั้นผู้ปกครอง" ค่อนข้างสับสนที่นี่และไม่อย่างนั้นมันก็ไม่สมเหตุสมผลสำหรับฉัน นอกจากนี้หากใช้การประชุมเราpublic static void main...จะไม่สามารถใช้การประชุมได้เนื่องจากคลาสการเข้าใช้แอปพลิเคชันควรมีตัวสร้างค่าเริ่มต้นสาธารณะ
Edwin Dalorzo

2
@Jacob JVM จะทราบได้อย่างไรว่าstatic void mainโทรศัพท์ใดที่มีการโทรมากเกินไป? ไม่มีปัญหาเลย
Konrad Rudolph

4
@Namratha: ใช่คุณไม่มีอะไร มันไม่เป็นความจริงเลยที่ "วิธีการแบบคงที่ไม่สามารถอ้างอิงวิธีแบบไม่คงที่" คำสั่งที่ถูกต้องคือ: "ทุกวิธีคงที่จะต้องให้วัตถุเมื่อใช้วิธีการไม่คงที่" และดูstaticวิธีการต่าง ๆ เช่นmainใช้บ่อยnewในการสร้างวัตถุดังกล่าว
Ben Voigt

38

ทำไมโมฆะหลักคงที่สาธารณะ (String [] args)?

นี่คือวิธีการออกแบบภาษา Java และ Java Virtual Machine ได้รับการออกแบบและเขียน

ข้อกำหนดภาษาของ Oracle Java

ลองดูบทที่ 12 การดำเนินการ - ส่วนที่ 12.1.4 เรียกใช้ Test.main :

ในที่สุดหลังจากเสร็จสิ้นการเริ่มต้นสำหรับการทดสอบในชั้นเรียน (ในระหว่างที่การโหลดการเชื่อมโยงและการเริ่มต้นอื่นอาจเกิดขึ้น) วิธีการหลักของการทดสอบจะถูกเรียกใช้

วิธีการหลักจะต้องประกาศสาธารณะคงที่และเป็นโมฆะ จะต้องยอมรับอาร์กิวเมนต์เดียวที่เป็นอาร์เรย์ของสตริง วิธีนี้สามารถประกาศเป็นอย่างใดอย่างหนึ่ง

public static void main(String[] args)

หรือ

public static void main(String... args)

ข้อมูลจำเพาะของ Oracle Java Virtual Machine

ลองดูบทที่ 2 แนวคิดภาษาการเขียนโปรแกรม Java - ส่วนที่ 2.17 การดำเนินการ :

เครื่องเสมือน Java เริ่มต้นการดำเนินการโดยเรียกใช้เมธอด main ของคลาสที่ระบุและส่งผ่านอาร์กิวเมนต์ตัวเดียวซึ่งเป็นอาร์เรย์ของสตริง สิ่งนี้ทำให้คลาสที่ระบุถูกโหลด (§2.17.2), linked (§2.17.3) กับประเภทอื่นที่ใช้และเริ่มต้น ((2.17.4) วิธีการหลักจะต้องประกาศสาธารณะคงที่และเป็นโมฆะ

Oracle OpenJDK Source

ดาวน์โหลดและแตกซอร์ส 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);

... ...

4
ปัญหาที่นี่คือจริง ๆ แล้วนี่เป็นคำตอบที่ดีมากสำหรับคำถามในรูปแบบดั้งเดิมโดยมีการอ้างอิงมากมาย (+1) อย่างไรก็ตามฉันชอบที่จะเรียนรู้เกี่ยวกับเหตุผลในการตัดสินใจออกแบบวิธีการคงที่เป็นจุดเริ่มต้นแทนที่จะเป็นวิธีการสร้างหรือวิธีการเช่น
Konrad Rudolph

1
@KonradRudolph สำหรับคำถามเกี่ยวกับภาษาและการออกแบบข้อกำหนด JVM บางทีคุณอาจลองติดต่อแหล่งต้นฉบับจาก Oracle และดูว่าคุณจะได้รับผลตอบรับเชิงบวกหรือไม่
yorkw

2
โดยทั่วไปเมื่อการคำนวณผลลัพธ์ของเมธอดขึ้นอยู่กับพารามิเตอร์ของมันเท่านั้นดังนั้นจึงไม่ได้ขึ้นอยู่กับสถานะภายในอินสแตนซ์ของวัตถุมันอาจเป็นแบบสแตติก และขอแนะนำให้ตั้งเป็นแบบคงที่สำหรับการบำรุงรักษาโค้ด / การใช้งานซ้ำ หากวิธีการmainไม่คงที่ก็หมายความว่าจะต้องรู้สถานะของอินสแตนซ์ของคลาสและมีความซับซ้อนในการกำหนดเช่นเดียวกับตัวสร้างที่จะใช้ก่อน
Yves Martin

@KonradRudolph น่าสนใจโอ๊ค (บรรพบุรุษของ Java) ที่จำเป็นแล้ววิธีการหลักที่จะมีต้นแบบที่คล้ายกัน: public static void main(String arguments[])- อ้างอิง: โอ๊ค 0.2 Spec
assylias

2
@Yves มันสามารถเป็น ไม่จำเป็นถ้าการออกแบบอื่นเหมาะสม ผมเคยได้ยินข้อโต้แย้งที่ดีบางอย่างในความคิดเห็นที่นี่ แต่ผมก็ยังคิดว่ากระบวนการที่มีประสิทธิภาพมากเช่นด้าย (มันเป็น ) และการตั้งกระทู้ใน Java Runnableมักจะแสดงเป็นตัวอย่างของ การเป็นตัวแทนของกระบวนการทั้งหมดในลักษณะเดียวกัน (เช่นการมีRunnable.Runจุดเข้าใช้งาน) มีความสมเหตุสมผลใน Java แน่นอนว่าRunnableตัวเองเป็นข้อบกพร่องในการออกแบบที่เกิดจากข้อเท็จจริงที่ว่า Java ยังไม่มีวิธีการที่ไม่ระบุชื่อ (ยัง) แต่เนื่องจากมีแล้ว ...
Konrad Rudolph

36

ลองทำเป็นว่าstaticมันไม่จำเป็นสำหรับจุดเข้าใช้งาน

คลาสแอปพลิเคชันจะมีลักษณะดังนี้:

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

ความแตกต่างระหว่างรหัสคอนสตรัคเตอร์และmainวิธีการเป็นสิ่งที่จำเป็นเพราะใน OO พูดคอนสตรัคเตอร์จะต้องทำให้แน่ใจว่าจะมีการเริ่มต้นอินสแตนซ์ได้อย่างถูกต้อง หลังจากการกำหนดค่าเริ่มต้นอินสแตนซ์สามารถใช้สำหรับ "บริการ" ที่ต้องการได้ การใส่รหัสแอปพลิเคชันที่สมบูรณ์ลงในตัวสร้างจะทำให้เสียอย่างนั้น

ดังนั้นวิธีการนี้จะบังคับสัญญาที่แตกต่างกันสามแอปพลิเคชัน:

  • ต้องมีเป็นตัวสร้างเริ่มต้น มิฉะนั้น JVM จะไม่ทราบว่าตัวสร้างที่จะเรียกและพารามิเตอร์ใดควรให้
  • มีต้องเป็นmainวิธีที่1 1ตกลงนี้ไม่น่าแปลกใจ
  • ชั้นจะต้องไม่abstractเป็น มิฉะนั้น JVM ไม่สามารถสร้างอินสแตนซ์ได้

staticวิธีการในมืออื่น ๆ เพียง แต่ต้องใช้อย่างใดอย่างหนึ่งสัญญา:

  • จะต้องมีmainวิธีการ 1

ที่นี่ทั้งสองabstractหรือไม่ก่อสร้างหลายเรื่อง

ตั้งแต่จาวาถูกออกแบบมาให้เป็นภาษาที่เรียบง่ายสำหรับผู้ใช้จึงไม่น่าแปลกใจที่จุดเข้าใช้งานของแอปพลิเคชันได้รับการออกแบบในวิธีที่ง่ายโดยใช้สัญญาเดียวและไม่ได้ใช้อย่างซับซ้อนสามสัญญาอิสระและเปราะ

โปรดทราบ: อาร์กิวเมนต์นี้ไม่ได้เกี่ยวกับความเรียบง่ายภายใน JVM หรือภายใน JRE เรื่องนี้เป็นเรื่องเกี่ยวกับความเรียบง่ายสำหรับผู้ใช้


1 ที่นี่ลายเซ็นที่สมบูรณ์ถือเป็นสัญญาเดียวเท่านั้น


1
อันที่จริงความต้องการที่มีความซับซ้อนมากขึ้น: จะต้องมีmainวิธีการซึ่งเป็นpublic, และมีลายเซ็นstatic void main(String[])ผมเห็นว่าถ้าวิธีการที่มีวิธีการเช่น JRE จะมีเล็กน้อยทำงานมากขึ้น แต่ชนิดของการทำงานจะเหมือนกันและความซับซ้อนไม่สูงอย่างมีนัยสำคัญ (ดูการอภิปรายในความคิดเห็นของคำตอบก่อนหน้า) ฉันไม่เชื่อว่าความแตกต่างนี้เป็นสาเหตุของการตัดสินใจที่จะทำให้จุดเข้าใช้งานคงที่โดยเฉพาะอย่างยิ่งเนื่องจากวิธีการที่จำเป็นสำหรับการแก้ปัญหาของวิธีการอินสแตนซ์ที่มีอยู่และใช้งานได้อย่างง่ายดาย
Konrad Rudolph

3
@ KonradRudolph: ประเด็นของฉันไม่ได้เกี่ยวกับงานที่ JRE จะต้องทำ ประเด็นของฉันคือการบังคับให้ผู้ใช้ภาษาทุกคนปฏิบัติตามสัญญาเพิ่มเติมตามความจำเป็น ในแง่นี้static public main(String[])วิธีการหนึ่งลายเซ็นและด้วยเหตุนี้หนึ่งสัญญา มิฉะนั้นจะต้องปฏิบัติตามสัญญาอิสระสามฉบับ
อา

1
อา. ฉันยังไม่เห็นด้วยที่จะสร้างความแตกต่าง Runnableรายการเรียนจุดเดียวสามารถใช้ เห็นได้ชัดว่า Java คาดหวังว่านักพัฒนาจะปฏิบัติตามสัญญานั้นตลอดเวลาทำไมมันถึงมากเกินไปสำหรับจุดเริ่มต้นแอปพลิเคชัน? ไม่สมเหตุสมผลเลย
Konrad Rudolph

3
@KonradRudolph: ไม่มีข้อขัดแย้ง: ในกรณีหนึ่งระบบจะบังคับให้ผู้ใช้สามสัญญา สัญญาที่น่าสงสัยซึ่งไม่สามารถตรวจสอบได้ผ่านคอมไพเลอร์และเป็นอิสระจากมุมมองของผู้ใช้ ในกรณีปกติThreadและ Runnableไม่มีกรณีใดที่ถูกซ่อนไว้จากผู้ใช้เขาสามารถเห็นได้อย่างชัดเจนว่าเกิดอะไรขึ้นและเขามีการเปลี่ยนแปลงที่จะใช้เฉพาะสัญญาที่เหมาะสมกับเขา - เขาเป็นผู้ควบคุมไม่ใช่ระบบ
อา

2
นี่คือคำตอบที่ดีที่สุดที่นี่ เป็นเรื่องน่าละอายที่ผู้ใช้หลายคนจะอ่านเฉพาะคำตอบ 2 หรือ 3 อันดับแรกในหน้านี้ และอันนี้ก็ไม่น่าจะไปได้ตลอดเวลาเร็ว ๆ นี้ มันกล่าวถึงจุดสำคัญของตัวสร้างเป็นเพียงการเริ่มต้น - และดังนั้นจึงไม่มีเหตุผลที่จะเขียนโค้ดในสไตล์ที่ตัวสร้างใช้แอปพลิเคชันทั้งหมด
Dawood ibn Kareem

14

ถ้าไม่ใช่มันควรใช้นวกรรมิกตัวไหนถ้ามีมากกว่าหนึ่งตัว?

มีข้อมูลเพิ่มเติมเกี่ยวกับการเริ่มต้นและการดำเนินการของโปรแกรม Java ที่มีอยู่ในเป็นข้อมูลจำเพาะภาษา Java


12

ก่อนที่จะเรียกใช้เมธอดหลักจะไม่มีการสร้างออบเจ็กต์ การมีคำหลักคงที่หมายถึงวิธีการที่สามารถเรียกได้โดยไม่ต้องสร้างวัตถุใด ๆ ก่อน


ไม่ถูกต้อง. หรืออย่างน้อยไม่แน่นอนมาก คลาสสาธารณะหลัก {วัตถุวัตถุคงที่ = วัตถุใหม่ () {{System.out.println ("วัตถุที่สร้างขึ้น"); }}; โมฆะคงที่สาธารณะหลัก (String [] args) {System.out.println ("ในหลัก"); }}
eljenso

ความคิดเห็นที่เป็นธรรม ในทางเทคนิคแล้วฉันควรจะบอกว่าก่อนที่จะมีการเรียกเมธอด Main คลาสที่มีเมธอด main จะไม่ถูกทำให้เป็นอินสแตนซ์
BlackWasp

12

เพราะมิฉะนั้นจะต้องมีอินสแตนซ์ของวัตถุที่จะดำเนินการ แต่จะต้องถูกเรียกจากศูนย์โดยไม่ต้องสร้างวัตถุก่อนเนื่องจากโดยทั่วไปแล้วจะเป็นหน้าที่ของ main () ฟังก์ชั่น (bootstrap) เพื่อแยกอาร์กิวเมนต์และสร้างวัตถุโดยใช้พารามิเตอร์อาร์กิวเมนต์ / โปรแกรมเหล่านี้


10

ให้ฉันอธิบายสิ่งเหล่านี้ในวิธีที่ง่ายกว่ามาก:

public static void main(String args[])

แอปพลิเคชัน Java ทั้งหมดยกเว้นแอปเพล็ตเริ่มการทำงานจาก main()ทุกการใช้งานจาวายกเว้นแอปเพล็เริ่มต้นการดำเนินการของพวกเขาจาก

คำสำคัญpublicคือตัวดัดแปลงการเข้าถึงซึ่งอนุญาตให้สมาชิกถูกเรียกจากภายนอกคลาส

staticถูกใช้เนื่องจากอนุญาตให้main()เรียกได้โดยไม่ต้องยกตัวอย่างของคลาสนั้น

voidบ่งชี้ว่าmain()ไม่ส่งคืนค่าใด ๆ


9

ความหมายของpublic static void main(String args[])อะไร

  1. public เป็นตัวระบุการเข้าถึงหมายความว่าทุกคนสามารถเข้าถึง / เรียกใช้เช่น JVM (Java Virtual Machine)
  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 */
        }
    }

    ในทำนองเดียวกันเราใช้สแตติกบางครั้งสำหรับวิธีการที่ผู้ใช้กำหนดดังนั้นเราไม่จำเป็นต้องสร้างวัตถุ

  3. voidบ่งชี้ว่าmain()วิธีการประกาศไม่คืนค่า

  4. String[] argsระบุพารามิเตอร์เท่านั้นในmain()วิธีการ

    args- Stringพารามิเตอร์ที่มีอาร์เรย์ของวัตถุชนิดระดับเกรด


6

Applets, midlets, servlets และ beans หลายชนิดถูกสร้างขึ้นและมีเมธอดวงจรชีวิตที่เรียกใช้ การเรียกใช้ main คือสิ่งที่เคยทำกับคลาสหลักดังนั้นจึงไม่จำเป็นต้องมีสถานะที่จะถูกเก็บไว้ในวัตถุที่เรียกว่าหลายครั้ง เป็นเรื่องปกติที่จะปักหมุดบนชั้นอื่น (แม้ว่าจะไม่ใช่ความคิดที่ดี) ซึ่งจะเป็นการใช้ชั้นเรียนเพื่อสร้างวัตถุหลัก


5

มันเป็นเพียงแค่การประชุม แต่อาจจะสะดวกกว่าทางเลือกอื่น ด้วยหลักคงที่สิ่งที่คุณต้องรู้เพื่อเรียกใช้โปรแกรม Java คือชื่อและที่ตั้งของชั้นเรียน ถ้ามันไม่คงที่คุณต้องรู้วิธีสร้างอินสแตนซ์ของคลาสนั้นหรือต้องการให้คลาสนั้นมี Constructor ว่างเปล่า


มันไม่ใช่การประชุม เป็นส่วนหนึ่งของข้อกำหนดภาษา รันไทม์จะไม่รู้จักคลาสที่ไม่มีเมธอด main static เป็นจุดเข้าใช้งานที่ถูกต้อง
Rob

2
สเป็คภาษาตัวเองเป็นไปตามการประชุม ไม่มีข้อกำหนดที่แท้จริงสำหรับนักออกแบบ Java ที่จะเลือกใช้สำหรับการใช้งานสแตติกหลัก อย่างไรก็ตามดังที่โลแกนอธิบายว่าทางเลือกนั้นซับซ้อนกว่า
David Arno

@DavidArno มันจะทำให้รู้สึกมากกว่าที่จะพูดว่าการประชุมตามข้อกำหนดภาษา
มาร์ควิสแห่ง Lorne

5

หากวิธีการหลักจะไม่คงที่คุณจะต้องสร้างวัตถุของคลาสหลักของคุณจากนอกโปรแกรม คุณต้องการทำอย่างไร


5

เมื่อคุณรัน Java Virtual Machine (JVM) ด้วยjavaคำสั่ง

java ClassName argument1 argument2 ...

เมื่อคุณเรียกใช้แอปพลิเคชันของคุณคุณจะต้องระบุชื่อคลาสเป็นอาร์กิวเมนต์สำหรับคำสั่ง java ดังกล่าวข้างต้น

JVM พยายามเรียกใช้เมธอดหลักของคลาสที่คุณระบุ

- ณ จุดนี้ไม่มีการสร้างวัตถุของชั้นเรียน

ประกาศmainเป็นallowsJVM แบบสแตติกเพื่อสร้างinvokemain ของคลาสwithoutinstance

กลับไปที่คำสั่ง

ClassNameคือcommand-line argumentการ JVM ที่บอกคลาสที่จะดำเนินการ หลังจาก ClassName คุณสามารถระบุlist of Strings(คั่นด้วยช่องว่าง) เป็นอาร์กิวเมนต์บรรทัดคำสั่งที่ JVM จะส่งผ่านไปยังแอ็พพลิเคชันของคุณ - อาร์กิวเมนต์ดังกล่าวอาจถูกใช้เพื่อระบุตัวเลือก (เช่นชื่อไฟล์) เพื่อเรียกใช้แอปพลิเคชัน - นี่คือสาเหตุที่มีพารามิเตอร์ที่เรียกว่าString[] argsใน main

ข้อมูลอ้างอิง: Java ™วิธีการโปรแกรม (Early Objects), Tenth Edition


4

เมื่อเร็ว ๆ นี้มีการโพสต์คำถามที่คล้ายกันที่ Programmers.SE

  • ทำไมวิธีหลักแบบคงที่ใน Java และ C # มากกว่าตัวสร้าง?

    กำลังมองหาคำตอบที่ชัดเจนจากแหล่งที่มาหลักหรือรองว่าทำไม (และสะดุดตา) Java และ C # ตัดสินใจที่จะมีวิธีการคงที่เป็นจุดเริ่มต้นของพวกเขา - แทนที่จะเป็นตัวแทนอินสแตนซ์ของแอปพลิเคชันโดยอินสแตนซ์ของApplicationคลาส คอนสตรัคที่เหมาะสม?

TL; DRส่วนหนึ่งของคำตอบที่ยอมรับคือ

ใน Java เหตุผลpublic static void main(String[] args)ก็คือ

  1. ลูกห่านที่ต้องการ
  2. รหัสที่เขียนโดยคนที่มีประสบการณ์ใน C (ไม่ใช่ใน Java)
  3. จะถูกประหารโดยใครบางคนที่เคยใช้งานPostScriptบนNeWS

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

 
สำหรับ C # เหตุผลคล้ายคลึงกันในลักษณะทรานซิทจึงจะพูด นักออกแบบภาษาใช้ไวยากรณ์จุดเข้าใช้งานโปรแกรมที่คุ้นเคยสำหรับโปรแกรมเมอร์ที่มาจาก Java ในฐานะที่เป็น C # สถาปนิกAnders Hejlsberg ทำให้มัน ,

... แนวทางของเรากับ C # เป็นเพียงการนำเสนอทางเลือก ... แก่โปรแกรมเมอร์ Java ...

...


3

ฉันคิดว่าคำหลัก 'คงที่' ทำให้วิธีการหลักเป็นวิธีการเรียนและวิธีการเรียนมีเพียงหนึ่งสำเนาของมันและสามารถใช้ร่วมกันโดยทั้งหมดและยังไม่จำเป็นต้องมีวัตถุสำหรับการอ้างอิง ดังนั้นเมื่อมีการคอมไพล์คลาสไดรเวอร์เมธอดหลักสามารถเรียกใช้ได้ (ฉันแค่อยู่ในระดับตัวอักษรของจาวาขอโทษถ้าฉันผิด)


วิธีการทั้งหมดมีเพียงหนึ่งสำเนาเท่านั้น
มาร์ควิสแห่ง Lorne

3

main () เป็นแบบคงที่เพราะ; ณ จุดนั้นในวงจรชีวิตของแอปพลิเคชันสแต็กของแอปพลิเคชันเป็นขั้นตอนตามธรรมชาติเนื่องจากยังไม่มีวัตถุที่อินสแตนซ์

มันเป็นกระดานชนวนที่สะอาด แอปพลิเคชันของคุณกำลังทำงานที่จุดนี้แม้ว่าจะไม่มีการประกาศวัตถุใด ๆ ก็ตาม (โปรดจำไว้ว่ามีรูปแบบการเข้ารหัสและขั้นตอนการ OO) คุณในฐานะนักพัฒนาเปลี่ยนแอปพลิเคชันให้เป็นโซลูชันเชิงวัตถุโดยการสร้างอินสแตนซ์ของวัตถุของคุณและขึ้นอยู่กับโค้ดที่รวบรวมภายใน

การวางวัตถุนั้นยอดเยี่ยมด้วยเหตุผลหลายล้านอย่างที่ชัดเจน อย่างไรก็ตามไปแล้วเป็นวันที่นักพัฒนา VB ส่วนใหญ่ใช้คำหลักเช่น "goto" ในรหัสของพวกเขาเป็นประจำ "goto" เป็นคำสั่งขั้นตอนใน VB ที่ถูกแทนที่ด้วย OO คู่กัน: การเรียกใช้เมธอด

นอกจากนี้คุณยังสามารถดูที่จุดเข้าใช้งานแบบคงที่ (หลัก) ว่าเป็นอิสระอย่างแท้จริง หาก Java แตกต่างกันพอที่จะยกตัวอย่างวัตถุและแสดงเฉพาะอินสแตนซ์นั้นให้คุณทำงานคุณจะไม่มีทางเลือก แต่จะเขียนแอปตามขั้นตอน เป็นไปไม่ได้ราวกับว่ามันอาจฟังดูสำหรับ Java เป็นไปได้มีหลายสถานการณ์ที่เรียกว่าวิธีการขั้นตอน

นี่อาจเป็นคำตอบที่คลุมเครือมาก โปรดจำไว้ว่า "class" เป็นเพียงชุดของรหัสที่เกี่ยวข้องกัน "อินสแตนซ์" เป็นรุ่นที่แยกตัวอยู่อาศัยและหายใจอิสระในชั้นเรียนนั้น


7
สิ่งนี้ไม่ถูกต้อง วัตถุจำนวนมากถูกสร้างอินสแตนซ์ก่อนที่mainจะถึง และถ้าคุณรวม Constructor แบบคงที่ในคลาสที่มี main สิ่งนั้นจะถูกดำเนินการก่อนหน้าmainเช่นเดียวกัน
Konrad Rudolph

2

มันเป็นเพียงแค่การประชุม JVM สามารถจัดการกับวิธีการแบบไม่คงที่ได้แน่นอนหากเป็นแบบแผน ท้ายที่สุดคุณสามารถกำหนด initializer คงที่ในชั้นเรียนของคุณและยกตัวอย่างวัตถุ zillion ก่อนที่จะไปยังวิธีการหลัก () ของคุณ


2

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 เพราะมันส่อนัยโดยข้อเท็จจริงที่ว่าไม่มีการสร้างตัวอย่างก่อนที่จะเรียกวิธีการหลัก


2

publicคำหลักคือการปรับปรุงการเข้าถึงซึ่งจะช่วยให้โปรแกรมเมอร์ที่จะควบคุมการแสดงผลของสมาชิกในชั้นเรียน เมื่อสมาชิกคลาสถูกนำหน้าด้วยpublicสมาชิกนั้นอาจเข้าถึงได้โดยรหัสภายนอกคลาสที่มีการประกาศ

ตรงกันข้ามของpublicคือprivateซึ่งป้องกันสมาชิกจากการถูกใช้โดยรหัสที่กำหนดไว้นอกชั้นเรียน

ในกรณีนี้main()จะต้องประกาศเป็นpublicเพราะมันจะต้องถูกเรียกโดยรหัสนอกระดับเมื่อโปรแกรมเริ่มต้น

คีย์เวิร์ดstaticอนุญาตให้ main()ถูกเรียกโดยไม่ต้องยกตัวอย่างอินสแตนซ์ของคลาส สิ่งนี้มีความจำเป็นตั้งแต่main()ล่าม Java ถูกเรียกใช้ก่อนที่วัตถุใด ๆ จะถูกสร้างขึ้น

คำหลักvoidเพียงบอกคอมไพเลอร์ที่main()ไม่ส่งคืนค่า


1

จุดเริ่มต้นที่แท้จริงไปยังแอปพลิเคชันใด ๆ เป็นวิธีการคงที่ หากภาษา Java รองรับวิธีอินสแตนซ์เป็น "จุดเข้าใช้งาน" แล้วรันไทม์จะต้องใช้มันภายในเป็นวิธีคงที่ซึ่งสร้างอินสแตนซ์ของวัตถุตามด้วยการเรียกวิธีการอินสแตนซ์

เมื่อพ้นทางนั้นฉันจะตรวจสอบเหตุผลในการเลือกหนึ่งในสามตัวเลือกต่อไปนี้:

  1. static void main()เหมือนที่เราเห็นในวันนี้
  2. วิธีการอินสแตนซ์ที่void main()เรียกว่าบนวัตถุที่สร้างขึ้นใหม่
  3. การใช้ตัวสร้างประเภทเป็นจุดเริ่มต้น (เช่นถ้ามีการเรียกคลาสรายการProgramการดำเนินการจะประกอบด้วยอย่างมีประสิทธิภาพnew Program())

ทำให้พังถล่ม:

static void main()

  1. เรียกใช้ตัวสร้างแบบคงที่ของคลาสที่ล้อมรอบ
  2. main()เรียกวิธีการคง

void main()

  1. เรียกใช้ตัวสร้างแบบคงที่ของคลาสที่ล้อมรอบ
  2. new ClassName()สร้างอินสแตนซ์ของชั้นล้อมรอบด้วยการได้อย่างมีประสิทธิภาพเรียก
  3. main()เรียกวิธีการเช่น

new ClassName()

  1. เรียกใช้ตัวสร้างแบบคงที่ของคลาสที่ล้อมรอบ
  2. สร้างตัวอย่างของคลาส (จากนั้นไม่ทำอะไรเลยกับมันแล้วส่งคืน)

เหตุผล:

ฉันจะเรียงลำดับย้อนกลับสำหรับอันนี้

โปรดทราบว่าหนึ่งในเป้าหมายการออกแบบของ Java คือการเน้นการเขียนโปรแกรมเชิงวัตถุที่ดี ในบริบทนี้ตัวสร้างของวัตถุเริ่มต้นวัตถุ แต่ไม่ควรรับผิดชอบต่อพฤติกรรมของวัตถุ ดังนั้นข้อมูลจำเพาะที่ให้จุดเริ่มต้นnew ClassName()จะทำให้สถานการณ์สับสนสำหรับผู้พัฒนา Java ใหม่โดยบังคับให้มีข้อยกเว้นในการออกแบบตัวสร้าง "อุดมคติ" ในทุก ๆ แอปพลิเคชัน

โดยการทำmain()วิธีการตัวอย่างปัญหาข้างต้นได้รับการแก้ไขอย่างแน่นอน อย่างไรก็ตามมันสร้างความซับซ้อนโดยการกำหนดคุณสมบัติเพื่อแสดงรายการลายเซ็นของคอนสตรัคเตอร์ของคลาสรายการรวมทั้งลายเซ็นของmain()วิธีการ

โดยสรุประบุstatic void main()สร้างสเปคที่มีความซับซ้อนน้อยในขณะที่การยึดมั่นในหลักการของพฤติกรรมการวางลงในวิธีการ เมื่อพิจารณาว่าตรงไปตรงมาคือการใช้main()เมธอดที่สร้างอินสแตนซ์ของคลาสและเรียกใช้เมธอดอินสแตนซ์ไม่มีประโยชน์จริง ๆ ในการระบุmain()เป็นวิธีอินสแตนซ์


1
นี่เป็นเพียงแค่ขอทานคำถาม Java mainต้องการอยู่แล้วสำหรับรถตักดินปพลิเคชันที่ไม่ยกของหนักก่อนที่จะเรียก เหตุผลของคุณเกี่ยวกับmainความซับซ้อนเกินไปสำหรับผู้เริ่มต้นดูเหมือนไม่น่าเชื่อ ในความเป็นจริงคงmainเป็นอย่างมากทำให้เกิดความสับสนสำหรับผู้เริ่มต้นผมสงสัยนวกรรมิกจะมีมากขึ้นดังนั้น คุณพูดว่า“ ผู้สร้างไม่ควรรับผิดชอบต่อพฤติกรรมของวัตถุ” ฟังดูน่าสนใจ แต่ฉันไม่แน่ใจว่าฉันเห็นด้วย ทำไมไม่เป็นเช่นนั้น? จะป้องกันสิ่งนี้ได้อย่างไร
Konrad Rudolph

1

คงที่ - เมื่อ JVM ทำให้การเรียกวิธีการหลักไม่มีวัตถุที่มีอยู่สำหรับชั้นเรียนที่ถูกเรียกดังนั้นมันจะต้องมีวิธีการแบบคงที่เพื่อให้สามารถเรียกใช้จากชั้นเรียน


1

ฉันไม่รู้ว่า JVM เรียกใช้วิธีการหลักก่อนที่วัตถุจะถูกสร้างอินสแตนซ์ ... แต่มีเหตุผลที่ทรงพลังกว่าทำไมเมธอด main () นั้นคงที่ ... เมื่อ JVM เรียกเมธอดหลักของคลาส (พูด คน) มันเรียกใช้โดย " Person.main () " คุณเห็น JVM เรียกใช้โดยชื่อคลาส นั่นคือเหตุผลที่เมธอด main () ควรจะเป็นแบบสแตติกและเป็นแบบสาธารณะเพื่อให้สามารถเข้าถึงได้โดย JVM

หวังว่ามันจะช่วย ถ้าเป็นเช่นนั้นแจ้งให้เราทราบโดยแสดงความคิดเห็น


0

วิธีการคงที่ไม่ต้องใช้วัตถุใด ๆ มันวิ่งโดยตรงดังนั้นวิ่งหลักโดยตรง


0

คำสำคัญคงที่ในวิธีการหลักจะใช้เพราะไม่มีการสร้างตัวอย่างที่เกิดขึ้นในวิธีการหลัก แต่วัตถุนั้นถูกสร้างขึ้นแทนที่จะเรียกใช้ดังนั้นเราจึงใช้คำสำคัญคงที่ในวิธีการหลัก ในหน่วยความจำบริบท jvm จะถูกสร้างขึ้นเมื่อโหลดคลาสลงไปและสมาชิกสแตติกทั้งหมดจะอยู่ในหน่วยความจำนั้น หากเราสร้างสแตติกหลักตอนนี้มันจะอยู่ในหน่วยความจำและสามารถเข้าถึงได้โดย jvm (class.main (.. )) ดังนั้นเราสามารถเรียกเมธอดหลักโดยไม่จำเป็นต้องสร้างฮีปได้


0

มันเป็นเพียงการประชุมที่เราสามารถดูได้ที่นี่:

วิธีการจะต้องประกาศสาธารณะและคงที่จะต้องไม่ส่งกลับค่าใด ๆ และจะต้องยอมรับอาร์เรย์สตริงเป็นพารามิเตอร์ โดยค่าเริ่มต้นอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกแรกคือชื่อของชั้นที่จะเรียก ควรใช้ชื่อคลาสที่ผ่านการรับรองโดยสมบูรณ์ หากระบุอ็อพชัน -jar อาร์กิวเมนต์ที่ไม่ใช่ตัวเลือกแรกคือชื่อของไฟล์เก็บถาวร JAR ที่มีคลาสและไฟล์รีซอร์สสำหรับแอ็พพลิเคชันโดยมีคลาสเริ่มต้นที่ระบุโดยส่วนหัวรายการคลาสหลัก

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


กฎของภาษาคุณหมายถึง
มาร์ควิสแห่ง Lorne

0

คำหลักโมฆะสาธารณะคงที่หมายถึงล่าม Java virtual machine (JVM) สามารถเรียกวิธีการหลักของโปรแกรมเพื่อเริ่มโปรแกรม (สาธารณะ) โดยไม่ต้องสร้างอินสแตนซ์ของคลาส (คงที่) และโปรแกรมไม่ส่งคืนข้อมูลไปยังล่าม Java VM (เป็นโมฆะ) เมื่อมันสิ้นสุด

ที่มา: สิ่งจำเป็นตอนที่ 1 บทที่ 2: การสร้างแอปพลิเคชัน


0

โดยพื้นฐานแล้วเราได้จัดทำข้อมูลสมาชิกและสมาชิกฟังก์ชั่นเหล่านั้นเป็นสถิติซึ่งไม่ได้ทำงานใด ๆ ที่เกี่ยวข้องกับวัตถุ และในกรณีของวิธีการหลักเราจะทำให้มันเป็นแบบคงที่เพราะมันไม่มีอะไรเกี่ยวข้องกับวัตถุเพราะวิธีการหลักนั้นจะทำงานอยู่เสมอไม่ว่าเราจะสร้างวัตถุหรือไม่


0

วิธีการใด ๆ ที่ประกาศเป็นแบบคงที่ใน Java เป็นของชั้นเรียนตัวเอง วิธีการคงที่อีกครั้งของคลาสเฉพาะสามารถเข้าถึงได้โดยอ้างอิงถึงคลาสที่ชอบเท่านั้นClass_name.method_name();

ดังนั้นคลาสไม่จำเป็นต้องมีอินสแตนซ์ก่อนที่จะเข้าถึงวิธีการคงที่

ดังนั้นเมธอด main () จึงถูกประกาศstaticว่าสามารถเข้าถึงได้โดยไม่ต้องสร้างออบเจ็กต์ของคลาสนั้น

เนื่องจากเราบันทึกโปรแกรมด้วยชื่อของคลาสที่มีวิธีการหลักอยู่ (หรือจากที่โปรแกรมควรเริ่มการทำงานของมันซึ่งสามารถใช้งานได้สำหรับคลาสที่ไม่มีmain()เมธอด () (ระดับขั้นสูง)) ดังนั้นโดยวิธีการดังกล่าวข้างต้น:

Class_name.method_name();

วิธีการหลักสามารถเข้าถึงได้

โดยสังเขปเมื่อโปรแกรมถูกคอมไพล์มันจะค้นหาmain()เมธอดที่มีStringอาร์กิวเมนต์เช่น: main(String args[])ในคลาสที่กล่าวถึง (เช่นโดยชื่อของโปรแกรม) และตั้งแต่ต้นมันไม่มีขอบเขตในการสร้างอินสแตนซ์ของคลาสนั้นดังนั้น main () วิธีการประกาศเป็นแบบคงที่


มันเกิดขึ้นเมื่อโปรแกรมทำงานไม่ได้คอมไพล์
มาร์ควิสแห่ง Lorne

0

จากjava.sun.com (มีข้อมูลเพิ่มเติมเกี่ยวกับเว็บไซต์):

วิธีการหลักคือคงที่เพื่อให้ล่าม Java VM วิธีการเริ่มเรียนโดยไม่ต้องสร้างตัวอย่างของการควบคุมชั้นแรก อินสแตนซ์ของคลาสควบคุมถูกสร้างในวิธีหลักหลังจากที่โปรแกรมเริ่มทำงาน

ความเข้าใจของฉันเป็นเพียงแค่วิธีการหลักเช่นเดียวกับวิธีการคงที่ใด ๆ สามารถเรียกได้โดยไม่ต้องสร้างอินสแตนซ์ของคลาสที่เกี่ยวข้องช่วยให้มันทำงานก่อนสิ่งอื่นใดในโปรแกรม ถ้ามันไม่คงที่คุณจะต้องยกตัวอย่างวัตถุก่อนที่จะเรียกมัน - ซึ่งสร้างปัญหา 'ไก่และไข่' เนื่องจากวิธีการหลักโดยทั่วไปคือสิ่งที่คุณใช้ในการสร้างอินสแตนซ์ของวัตถุที่จุดเริ่มต้นของโปรแกรม


แต่มันจะไม่ทำงาน“ ก่อนสิ่งอื่นใดในโปรแกรม” อาร์กิวเมนต์ทั้งหมดเป็นความเข้าใจผิดและยิ่งไปกว่านั้นนี่ไม่ใช่คำตอบแรกที่กล่าวถึงหรือแม้แต่ข้อสองหรือข้อสาม
Konrad Rudolph

ฉันขอโทษที่คำตอบของฉันซ้ำสิ่งที่คนอื่นพูด ฉันตอบเฉพาะความเข้าใจที่ดีที่สุดและจากสิ่งที่ฉันสามารถหาได้ทางออนไลน์ จากผลลัพธ์ที่ฉันได้ดูไม่มีเหตุผลอื่นว่าทำไมวิธีหลักจึงคงที่ ถ้าไม่มีใครซ่อนอยู่ที่ไหนสักแห่งบางทีนั่นอาจเป็นคำตอบเดียวที่มี ความเข้าใจของฉันเกี่ยวกับ Java ค่อนข้างพื้นฐาน แต่ฉันเคยได้ยินเหตุผลข้างต้น (จากอาจารย์ตำรา ฯลฯ ) และไม่เคยมีใครอื่น
Jesse M

@Jesse M ความคิดเห็นของคุณจะสมเหตุสมผลถ้าคุณไม่ได้ลองอ่านคำตอบอื่นก่อน ซึ่งโดยวิธีนี้ไม่ได้เป็นสิ่งที่ไกลเกินเอื้อมที่จะทำ เมื่อคุณพูดถึงตัวเองความเข้าใจของคุณนั้นค่อนข้างพื้นฐานดังนั้นจึงเป็นไปได้มากที่คนอื่นจะตอบคำถามได้ดีกว่า และความคิดเห็นของคุณดูเหมือนจะหาเหตุผลเข้าข้างตนเองเพื่อให้คำตอบของคุณดูดีขึ้น มันเป็นข้อเรียกร้องที่ไม่ธรรมดาที่คุณมีตำราและอาจารย์ของ Java ที่คิดว่าสิ่งที่คุณอ้างและตรงไปตรงมาฉันไม่เชื่อว่าพวกเขาทำ (การอ้างอิงใด ๆ ?)
LeoR

1
@ KonradRudolph ความคิดเห็นยอดนิยมดูเหมือนจะค่อนข้างสมเหตุสมผล main () ใช้เป็นจุดเข้าสู่โปรแกรมและมีการอ้างอิงหลายรายการบนเว็บไซต์ Java ที่บอกว่าควรจะคล้ายกับวิธีที่ C / C ++ มีฟังก์ชั่น main () เนื่องจาก Java เป็นวัตถุทั้งหมดจึงต้องเป็นแบบคงที่เพื่อหลีกเลี่ยงการสร้างอินสแตนซ์ของวัตถุ การมีสแตติกช่วยให้สามารถโหลดและเรียกใช้งานได้ใน JVM ขณะใช้งานจริง ฉันเพิ่งสำรอกคำตอบก่อนหน้านี้ แต่ฉันสงสัยว่าคุณจะพิจารณาคำตอบที่น่าพอใจอย่างไร ฉันคิดว่าสิ่งที่ดีที่สุดที่คุณจะได้รับคือ "นั่นคือสิ่งที่พวกเขาต้องการ" โปรดจำไว้ว่าวันที่ Java ถูกสร้างขึ้น
เทรเวอร์ -e

1
@Jesse Spot-on เป็นไปได้ทั้งหมดว่าเป็นเพียงเรื่องของการประชุม (แม้ว่าฉันหวังว่ามันจะไม่เป็นเช่นนั้นจะเป็นคำตอบที่น่าเบื่อ) ความสนใจเริ่มแรกของฉันในคำถามนี้คือเพราะฉันคิดว่าการใช้อินสแตนซ์ที่เหมาะสมเพื่อแสดงวัตถุ "แอพพลิเคชั่นที่กำลังรัน" และการมีจุดเข้าใช้งานเป็นวิธีการ (หรือตัวสร้าง) ของคลาสนี้ ถูกออกแบบให้เป็นเชิงวัตถุจากที่ได้รับไปและตั้งแต่วัตถุคล้ายดูเหมือน (กระทู้, ผ่านRunnable) ในชวาทำใช้การออกแบบนี้ ทำไมข้อยกเว้น (ชัดเจน) ที่นี่?
Konrad Rudolph
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.