Java ana yöntemi neden statiktir?


505

Java main () yönteminin yöntem imzası :

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

Bu yöntemin statik olmasının bir nedeni var mı?


1
bu durumda, yöntem imzasını söylememeliyiz , çünkü terim sadece yöntem adlarını ve parametrelerini ifade eder
Andrew Tobilko

Java, bir C programcısına tanıdık gelecek şekilde tasarlanmıştır. Bu C sözleşmesine çok yakın.
Thorbjørn Ravn Andersen

Yanıtlar:


337

Yöntem statiktir çünkü aksi takdirde belirsizlik olacaktır: hangi kurucu çağrılmalıdır? Özellikle sınıfınız şöyle görünüyorsa:

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

JVM aramalı new JavaClass(int)mı? Ne için geçmeli x?

Değilse, JVM JavaClassherhangi bir kurucu yöntemi çalıştırmadan başlatılmalı mıdır? Bence değil, çünkü bu tüm sınıfınızı özel olarak ele alacaktır - bazen başlatılmamış bir örneğiniz vardır ve çağrılabilecek her yöntemde bunu kontrol etmeniz gerekir.

Giriş noktası çağrılmadan önce JVM'nin bir sınıfı başlatması mantıklı hale gelmesi için çok fazla uç durum ve belirsizlik var. Bu yüzden mainstatiktir.

Neden mainhep işaretlenmiş olduğu hakkında hiçbir fikrim yok public.


4
Bir arabirim uygulamak örnekleme sorununu çözmez.
Jacob Krall

26
Ben şahsen bu public static void mainbir giriş noktasının bir işareti olarak hizmet - hoş bir kamu parametresiz yapıcı "Bu muhtemelen bir giriş noktası!" aynı şekilde.
Jacob Krall

5
@EdwinDalorzo - Giriş noktası sınıfını somutlaştırılmaya zorlayarak ne elde edilir? Statik bir yöntem çağırmak, sınıfa en az yük getirir. Bu, tasarımınız için daha mantıklıysa, kendini örneklemek ücretsizdir.
David Harkness

18
“Hangi kurucu çağrılmalıdır?” Bu bile akla yatkın bir problemdir? mainAranacak karar için aynı “sorun” vardır . Garip bir şekilde (sizin için) JVM bunu gayet iyi idare ediyor.
Konrad Rudolph

9
Ana yöntem her zaman herkese açıktır, çünkü çalışma zamanı motoru JVM tarafından erişilmesi gerekir.
gthm

398

Bu sadece bir ibadet. Aslında, main () adı ve aktarılan argümanlar bile tamamen ibadettir.

Java.exe'yi (veya Windows'ta JavaW.exe) çalıştırdığınızda, gerçekten olan birkaç Java Yerel Arabirimi (JNI) çağrısıdır. Bu çağrılar gerçekten JVM DLL yükler (bu doğru - java.exe JVM DEĞİLDİR). JNI, sanal makine dünyasını ve C, C ++, vb. Dünyasını köprülememiz gerektiğinde kullandığımız araçtır ... Tersi de doğrudur - (en azından bilgime göre) aslında bir JVM, JNI kullanmadan çalışır.

Temel olarak, java.exe, komut satırını ayrıştıran, bu bağımsız değişkenleri tutmak için JVM'de yeni bir String dizisi oluşturan, main () içerdiği belirttiğiniz sınıf adını ayrıştıran, bulmak için JNI çağrılarını kullanan süper basit bir C uygulamasıdır. main () yönteminin kendisini seçtikten sonra, yeni oluşturulan dize dizisini parametre olarak ileterek main () yöntemini çağırır. Bu, Java'dan yansıma kullandığınızda yaptığınız gibi çok, çok benzer - bunun yerine kafa karıştırıcı olarak adlandırılmış yerel işlev çağrılarını kullanır.

Kendi java.exe (kaynak JDK ile dağıtılır) sürümünü yazmak ve tamamen farklı bir şey yapmak için mükemmel yasal olacaktır. Aslında, tüm Java tabanlı uygulamalarımızla tam olarak bunu yapıyoruz.

Java uygulamalarımızın her birinin kendi başlatıcısı vardır. Öncelikle bunu yapıyoruz, böylece kendi ikonumuzu ve süreç ismimizi alıyoruz, ancak işleri yapmak için normal main () çağrısının yanı sıra bir şeyler yapmak istediğimiz diğer durumlarda kullanışlı oldu (Örneğin, bir durumda COM ile birlikte çalışabilirlik ve aslında bir COM tutamacını dize dizisi yerine main () içine geçiririz).

Uzun ve kısa: statik olmasının nedeni uygun olan b / c. 'Ana' deniyor nedeni () onlar C eski günlerdeki (ve o günlerde, fonksiyonun adı yaptıklarını bir şey olması gerekiyordu ve ana olmasıdır idi önemli). Java.exe'nin sadece sınıf (java com.mycompany.Foo.someSpecialMain) yerine tam nitelikli bir ana yöntem adı belirtmenize izin verebileceğini varsayalım - ancak IDE'lerde otomatik olarak algılamayı zorlaştırıyor ' launcdable 'sınıfları.


