Java'daki statik kurucuları tam olarak anlamadım. İzin verilirse, neden izin verilir? Hangi senaryolarda kullanırsınız? Hangi amaca hizmet ederdi? Birisi bana basit bir örnek verebilir mi lütfen?
Java'daki statik kurucuları tam olarak anlamadım. İzin verilirse, neden izin verilir? Hangi senaryolarda kullanırsınız? Hangi amaca hizmet ederdi? Birisi bana basit bir örnek verebilir mi lütfen?
Yanıtlar:
Bir yapıcı, tanımı gereği, çünkü Açıkçası, Java statik kurucular yok olmak statik. Ne demek istediğinize "statik başlatma bloğu" denir. Bir kurucu, bir nesne inşa ettiğinizi ima eder. Bir sınıfın yapıcısı olamaz çünkü sınıf kendisinin bir örneği değildir. Bu sadece bir sınıf. Sınıfı "oluşturan" şeye derleyici (veya "yapılar" ile kastedilene bağlı olarak sanal makine) denir ve başka bir kod içinde kod oluşturmaya başlarsanız, kod oluşturma sürecine girersiniz. tamamen farklı bir canavar.
Tüm nit toplama bir yana, bir sınıf için karmaşık statik (veya sınıf düzeyi) alanları başlatmak için bir statik başlatma bloğu kullanılır. Genellikle bunlar bir satırda başlatılamayacak veya başka bir nesnenin (statik bloğun uygulandığı sınıfta olabilir veya olmayabilir) başlatılmasını gerektiren şeyleri başlatmak için kullanılır.
Temel olarak, onları "Hey, A değişkenini İLK bu değere ayarlayın, sonra, bittiğinde, A'yı B'yi başlatmak için kullanın." Java, standart alan başlatmanın bir kurucu ya da yöntem içinde ya da bir kurucu ya da yöntemin çağrısıyla yapılmasını gerektirdiğinden (değişmezse), bunlar karmaşık, statik nesneleri başlatmak için uygun bir yöntem olabilir.
Statik başlatma bloklarına çok sık ihtiyaç duyulmaz ve gerçek bir kullanımları olmadıkça genellikle kaçınılmalıdır . Beni yanlış anlamayın, Java'daki yerleri var, ancak diğer birçok şey gibi (break, return, switch ve goto ifadeleri gibi) kolayca aşırı kullanılabilirler, bu da okunabilirliklerini ve kodun sürdürülebilirliğini azaltır -baz kullanılır.
Kullanılan statik başlatma bloğunun kısa bir örneği aşağıdakiler olacaktır ( burada bulunan statik başlatma bloklarının mükemmel açıklamasına göre ):
Kod:
public class StaticExample{
static {
System.out.println("This is first static block");
}
public StaticExample(){
System.out.println("This is constructor");
}
public static String staticString = "Static Variable";
static {
System.out.println("This is second static block and "
+ staticString);
}
public static void main(String[] args){
StaticExample statEx = new StaticExample();
StaticExample.staticMethod2();
}
static {
staticMethod();
System.out.println("This is third static block");
}
public static void staticMethod() {
System.out.println("This is static method");
}
public static void staticMethod2() {
System.out.println("This is static method2");
}
}
Çıktı:
This is first static block
This is second static block and Static Variable
This is static method
This is third static block
This is constructor
This is static method2
Statik blokların yararlı olabileceği durumlarda listeledikleri bazı örnekler:
Statik blokları KULLANMAMANIN bazı nedenleri (diğer durumlarda):
thisÖrnek olmadığı için anahtar kelimeyi kullanamazsınız .Şunu not etmeliyim: Bazı diller (C # gibi) statik olan "yapıcılar" için sözdizimine sahip olsa da, bu "yapıcılar" statik başlatma bloklarının Java ile yaptığı gibi çalışır ve birçok kişi tarafından (kendim dahil) OOP yapıcısının temel konsepti göz önüne alındığında, dilde yanlış adlandırmalar .
atamaktan daha zor olan alanları başlatmak için kullanılır:
public class Example{
public final static Map<String, String> preFilledField;
static{
Map<String, String> tmp = new HashMap<>();
//fill map
preFilledField = Collections.unmodifiableMap(tmp);
}
}
başlatma sırasında bir haritayı doldurmak mümkün değildir (anonim alt sınıf kesmek kullanmazsanız), bu ilk kullanımdan önce doldurulduğunu garanti etmenin en iyi yoludur.
Bunu başlatırken işaretli istisnaları yakalamak için de yapabilirsiniz
Gurgadurgen'ın cevabı muhtemelen aradığınız şeydir, ancak biri "statik kurucu" istediğinde bazen ihmal edilen birkaç nokta daha ekleyeceğim.
Sınıfınızın bir örneğini oluşturan statik bir yöntem istiyorsanız, yalnızca sınıfın yapıcısını çağıran statik bir yöntem oluşturabilirsiniz.
public class Example
{
/** Static method to create an instance. */
public static Example build()
{ return new Example() ; }
/** A field of each instance. */
private String stuff ;
/** The class's actual constructor. */
public Example()
{ stuff = new String() ; }
public String getStuff()
{ return this.stuff ; }
/**
* Mutator for "stuff" property. By convention this returns "void"
* but you might want to return the object itself, to support the
* sort of chained invocations that are becoming trendy now. You'll
* see the stylistic benefits of chaining later in this example.
*/
public Example setStuff( String newStuff )
{
this.stuff = newStuff ;
return this ;
}
}
public class ExampleTest
{
public static void main( String[] args )
{
// The usual instance model.
Example first = new Example() ;
System.out.println( first.setStuff("stuff").getStuff() ) ;
// Using your static method to construct an instance:
Example second = Example.build() ;
System.out.println( second.setStuff("more stuff").getStuff() ) ;
// Chaining all the invocations at once:
System.out.println( Example.build().setStuff("even more stuff").getStuff() ) ;
}
}
Bu çıktıyı üretir:
stuff
more stuff
even more stuff
Bir örnek oluşturmak için statik bir yöntem oluşturmanın diğer nedeni , herhangi bir zamanda sınıfınızın tam olarak bir örneğinin var olmasını sağlamak istediğiniz durumdur ; buna singleton denir . Kural olarak, böyle bir sınıf "singleton" olarak değerlendirilen tek ve tek örneğigetInstance() almak için çağrılan statik bir yöntem sağlayacaktır .
public class SingletonExample extends Example
{
// Note: This extends my previous example, which has a "stuff"
// property, and a trivial constructor.
/** The singleton instance, statically initialized as null. */
private static SingletonExample singleton = null ;
/**
* The static accessor for the singleton. If no instance exists,
* then it will be created; otherwise, the one that already exists
* will be returned.
*/
public static SingletonExample getInstance()
{
if( singleton == null )
singleton = new SingletonExample() ;
return singleton ;
}
}
public class SingletonExampleTest
{
public static void main( String[] args )
{
System.out.println( SingletonExample.getInstance().setStuff("stuff").getStuff() ) ;
// You could still create instances of this class normally if you want to.
SingletonExample otherstuff = new SingletonExample() ;
otherstuff.setStuff("other stuff") ;
// But watch what happens to this.
System.out.println( SingletonExample.getInstance().getStuff() ) ;
System.out.println( otherstuff.getStuff() ) ;
// Now we show what happens when you start modifying the singleton.
SingletonExample theoneandonly = SingletonExample.getInstance() ;
theoneandonly.setStuff("changed stuff") ;
System.out.println( SingletonExample.getInstance().getStuff() ) ;
}
}
Bu aşağıdakileri üretir.
stuff
stuff
other stuff
changed stuff
Singletona bir referans depolayarak ve daha sonra değiştirerek, bir sonraki çağrı getInstance()o değiştirilmiş singletonu alır.
Teklitonları uygulamanız için genel değişkenler oluşturmaya başlamanın bir yolu olarak kullanmak caziptir. Bazı bağlamlarda bu yararlı olabilir, ama aynı zamanda başınızı belaya sokabilir. Özellikle singleton örneklerinin kaybolabileceği bir Android uygulaması geliştirirken ilginç bir hata ile karşılaştım. Bir aktiviteden diğerine atlamak bazen JVM'yi önceki bir sınıf yükleyici tarafından statik olarak depolanan singleton hakkında bilgi sahibi olmayan yeni bir "sınıf yükleyici" kullanmaya yönlendirebilir.
Bir "statik kurucu" kavramını yanlış isim olarak gören birçok kişi olduğunu anlasam da, bunun böyle olduğuna inanmıyorum. Sorun, hem sınıfları hem de örnek nesnelerini oluşturma sürecindedir . Diğer konularda sınıfın inşasının derleyicinin işi olduğu belirtilmiştir. Java'da bile, bu sadece yarı doğrudur.
Derleyici her sınıf tanımı için bir yapı iskelesi oluşturur. İskele, sınıf ve inşaat sırasında bunlarda hangi örneklerin olması gerektiği hakkında meta veriler içerir. Bir sınıf, sabit bir ilkel değer atanmış bir alanı tanımlarsa, bu değer derleyici tarafından iskeleye dahil edilir. Atanan diğer değer türleri için, derleyici, iskele'yi uygun değerlerle güncelleyen birinci sınıf örneğinin oluşturulmasından önce 1 kez çalıştırılacak bir başlatma yordamı oluşturur. Bu güncelleştirme derleyici tarafından yapılamaz.
İskele için yapılan bu bir kerelik güncelleme genellikle örnek yapıcıların düzgün çalışması için kritik bir önkoşul olduğundan, aynı zamanda bir tür kurucu olarak adlandırmak da mantıklıdır. Bu nedenle konsepti destekleyen ortak OO dillerinde buna statik kurucu denir. Java'daki statik başlatma bloklarının arkasındaki kavram, bir Java programcısının hem sistem hem de uygulama agnostik olması gerektiği fikrine uymak için semantik bir değişiklikten biraz daha fazlasıdır.
Diğer cevapların söylediği gibi, bir nesneyi oluşturan statik yöntemler yazabilirsiniz. Bu, Java'da (ve diğer birçok dilde. Parametrelerin türleri ve sırası ile oynayabilirsiniz, ancak bu belirsiz ve kırılgan koda yol açabilir.
Örneğin, nesnenizin XML dizesinden veya JSON dizesinden oluşturulabileceği bir senaryo icat edebiliriz. Aşağıdaki gibi yöntemler yazabilirsiniz:
static MyObject createFromXml(String xml);
static MyObject createFromJson(String json);
Bu çok zaman zaman adlandırılmış başlatma yöntemleri ile parametresiz bir kurucu alternatif olarak kullandım:
MyObject myObject = new MyObject();
myObject.loadXml(xml).
Statik oluşturma yöntemini oluşturucu desenini sınıfınızda uygulamak olarak görebilirsiniz.
Sınıf özelliklerini (java'da statik) başlatmak için sınıf düzeyinde bir yapıcı tarafından kullanılan "statik" bölümünü görüntüleyebilirsiniz. Örnek düzey özelliklerini başlatmak için kullanılan "normal" yapıcı ile aynıdır.