66
+1: Çok etkileyici (özellikle bir özel yazma bölümü java.exe)
Adam Paynter

9
İlginç olan, "Bu sadece bir ibadet." Cevabın bir parçası. OP'nin asıl sorusu, deklarasyonda statik neden oldu. Sanmıyorum staticiçinde main()beyan sadece kongre uğruna olduğunu. Bununla birlikte, başka bir şey değil, `` ana () '' olması mümkündür.
Jared

2
@David Öyleydi. Aslında başlangıçta yer alan insanlardan bir cevap tercih ederdim - ama bu çok uzak bir vuruştu. Diğer cevapların çoğu maalesef geçici akıl yürütmedir. Bu, (muhtemelen) teknik olmayan bir nedenden ötürü yanlış teknik detayları icat etmemek için alçakgönüllülüğe sahip olmanın yanı sıra oldukça ilginç ayrıntılar verir.
Konrad Rudolph

2
@Jared - Herkese açık argüman kurucuya ihtiyaç duyabilirler ve mainstatik olmayan ve yine de dilin sınırları dahilinde olabilirlerdi. Tasarımcılardan haber almadan, katılmamaya karar vermeliyiz. :)
David Harkness

4
@BenVoigt jvm dll almak için LoadLibrary () çağırırsınız. Sonra getprocaddress'i ("JNI_CreateJavaVM") çağırırsınız, ardından JNI_CreateJavaVM işlevini çağırırsınız ( docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/… ) çağırırsınız . VM yüklendikten sonra, doğru sınıfı bulmak, statik ana yöntemi yüklemek ve çağırmak için standart JNI çağrılarını kullanırsınız. Orada yanlış yorumlanacak çok yer yok. JNI kesinlikle VM'yi nasıl yüklediğinizdir. Yerel anahtar, javah -jni, vb. Kullanılarak yalnızca istemci tarafı JNI yazmak için kullanılabilir ... ancak bu, JNI'nın yalnızca yarısıdır.
Kevin Day

188

main()Yöntem C++, C#ve Javastatiktir
daha sonra çalışma zamanı motoru devreye sokulabilen Çünkü olmadan gövdesinde sonra kodu herhangi bir nesneyi örneğini zorunda main()gerisini halleder.


1
Tamam ama çalışma zamanı sınıfın bir nesnesini başlatamadı mı? Ve sonra Ana yöntemi çağır? Neden?
Andrei Rînea

12
JVM, ana sınıfınız kurucuları aşırı yüklüyse hangi kurucuyu arayacağını nasıl bilebilir? Hangi parametreleri geçirirdi?
Jacob Krall

1
@Noah, üst sınıf dediğinde ana yöntemi içeren sınıfı mı kastediyorsun? Çünkü eğer öyleyse, "ana sınıf" terimi burada oldukça kafa karıştırıcıdır, aksi takdirde benim için bir anlam ifade etmez. Ayrıca, eğer sözleşmeyle kullanırsak public static void main..., uygulama giriş noktası sınıfının ortak bir varsayılan kurucuya sahip olması neden kural olamaz?
Edwin Dalorzo

2
@Jacob JVM hangisinin aşırı yükleneceğini nasıl bilebilir static void main? Hiç sorun değil.
Konrad Rudolph

4
@Namratha: Evet, bir şey eksik. "Statik yöntemin statik olmayan yönteme başvuramadığı" doğru değil. Doğru ifade: "Her statik yöntem, statik olmayan bir yöntem kullanılırken bir nesne sağlamalıdır". Ve bak, böyle bir nesne oluşturmak için sık kullanılan staticyöntemler gibi . mainnew
Ben Voigt

38

Neden genel statik void main (String [] argümanları)?

Java Dili bu şekilde tasarlanır ve Java Sanal Makinesi bu şekilde tasarlanır ve yazılır.

Oracle Java Dil Özellikleri

Check out Bölüm 12.1.4 çağırır Test.main - Bölüm 12 Yürütülmesine :

Son olarak, Sınıf Testi için başlatma işleminin tamamlanmasından sonra (bu sırada diğer yükleme, bağlama ve başlatma işlemleri gerçekleşmiş olabilir), Test ana yöntemi çağrılır.

Main yöntemi genel, statik ve geçersiz olarak bildirilmelidir. Bir dize dizisi olan tek bir argümanı kabul etmelidir. Bu yöntem ya

public static void main(String[] args)

veya

public static void main(String... args)

Oracle Java Sanal Makine Özellikleri

Check out Bölüm 2 Java Programlama Dili Kavramları - Bölüm 2.17 Yürütme :

Java sanal makinesi, belirtilen sınıfın ana yöntemini çağırarak ve dizeden oluşan tek bir argüman ileterek yürütmeye başlar. Bu, belirtilen sınıfın yüklenmesine (§2.17.2), kullandığı diğer türlere (§2.17.3) bağlanmasına ve başlatılmasına (§2.17.4) neden olur. Main yöntemi genel, statik ve geçersiz olarak bildirilmelidir.

Oracle OpenJDK Kaynağı

Kaynak kavanozunu indirin ve çıkarın ve JVM'nin nasıl yazıldığını görün, ../launcher/java.ckomutun arkasında yerel C kodu içeren kontrol edin 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
Buradaki problem, bunun aslında soruya orijinal haliyle, çok sayıda referansla (+1) çok iyi bir cevap olmasıdır. Ancak, bir yapıcı veya örnek yöntemi yerine giriş noktası olarak statik bir yöntem yapma tasarım kararının gerekçesini öğrenmek isterim .
Konrad Rudolph

1
@KonradRudolph, dil ve JVM spesifikasyon tasarımı ile ilgili sorular için, belki de Oracle'ın orijinal kaynağına başvurmayı deneyebilir ve herhangi bir olumlu geri bildirim alıp alamayacağınızı görebilirsiniz.
yorkw

2
Genel olarak, bir yöntem sonuç hesaplaması sadece parametrelerine bağlı olduğunda, böylece nesne örneği iç durumuna bağlı olmadığında, statik olabilir. Ve kod bakımı / yeniden kullanılabilirliği için statik olarak ayarlanması önerilir. Yöntem mainstatik değilse, sınıf örneği durumunun bilinmesi gerektiği ve ilk olarak hangi kurucunun kullanılacağı gibi tanımlanması çok daha karmaşık olduğu anlamına gelir.
Yves Martin

@KonradRudolph İlginç bir şekilde, Oak (Java'nın selefi) zaten benzer bir prototipe sahip ana yönteme ihtiyaç duyuyordu: public static void main(String arguments[])- Referans: Oak 0.2 Spec .
assylias

2
@Yves O yapabilirsiniz olmak. Başka bir tasarımın mantıklı olması gerekmez. Burada yorumlarda bazı iyi argümanlar duydum ama hala bir süreçtir çok bir iş parçacığı (Bu gibi etkili bir olduğunu düşünüyorum olduğunu ) ve Java bir iplik genellikle bir örneği olarak temsil edilir Runnable. Tüm süreci aynı şekilde temsil etmek (yani Runnable.Rungiriş noktası olmak) Java'da kesinlikle mantıklıdır. Tabii ki, Runnablekendisi Java'nın anonim yöntemlere sahip olmamasından kaynaklanan bir tasarım hatasıdır (henüz). Ama orada olduğu için…
Konrad Rudolph

36

Basitçe static, uygulama giriş noktası olarak gerekli olmayacağını varsayalım .

Bir uygulama sınıfı şu şekilde görünecektir:

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

Yapıcı kodu ile mainyöntem arasındaki ayrım gereklidir çünkü OO konuşmasında bir kurucu yalnızca bir örneğin doğru şekilde başlatıldığından emin olmalıdır. Başlatma işleminden sonra, örnek amaçlanan "hizmet" için kullanılabilir. Uygulama kodunun tamamını kurucuya koymak bunu bozacaktır.

Dolayısıyla bu yaklaşım , başvuru üzerine üç farklı sözleşmeyi zorlar :

  • Orada gereken bir varsayılan yapıcı ol. Aksi takdirde, JVM hangi kurucuyu arayacağını ve hangi parametrelerin sağlanması gerektiğini bilemez.
  • Orada gereken bir olmak mainmetot 1 . Tamam, bu şaşırtıcı değil.
  • Sınıf olmamalıdır olmak abstract. Aksi takdirde JVM bunu başlatamadı.

staticÖte yandan yaklaşım sadece gerektirir bir sözleşme:

  • Bir mainyöntem 1 olmalıdır .

Burada ne abstractçok ne de yapıcıların önemi yoktur.

Java basit bir dil olacak şekilde tasarlanmıştır beri kullanıcı için aynı zamanda uygulama giriş noktası kullanarak basit bir şekilde dizayn edildiğini şaşırtıcı değildir biri sözleşme olup kullanarak karmaşık bir şekilde üç bağımsız ve kırılgan sözleşmeleri.

Lütfen dikkat: Bu argüman JVM veya JRE içindeki basitlik ile ilgili değildir . Bu argüman kullanıcı için basitlikle ilgilidir .


1 Burada imzanın tamamı tek bir sözleşme olarak sayılır.


1
Aslında şartlar daha karmaşıktır: Bir olmalı mainolan yöntem public, staticve imzası vardır void main(String[]). Yöntem bir örnek yöntem olsaydı, JRE'nin biraz daha fazla işi olacağını, ancak işin türünün aynı olacağını ve karmaşıklığın önemli ölçüde daha yüksek olmayacağını kabul ediyorum (önceki cevabın yorumlarındaki tartışmalara bakın). Bu farkın, özellikle bir örnek yönteminin çözümlenmesi için gerekli yöntemler mevcut olduğundan ve kolayca kullanılabilir olduğundan, giriş noktasını statik hale getirme kararını açıkladığına inanmıyorum.
Konrad Rudolph

3
@KonradRudolph: Demek istediğim, JRE'nin yapması gereken iş hakkında değil. Demek istediğim, dilin her kullanıcısını gerektiğinde daha fazla sözleşme izlemeye zorlamak . Bu anlamda bir static public main(String[])yöntem bir imza ve dolayısıyla bir sözleşmedir. Aksi takdirde üç bağımsız sözleşme takip edilmelidir.
AH

1
Ah. Yine de bunun herhangi bir fark yarattığına katılmıyorum. Giriş noktası sınıfları iyi uygulanabilir Runnable. Açıkçası, Java geliştiricilerin bu sözleşmeyi her zaman takip etmelerini beklemektedir, neden uygulama giriş noktası için çok fazla olması gerekir? Bu hiç mantıklı değil.
Konrad Rudolph

3
@KonradRudolph: Bir çelişki yok: Bir durumda sistem kullanıcı üzerinde üç sözleşmeyi zorlardı. Şüpheli, derleyici aracılığıyla kontrol edilemeyen ve kullanıcının bakış açısından bağımsız olan sözleşmeler. Her zamanki Threadve Runnabledurumda hiçbir şey kullanıcıdan gizlenmez, neler olduğunu açıkça görebilir ve yalnızca kendisine uygun sözleşmeleri uygulama değişikliğine sahiptir - sistemde değil, kontrolde.
AH

2
Buradaki en iyi cevap bu. Birçok kullanıcının yalnızca sayfadaki en iyi 2 veya 3 cevabı okuyacağı utanç verici; ve bunun yakın zamanda oraya ulaşması pek olası değildir. Bir kurucunun SADECE başlatma için önemli bir noktadan bahseder ve bu nedenle kurucunun tüm uygulamayı çalıştığı bir tarzda kodlama yapmak mantıklı değildir.
Dawood ibn Kareem

14

Değilse, birden fazla varsa hangi kurucu kullanılmalıdır?

Java Dil Belirtimi'nde bulunan Java programlarının başlatılması ve yürütülmesi hakkında daha fazla bilgi vardır .


12

Ana yöntem çağrılmadan önce hiçbir nesne somutlaştırılmaz. Statik anahtar kelimeye sahip olmak, yöntemin önce herhangi bir nesne oluşturmadan çağrılabileceği anlamına gelir.


Yanlış. Ya da en azından çok belirsiz. public class Main {statik Nesne nesnesi = yeni Nesne () {{System.out.println ("nesne oluşturuldu"); }}; public static void main (Dize [] args) {System.out.println ("ana"); }}
eljenso

Adil yorum. Teknik olarak, Main yöntemi çağrılmadan önce, ana yöntemi içeren sınıfın başlatılmadığını söylemeliydim.
BlackWasp

12

Aksi takdirde, yürütülecek nesnenin bir örneğine ihtiyaç duyacaktır. Ancak, ilk önce nesneyi oluşturmadan sıfırdan çağrılmalıdır, çünkü genellikle bu argümanları / program parametrelerini kullanarak argümanları ayrıştırmak ve nesneyi oluşturmak genellikle main () işlevinin (bootstrap) görevidir.


10

Bunları çok daha basit bir şekilde açıklayayım:

public static void main(String args[])

Appletler hariç tüm Java uygulamaları yürütülmeye başlar main().

Anahtar kelime public, üyenin sınıfın dışından çağrılmasını sağlayan bir erişim değiştiricisidir.

statickullanılır, çünkü o main()sınıfın belirli bir örneğini başlatmaya gerek kalmadan çağrılmasına izin verir .

voidmain()herhangi bir değer döndürmediğini gösterir .


9

Anlamı ne public static void main(String args[])?

  1. public JVM (Java Sanal Makinesi) gibi herkesin erişebileceği / çağırabileceği anlamına gelen bir erişim belirleyicisidir.
  2. staticmain()sınıfın bir nesnesi oluşturulmadan çağrılmasına izin verir . Bu main()gereklidir, çünkü herhangi bir nesne yapılmadan önce JVM tarafından çağrılır. Statik olduğu için doğrudan sınıf aracılığıyla çağrılabilir.

    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 */
        }
    }

    Benzer şekilde, kullanıcı tanımlı yöntemler için bir süre statik kullanırız, böylece nesne yapmamız gerekmez.

  3. voidmain()bildirilen yöntemin bir değer döndürmediğini belirtir .

  4. String[] argsmain()yöntemdeki tek parametreyi belirtir .

    args- sınıf tipi bir nesne dizisi içeren bir parametre String.


6

Çeşitli türlerde küçük uygulamalar, midletler, servisler ve fasulye yapılır ve daha sonra üzerlerinde yaşam döngüsü yöntemleri çağrılır. Main'i çağırmak, ana sınıfa yapılan her şeydir, bu nedenle birden çok kez çağrılan bir nesnede bir durumun tutulmasına gerek yoktur. Ana öğeyi oluşturmak için sınıfı kullanma yoluna girecek başka bir sınıfa (büyük bir fikir olmasa da) sabitlemek oldukça normaldir.


5

Bu sadece bir kongre, ama muhtemelen alternatiften daha uygun. Statik bir main ile, bir Java programını çağırmak için bilmeniz gereken tek şey bir sınıfın adı ve konumudur. Statik olmasaydı, o sınıfı nasıl somutlaştıracağınızı veya sınıfın boş bir kurucuya sahip olmasını da bilmeniz gerekir.


Bu bir kongre değil; dil spesifikasyonunun bir parçası; çalışma zamanı, statik ana yöntemi olmayan bir sınıfı geçerli giriş noktası olarak tanımaz.
Rob

2
Söz konusu dil spesifikasyonunun kendisi. Java tasarımcılarının statik bir ana bilgisayar istemeyi seçmeleri için gerçek bir gereklilik yoktur. Bununla birlikte, Logan'ın açıkladığı gibi, alternatifler daha karmaşıktır.
David Arno

@DavidArno Sözleşmenin dil şartnamesine uygun olduğunu söylemek daha mantıklı olacaktır.
Lorne Marquis

5

Ana yöntem statik olmazsa, programın dışından ana sınıfınızın bir nesnesini oluşturmanız gerekir. Bunu nasıl yapmak istersiniz?


5

Java Sanal Makinesi'ni (JVM) şu javakomutla yürüttüğünüzde ,

java ClassName argument1 argument2 ...

Uygulamanızı yürüttüğünüzde, sınıf adını yukarıdaki gibi java komutuna bağımsız değişken olarak belirtirsiniz

JVM belirttiğiniz sınıfın ana yöntemini çağırmaya çalışır

—Bu noktada, sınıfın hiçbir nesnesi oluşturulmamıştır.

Bir sınıf oluşturmak için ana JVM mainstatik olarak bildirilmesi .allowsinvokewithoutinstance

komuta geri dönelim

ClassNameBir olduğu command-line argumentyürütmek için hangi sınıf söyler JVM. SınıfAdından sonra, JVM'nin list of Stringsuygulamanıza ileteceği komut satırı bağımsız değişkenleri olarak da (boşluklarla ayrılmış) belirtebilirsiniz . -Bu argüman, uygulamayı çalıştırmak için seçenekleri (örneğin, bir dosya adı) belirtmek için kullanılabilir.String[] args başlıca içinde

Kaynaklar: Java ™ Nasıl Programlanır (Erken Nesneler), Onuncu Baskı


4

Son zamanlarda, benzer bir soru Programmers'da yayınlanmıştır.

TL; kabul edilen cevabın DR kısmı,

Java'da, sebebi public static void main(String[] args)olmasıdır

  1. Gosling istedi
  2. C dilinde deneyimli biri tarafından yazılan kod (Java'da değil)
  3. birileri tarafından yürütülecek çalışan için kullanılan PostScript üzerinde News

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

 
C # için, akıl yürütme, tabiri caizse , geçici olarak benzerdir . Dil tasarımcıları, program giriş noktası sözdizimini Java'dan gelen programcılar için tanıdık tuttu . C # mimarı Anders Hejlsberg'in söylediği gibi ,

... C # ile yaklaşımımız sadece Java programcılarına alternatif sunmak ...

...


3

Ben 'statik' anahtar kelime ana yöntemi bir sınıf yöntemi yapar ve sınıf yöntemleri sadece bir kopyası var ve herkes tarafından paylaşılabilir ve ayrıca, başvuru için bir nesne gerektirmez düşünüyorum. Böylece sürücü sınıfı derlendiğinde ana yöntem çağrılabilir. (Ben sadece java alfabe seviyesindeyim, yanılıyorsam özür dilerim)


Tüm yöntemlerin yalnızca bir kopyası vardır.
Lorne Marquis

3

main () statiktir; uygulamanın yaşam döngüsünün bu noktasında, henüz başlatılan hiçbir nesne bulunmadığından, uygulama yığını doğası gereği yordamsaldır.

Temiz bir sayfa. Başvurunuz bu noktada, herhangi bir nesne bildirilmeden bile çalışıyor (unutmayın, prosedürel AND OO kodlama modelleri vardır). Geliştirici olarak, nesnelerinizin örneklerini oluşturarak ve içinde derlenen koda bağlı olarak uygulamayı nesne tabanlı bir çözüme dönüştürürsünüz.

Nesneye yönelik milyonlarca bariz nedenden ötürü mükemmeldir. Ancak, çoğu VB geliştiricisinin kodlarında "git" gibi anahtar kelimeleri düzenli olarak kullandığı günler geride kaldı. "goto", VB'de OO muadili: yöntem çağırma ile değiştirilen yordamsal bir komuttur.

Statik giriş noktasına (ana) saf özgürlük olarak da bakabilirsiniz. Java bir nesneyi örnekleyecek kadar farklı olsaydı ve sadece bu örneği size çalışırken sunsaydı, yordamsal bir uygulama yazmak için başka seçeneğiniz olmazdı. Java için kulağa geldiği kadar düşünülemez olduğu gibi, prosedürel yaklaşımlar gerektiren birçok senaryo olabilir.

Bu muhtemelen çok belirsiz bir cevaptır. Unutmayın, "sınıf" yalnızca ilişkili kodların bir derlemesidir. "Örnek", o sınıfın izole edilmiş, yaşayan ve nefes alan otonom bir neslidir.


7
Bu yanlış. Çok sayıda nesneye mainulaşılmadan önce somutlaştırılır . Ve main içeren sınıfa statik bir yapıcı eklerseniz, bu da daha önce mainaynı şekilde yürütülür .
Konrad Rudolph

2

Bu sadece bir kongre. JVM, konvansiyon olsaydı, kesinlikle statik olmayan ana yöntemlerle başa çıkabilirdi. Sonuçta, sınıfınızda statik bir başlatıcı tanımlayabilir ve ana () yönteminize ulaşmadan önce bir milyon nesne başlatabilirsiniz.


2

Protoype public static void main(String[])tanımlanan bir gelenektir JLS :

Main yöntemi genel, statik ve geçersiz olarak bildirilmelidir. Bildirilen türü Dize dizisi olan resmi bir parametre (§8.4.1) belirtmelidir.

JVM şartnamesinde 5.2. Sanal Makine Devreye Alma:

Java sanal makinesi, bootstrap sınıf yükleyicisini kullanarak uygulamaya bağlı olarak belirtilen bir başlangıç ​​sınıfı oluşturarak başlar (§5.3.1). Java sanal makinesi daha sonra ilk sınıfı bağlar, başlatır ve void main (String []) genel sınıf yöntemini çağırır . Bu yöntemin çağrılması, daha fazla yürütmeyi yönlendirir. Ana yöntemi oluşturan Java sanal makine talimatlarının yürütülmesi, ek sınıfların ve arabirimlerin bağlanmasına (ve sonuç olarak oluşturulmasına) ve ayrıca ek yöntemlerin çağrılmasına neden olabilir.

Komik bir şey, JVM spesifikasyonunda ana yöntemin statik olması gerektiğinden bahsetmiyor. Ancak spesifikasyon ayrıca Java sanal makinesinin daha önce 2 adım gerçekleştirdiğini söylüyor:

Bir sınıfın veya arabirimin başlatılması, sınıfının veya arabirim başlatma yönteminin yürütülmesinden oluşur.

İçinde 2.9. Özel Yöntemler :

Bir sınıf veya arayüz başlatma yöntemi tanımlanmıştır:

Bir sınıf veya arabirim en fazla bir sınıf veya arabirim başlatma yöntemine sahiptir ve bu yöntem çağrılarak başlatılır (§5.5). Bir sınıfın veya arabirimin başlatma yönteminin özel adı vardır <clinit>, bağımsız değişken almaz ve geçersizdir.

Ve bir sınıf veya arayüz başlatma usulü , bir farklı , örneğin başlatma yöntemi şu şekilde tanımlanır:

Java sanal makinesi düzeyinde, Java programlama dilinde (JLS §8.8) yazılmış her kurucu, özel ada sahip bir örnek başlatma yöntemi olarak görünür <init>.

Böylece JVM , aslında bir kurucu olan bir örnek başlatma yöntemini değil, bir sınıf veya arabirim başlatma yöntemini başlatır . Bu nedenle, ana yöntemin JVM spesifikasyonunda statik olması gerektiğinden bahsetmelerine gerek yoktur, çünkü ana yöntemi çağırmadan önce hiçbir örneğin oluşturulmadığı anlamına gelir.


2

publicAnahtar kelime programcı sınıfı üyelerinin görünürlüğünü kontrol sağlayan bir erişim değiştirici vardır. Bir sınıf üyesinden önce geldiğinde public, o üyeye bildirildiği sınıfın dışındaki kodla erişilebilir.

Karşıt publicIS privatesınıfının kodu tanımlanır dış tarafından kullanılan bir üyeyi engeller.

Bu durumda, program başlatıldığında sınıfının dışındaki kod tarafından çağrılması gerektiğinden, bu main()şekilde bildirilmelidir public.

Anahtar kelime , sınıfın belirli bir örneğini başlatmaya gerek kalmadan çağrılmaya staticizin verir main(). main()Herhangi bir nesne yapılmadan önce Java yorumlayıcısı tarafından çağrıldığından bu gereklidir .

Anahtar kelime voidderleyiciye main()bir değer döndürmediğini söyler .


1

Herhangi bir uygulamanın gerçek giriş noktası statik bir yöntemdir. Java dili "giriş noktası" olarak bir örnek yöntemini destekliyorsa, çalışma zamanının bunu, örnek yöntemini çağırarak nesnenin bir örneğini oluşturan statik bir yöntem olarak dahili olarak uygulaması gerekir.

Bu yoldan çıkarken, aşağıdaki üç seçenekten birini seçmek için mantığı inceleyeceğim:

  1. Bir static void main()bugün gördüğümüz şekilde.
  2. void main()Yeni oluşturulmuş bir nesneye çağrılan bir örnek yöntemi .
  3. Giriş türü olarak bir tür yapıcısı kullanıldığında (örneğin, giriş sınıfı çağrıldıysa Program, yürütme etkili bir şekilde oluşurdu new Program()).

Yıkmak:

static void main()

  1. Çevreleyen sınıfın statik yapıcısını çağırır.
  2. Statik yöntemi çağırır main().

void main()

  1. Çevreleyen sınıfın statik yapıcısını çağırır.
  2. Etkin bir şekilde çağırarak ek sınıfın bir örneğini oluşturur new ClassName().
  3. İnstance yöntemini çağırır main().

new ClassName()

  1. Çevreleyen sınıfın statik yapıcısını çağırır.
  2. Sınıfın bir örneğini oluşturur (daha sonra onunla hiçbir şey yapmaz ve sadece geri döner).

Gerekçe:

Bunun için ters sırayla gideceğim.

Java'nın tasarım hedeflerinden birinin iyi nesne yönelimli programlama uygulamalarını vurgulamak (mümkünse gerektirmek) olduğunu unutmayın. Bu bağlamda, bir nesnenin yapıcısı nesneyi başlatır , ancak nesnenin davranışından sorumlu olmamalıdır. Bu nedenle, bir giriş noktası veren bir özellik new ClassName(), her uygulamada bir "ideal" kurucu tasarımına bir istisna zorlayarak yeni Java geliştiricileri için durumu karıştırır.

Yaparak main()bir örnek yöntemi, yukarıda sorun kesinlikle çözülür. Ancak, belirtimin, giriş sınıfının yapıcısının imzasını ve main()yöntemin imzasını listelemesini gerektirerek karmaşıklık yaratır .

Özetle, a belirtmekstatic void main() , davranışı yöntemlere yerleştirme ilkesine bağlı kalarak en az karmaşıklığa sahip bir belirtim oluşturur . main()Kendisinin bir sınıf örneği oluşturan ve bir örnek yöntemi çağıran bir yöntemi uygulamanın ne kadar basit olduğu göz önüne alındığında, bir örnek yöntemi olarak belirtmenin gerçek bir avantajı yoktur main().


1
Bu sadece soruya yalvarıyor. Java, arama yapmadan önce zaten ağır kaldırma yapan bir uygulama yükleyiciye ihtiyaç duyar main. mainYeni başlayanlar için çok karmaşık olmanın mantığı inanılmaz görünüyor. Aslında, statik mainolan çok başlayanlar için kafa karıştırıcı, bir kurucu daha çok olacağını sanmıyorum. “Yapıcı nesnenin davranışından sorumlu olmamalı” diyorsunuz. Kulağa ilginç geliyor ama katılıyorum. Neden olmasın? Bunu engelleyen nedir?
Konrad Rudolph

1

static - JVM, ana yönteme çağrı yaptığında, çağrılmakta olan sınıf için var olan bir nesne olmadığından, sınıftan çağırmaya izin vermek için statik bir yönteme sahip olması gerekir.


1

JVM, nesneler somutlaştırılmadan önce ana yöntemi çağırıp çağırmadığını bilmiyorum ... Ama main () yönteminin statik olmasının çok daha güçlü bir nedeni var ... JVM sınıfın ana yöntemini çağırdığında ( , Kişi). " Person.main () " ile çağırır . Görüyorsunuz, JVM onu sınıf adına göre çağırıyor. Bu nedenle, main () yönteminin JVM tarafından erişilebilmesi için statik ve genel olması gerekiyordu.

Umarım yardımcı olmuştur. Eğer öyleyse, yorum yaparak bana bildirin.


0

Statik yöntemler herhangi bir nesne gerektirmez. Doğrudan çalışır, böylece ana doğrudan çalışır.


0

Ana yöntemdeki statik anahtar sözcüğü kullanılır, çünkü ana yöntemde yer alan herhangi bir örnekleme yoktur. Ancak nesne çağrılma yerine inşa edilir, sonuç olarak ana yöntemde statik anahtar kelimesini kullanırız. Jvm bağlamında, sınıf içine yüklendiğinde bellek oluşturulur ve bu bellekte tüm statik üyeler bulunur. şimdi ana statik yaparsak bellekte olacaktır ve jvm (class.main (..)) için erişilebilir olabilir, böylece yığın oluşturmaya bile gerek kalmadan ana yöntemi çağırabiliriz.


0

Burada gördüğümüz gibi sadece bir kongre:

Yöntem genel ve statik olarak bildirilmeli , herhangi bir değer döndürmemeli ve bir String dizisini parametre olarak kabul etmelidir. Varsayılan olarak, seçenek olmayan ilk bağımsız değişken çağrılacak sınıfın adıdır. Tam nitelikli bir sınıf adı kullanılmalıdır. -Jar seçeneği belirtilirse, ilk seçenek olmayan bağımsız değişken, uygulama için sınıf ve kaynak dosyaları içeren bir JAR arşivinin adıdır ve başlangıç ​​sınıfı Main-Class manifest üstbilgisi ile gösterilir.

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


Dilin kuralı demek istiyorsun.
Lorne Marquis

0

Genel statik geçersiz anahtar kelimeler, Java sanal makine (JVM) yorumlayıcısının, sınıfın bir örneğini (statik) oluşturmadan programı (genel) başlatmak için programın ana yöntemini çağırabileceği ve programın Java VM yorumlayıcısına veri döndürmediği anlamına gelir. (geçersiz) sona erdiğinde.

Kaynak: Temel Bilgiler, Bölüm 1, Ders 2: Bina Uygulamaları


0

Temel olarak bu VERİ ÜYELERİ ve ÜYE FONKSİYONLARINI bir nesne ile ilgili herhangi bir görev gerçekleştirmeyen STATİK yaparız. Ve ana yöntem durumunda, bunu bir STATIC olarak yapıyoruz çünkü ana yöntem her zaman bir nesne oluştursun ya da yaratmasak da çalıştığı için nesne ile ilgisi yoktur.


0

Java'da statik olarak bildirilen herhangi bir yöntem sınıfın kendisine aittir. Yine, belirli bir sınıfın statik yöntemine yalnızca aşağıdaki sınıfa atıfta bulunarak erişilebilir.Class_name.method_name();

Bu nedenle, statik bir yönteme erişmeden önce bir sınıfın başlatılması gerekmez.

Böylece main () yöntemi, staticbu sınıfın bir nesnesini oluşturmadan erişilebilecek şekilde bildirilir .

Programı, ana yöntemin bulunduğu sınıfın adıyla kaydettiğimizden (veya programın yürütülmeye başlaması gereken yerden main()(yöntemsiz) () (Advanced Level) olmayan sınıflar için geçerlidir . Yani yukarıda belirtilen yolla:

Class_name.method_name();

ana yönteme erişilebilir.

Kısacası, program derlendiğinde , belirtilen sınıfta (yani programın adıyla) gibi argümanlara main()sahip yöntemi arar ve başlangıçta bu sınıfı somutlaştırmak için bir kapsamı olmadığından, main () yöntemi statik olarak bildirilir.Stringmain(String args[])


Program yürütüldüğünde olur, derlenmez.
Lorne Marquis

0

Gönderen java.sun.com (sitede daha fazla bilgi var):

Ana yöntem, Java VM yorumlayıcısına, önce kontrol sınıfının bir örneğini oluşturmadan sınıfa başlamanın bir yolunu vermek için statiktir. Kontrol sınıfının örnekleri, program başladıktan sonra ana yöntemde oluşturulur.

Anladığım kadarıyla, ana yöntem, herhangi bir statik yöntem gibi, ilişkili sınıfın bir örneği oluşturmadan çağrılabilir ve programda herhangi bir şeyden önce çalışmasına izin verilebilir. Statik olmasaydı, bir nesneyi çağırmadan önce başlatmanız gerekir - bu bir 'tavuk ve yumurta' sorunu yaratır, çünkü ana yöntem genellikle programın başında nesneleri başlatmak için kullandığınız yöntemdir.


Ama yok değil “programında her şeyden önce” çalıştırın. Tüm argüman bir yanılgıdır ve dahası, bu ilk cevap, hatta ikinci ya da üçüncü değildir.
Konrad Rudolph

Cevabım başkalarının söylediklerini tekrarladığı için üzgünüm; Sadece en iyi şekilde ve çevrimiçi ortamda neler bulabileceğime cevap verdim. Baktığım sonuçlardan, ana yöntemin neden statik olduğu konusunda başka bir neden yok; bir yerde derin bir gizli olmadıkça belki de tek cevap budur. Java anlayışım oldukça basit, ama yukarıdaki sebebi duydum (profesörlerden, ders kitaplarından, vb.) Ve başka hiçbir şey.
Jesse M

@Jesse M Yorumunuz yalnızca önce diğer cevapları okumayı düşünmediyseniz mantıklıdır. Bu arada yapılması gereken çok şey değil. Kendinizden bahsettiğiniz gibi, anlayışınız oldukça basittir, bu nedenle başka bir kişinin soruyu daha yetkin bir şekilde cevaplaması çok olasıdır. Ve cevabınızın daha iyi görünmesi için yorumunuz rasyonelleştirme gibi görünüyor. Bu, iddia ettiğiniz şeyi düşünen Java ders kitaplarına ve profesörlere sahip olmanızın olağanüstü bir iddiası ve açıkçası yaptıklarıma inanmıyorum. (Referans var mı?)
LeoR

1
@KonradRudolph En iyi yorumlar oldukça makul görünüyor. main (), programa giriş noktası olarak kullanılır ve Java web sitesinde, C / C ++ 'nın main () işlevine nasıl sahip olduğuna benzer olması gerektiğini söyleyen birkaç referans vardır. Java tamamen Nesneler olduğundan, nesne somutlaştırmasını önlemek için statik olmalıdır. Statik olması, çalışma zamanında JVM'ye yüklenmesini ve çalıştırılabilir olmasını sağlar. Sadece önceki cevapları üzüyorum, ama tatmin edici bir cevap olarak neyi düşüneceğinizi merak ediyorum. Bence alacağınız en iyi şey "Bunu böyle istediler". Java'nın oluşturulduğu tarihi unutmayın.
trevor-e

1
@Jesse Spot-on. Sadece bir konuyla ilgili olması tamamen mümkündür (umarım olmasa da, bu sıkıcı bir cevap olacaktır). Bu sorudaki asıl ilgim, “çalışan uygulama” nesnesini temsil etmek için uygun bir örnek kullanmanın ve giriş noktasının bu sınıfın bir yöntemi (veya kurucu) olması, Java'dan bu yana çok daha belirgin bir tasarım olacağını düşündüm. get-go dan odaklı objesi olarak tasarlanması ve görünüşte benzer nesneler (dişler aracılığıyla beri edildi RunnableJava) yapmak bu tasarımı kullanabilirsiniz. Neden buradaki (açık) istisna?
Konrad Rudolph
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.