Java varsayılan parametre değerlerini destekliyor mu?


1661

Aşağıdaki yapıya sahip bazı Java koduyla karşılaştım:

public MyParameterizedFunction(String param1, int param2)
{
    this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
    //use all three parameters here
}

C ++ ile bir parametreye varsayılan değer atayabileceğimi biliyorum. Örneğin:

void MyParameterizedFunction(String param1, int param2, bool param3=false);

Java bu tür bir sözdizimini destekliyor mu? Bu iki aşamalı sözdiziminin tercih edilmesinin herhangi bir nedeni var mı?


85
Hayır. Ancak, Oluşturucu deseni yardımcı olabilir.
Dave Jarvis

50
Bu özelliği gerçekten özlüyorum. Mevcut bir kodu bir işleve veya
kurucuya

4
@Jatin Eclipse "Yöntem imzasını değiştir" yeniden düzenleme ile bir parametre ekleyebilir ve mevcut invokatörlerin kullanacağı varsayılan bir değer sağlayabilirsiniz.
Erwin Bolwidt

2
@ErwinBolwidt Teşekkürler. Android Studio kullanıyorum ve aynı zamanda yöntemi yeniden düzenleme ve varsayılan değerler sağlama seçeneğine de sahip. Gayet yararlı.
Jatin

3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)bir yapıcıdır, yöntem değil, bildirimdir.
Mario Ishac

Yanıtlar:


955

Hayır, bulduğunuz yapı Java'nın bunu nasıl ele aldığıdır (yani, varsayılan parametreler yerine aşırı yükleme ile).

Kurucular için, bakınız Etkili Java: Programlama Dili Rehberi'nin aşırı yükleme karmaşık oluyor eğer Madde 1 ucu (yerine inşaatçı statik fabrika yöntemleri düşünün). Diğer yöntemler için bazı durumları yeniden adlandırmak veya bir parametre nesnesi kullanmak yardımcı olabilir. Bu, farklılaşmanın zor olduğu yeterli karmaşıklığa sahip olduğunuz zamandır. Kesin bir durum, yalnızca sayı ve tür değil, parametrelerin sırasını kullanarak farklılaştırmanız gerektiğidir.


25
Bu, 2009 yılında gerçekleşti, static2015'te her şey oldukça zararlı olarak kabul edildi. Tam ve geçerli inşaat sözleşmelerini zorlayan tip güvenli akıcı Builderörnekler şimdi çok daha iyi bir çözüm.

135
@JarrodRoberson: Statik fabrika yöntemleri bundan daha zararlı değildir new. Onlar edilir kullanılan tüm zaman yeni kodda. Basit değerli nesneler için yapıcılar genellikle aşırı mühendisliğin sonucudur.
Lii

12
@JarrodRoberson: Derleyici aracılığıyla doğru kullanımı zorlamanın ilginç yolu, paylaştığınız için teşekkürler! Gelecekteki gönderiler için kolay öneri: 300 satırlık önerilmeyen kaynak kodu muhtemelen çoğu insan için sindirmek için biraz fazladır (sonuçta yazmaktan çok kod okumak daha zordur). Tekrar teşekkürler!
Christian Aichinger

17
@JarrodRoberson: Güzel, dört gözle bekliyorum! Ne iletişim kurmak istedim: Blogunuzun bir okuyucusu olarak, neler olup bittiğine dair kısa bir metin açıklaması içeren 50 satırlık bir örnek, bağlam olmadan 300'den fazla satırdan fazla yardımcı olacaktır.
Christian Aichinger

8
@ user177800 Katılmıyorum - saf işlevler olarak yazıldıysa statik yöntemler gayet iyi. Statik bir fonksiyon, bir sorun haline geldiklerini ifade ettiğinde ...
Levi Fuller

642

Hayır, ancak bu Yığın Taşması yanıtında açıklandığı gibi Oluşturucu Deseni'ni kullanabilirsiniz .

Bağlantılı cevapta açıklandığı gibi, Oluşturucu Kalıbı aşağıdaki gibi kod yazmanıza olanak tanır

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

bazı alanların varsayılan değerlere sahip olabileceği veya başka türlü isteğe bağlı olabileceği.


142
Son olarak Builder deseninin 2 sayfadan daha az örneği.
nevvermind

14
Yine de merak ediyorum, neden oluşturucu desenini kullanırken bir oluşturucu sınıfına ihtiyacımız var. Student s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr Hand);
ivanceras

52
@ivanceras: Sınıflar zorunlu alanlara sahip olduğunda ve bu sınıfları geçersiz bir durumda somutlaştırmak istemediğinizde önemlidir. Eğer daha yeni söylediyseniz Student s1 = new Student().age(16);, bu sizi isimsiz bir Öğrenci ile bırakacaktır, ki bu kötü olabilir. Kötü değilse, çözümünüz iyidir.
Eli Courtwright

57
@ivanceras: başka bir neden, inşaattan sonra sınıfınızın değişmez olmasını isteyebilmenizdir, bu nedenle içinde değerlerini değiştiren yöntemler istemezsiniz.
Jules

3
@ivanceras: Builders'ı 3 şey için kullandım - çoklu argümanı ve akıcı başlatmayı, değişmezliği ortadan kaldırıyorum ve en önemlisi build () yöntemindeki alan nesnesini doğrulamak istiyorum.Neden geçersizse bir nesne örneği yaratabilirsiniz. yukarıdaki durumda olduğu gibi fabrika yöntemleri buildFreshman (), buildSenior () vb
Abhijeet Kushe

485

Java'da varsayılan parametreleri simüle etmenin birkaç yolu vardır:

  1. Yöntem aşırı yükleme.

    void foo(String a, Integer b) {
        //...
    }
    
    void foo(String a) {
        foo(a, 0); // here, 0 is a default value for b
    }
    
    foo("a", 2);
    foo("a");

    Bu yaklaşımın sınırlamalarından biri, aynı tipte iki isteğe bağlı parametreniz varsa ve bunlardan herhangi biri atlanabilirse işe yaramayacağıdır.

  2. Varargs.

    a) İsteğe bağlı tüm parametreler aynı tiptedir:

    void foo(String a, Integer... b) {
        Integer b1 = b.length > 0 ? b[0] : 0;
        Integer b2 = b.length > 1 ? b[1] : 0;
        //...
    }
    
    foo("a");
    foo("a", 1, 2);

    b) İsteğe bağlı parametre türleri farklı olabilir:

    void foo(String a, Object... b) {
        Integer b1 = 0;
        String b2 = "";
        if (b.length > 0) {
          if (!(b[0] instanceof Integer)) { 
              throw new IllegalArgumentException("...");
          }
          b1 = (Integer)b[0];
        }
        if (b.length > 1) {
            if (!(b[1] instanceof String)) { 
                throw new IllegalArgumentException("...");
            }
            b2 = (String)b[1];
            //...
        }
        //...
    }
    
    foo("a");
    foo("a", 1);
    foo("a", 1, "b2");

    Bu yaklaşımın ana dezavantajı, isteğe bağlı parametreler farklı tipteyse statik tip kontrolünü kaybetmenizdir. Ayrıca, her parametrenin farklı bir anlamı varsa, bunları ayırt etmenin bir yoluna ihtiyacınız vardır.

  3. Boşlara. Önceki yaklaşımların sınırlamalarını gidermek için null değerlere izin verebilir ve ardından bir yöntem gövdesindeki her parametreyi analiz edebilirsiniz:

    void foo(String a, Integer b, Integer c) {
        b = b != null ? b : 0;
        c = c != null ? c : 0;
        //...
    }
    
    foo("a", null, 2);

    Şimdi tüm bağımsız değişken değerleri sağlanmalıdır, ancak varsayılan değerler boş olabilir.

  4. İsteğe bağlı sınıf. Bu yaklaşım null değerlerine benzer, ancak varsayılan değeri olan parametreler için Java 8 Optional sınıfını kullanır:

    void foo(String a, Optional<Integer> bOpt) {
        Integer b = bOpt.isPresent() ? bOpt.get() : 0;
        //...
    }
    
    foo("a", Optional.of(2));
    foo("a", Optional.<Integer>absent());

    İsteğe bağlı bir yöntem sözleşmesini bir arayan için açık hale getirir, ancak böyle bir imza çok ayrıntılı bulabilir.

  5. Oluşturucu desen. Oluşturucu deseni yapıcılar için kullanılır ve ayrı bir Builder sınıfı eklenerek uygulanır:

     class Foo {
         private final String a; 
         private final Integer b;
    
         Foo(String a, Integer b) {
           this.a = a;
           this.b = b;
         }
    
         //...
     }
    
     class FooBuilder {
       private String a = ""; 
       private Integer b = 0;
    
       FooBuilder setA(String a) {
         this.a = a;
         return this;
       }
    
       FooBuilder setB(Integer b) {
         this.b = b;
         return this;
       }
    
       Foo build() {
         return new Foo(a, b);
       }
     }
    
     Foo foo = new FooBuilder().setA("a").build();
  6. Haritalar. Parametre sayısı çok fazla olduğunda ve çoğu için varsayılan değerler genellikle kullanıldığında, yöntem bağımsız değişkenlerini adlarının / değerlerinin haritası olarak iletebilirsiniz:

    void foo(Map<String, Object> parameters) {
        String a = ""; 
        Integer b = 0;
        if (parameters.containsKey("a")) { 
            if (!(parameters.get("a") instanceof Integer)) { 
                throw new IllegalArgumentException("...");
            }
            a = (String)parameters.get("a");
        } else if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 

İstenilen bir sonuç elde etmek için bu yaklaşımlardan herhangi birini birleştirebileceğinizi lütfen unutmayın.


1
İyi açıklama. Bu şekilde kullanılan dönüş değerlerini hiç görmedim. 5) ne return thisyapar? Ayrıca, FooBuilder().setA("a").build();(tanım gereği) yapıcı ilk olarak çağrıldığından ve FooBuilder()bir değer döndürdüğünden, bu .setA("a"):çağrılma şansının olmadığı anlamına gelmez mi?
Celeritas

3
@Celeritas return this, yöntemin çağrıldığı nesneyi döndürür (örnekte FooBuilder). Bu, new FooBuilder().setA(..).setB(..).setC(..)her bir yöntemi ayrı bir deyimde çağırmak yerine , aynı nesne üzerinde hareket eden bir deyimde yöntemlerin zincirlenmesine izin verir .
ADTC

2
@Celeritas , yöntemin çağrıldığı new FooBuilder()bir FooBuildernesneyi döndürür setA. As setBçağrılmaz, this.bvarsayılan değerini korur. Son olarak buildyöntem bu FooBuildernesne üzerinde çağrılır . buildYöntem oluşturur ve bir döner Foodeğişken ayarlanır nesne Foo foo. FooBuilderNesnenin herhangi bir değişkende saklanmadığına dikkat edin .
ADTC

Ek açıklama varsayılan parametreler oluşturmak için de kullanılabilir ve polimorfik koleksiyonlar için gerektiğinde en kullanışlıdır. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer

1
İki soruda aynı cevabı veren 900'ün üzerinde oy. Etkilendim: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331

256

Üzgünüm hayır.


34
Çok üzücü mü? Bunu yapmak potansiyel olarak belirsiz işlev imzaları getirecektir.
Trey

69
@Trey: varsayılan parametrelere sahip diller, daha az zorlayıcı olduğu için genellikle aşırı işlev yükünü giderir. Yani belirsizlik yok. Ayrıca, Scala bu özelliği 2.8'de ekledi ve bir şekilde belirsizlik sorununu çözdü (uyumluluk nedeniyle aşırı yüklemeyi korudukları için).
PhiLho

32
Parametre varsayılanlarının fonksiyon aşırı yüklenmesini nasıl önlediğini göremiyorum. Örneğin C # geçersiz kılmaya izin verir ve varsayılan başlatmalara da izin verir. Keyfi seçim gibi görünüyor, neden kısıtlama değil.
FlavorScape

51
Evet, derleyicinin fazladan iş yapmasını sağlayarak ticaret yapalım ve bunun yerine hepimiz kütüphane kullanıcılarına kolaylık sağlamak için 100000 aşırı yük yazalım. İyi bir fikir.

28
@ user562566: Bir Java projesinde çalıştığımda, Java geliştiricilerinin günde kaç kod satırı ürettikleri / ödeme yaptıkları izlenimini alıyorum
Mark K Cowan

83

Maalesef evet.

void MyParameterizedFunction(String param1, int param2, bool param3=false) {}

Java 1.5'te şu şekilde yazılabilir:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

Ancak, derleyicinin bir

new Boolean[]{}

her çağrı için.

Birden çok varsayılan parametre için:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

Java 1.5'te şu şekilde yazılabilir:

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

Bu, yalnızca parametre listesinin sonunda varsayılan parametrelere izin veren C ++ sözdizimi ile eşleşir.

Sözdiziminin ötesinde, bunun geçirilen varsayılan parametreler için çalışma zamanı türü denetimi ve C ++ türü derleme sırasında bunları denetlemesi arasında bir fark vardır.


14
Zeki, ancak varargs (...) yalnızca varsayılan parametreyi destekleyen dillerin size verdiğinden daha sınırlayıcı olan son parametre için kullanılabilir.
CurtainDog

6
Zeki ama C ++ sürümüne göre biraz dağınık
Someone Somewhere

5
Java kesinlikle C # ve diğerleri izin verdiği gibi isteğe bağlı varsayılan parametrelere ihtiyacı vardır ... sözdizimi açıktır ve sadece olası tüm kombinasyonları derleyerek bile bunu oldukça uygulayabileceklerini varsayıyorum ... Neden dile eklemediklerini hayal edemiyorum hala!
jwl

10
assertÜretim kodunda asla kullanılmamalıdır . Bir istisna atın.
Michael Dorst

5
-1 Gerçekten varargs bunun için değildir. Bu bir hack. - bu durumda, aşırı yüklerin kullanımı çok daha okunabilir olacaktır (bu talihsizdir, çünkü üç ekstra karakter 5 ekstra kaynak satırından daha okunabilir ...). - ancak Java varsayılan parametreleri desteklemez.
BrainSlugs83

38

Hayır, ama onları kolayca taklit edebilirsiniz. C ++ 'ta ne vardı:

public: void myFunction(int a, int b=5, string c="test") { ... }

Java'da aşırı yüklenmiş bir işlev olacaktır:

public void myFunction(int a, int b, string c) { ... }

public void myFunction(int a, int b) {
    myFunction(a, b, "test");
}

public void myFunction(int a) {
    myFunction(a, 5);
}

Daha önce, varsayılan parametrelerin işlev aşırı yüklemesinde belirsiz vakalara neden olduğu belirtildi. Bu doğru değil, C ++ durumunda görebiliriz: evet, belki belirsiz vakalar oluşturabilir, ancak bu sorun kolayca ele alınabilir. Java'da geliştirilmemiştir, muhtemelen içerik oluşturucular C ++ gibi çok daha basit bir dil istediler - eğer doğrularsa başka bir soru. Ama çoğumuz basitliği nedeniyle Java kullandığını düşünmüyoruz.


8
C # varsayılan değer gösteriminin ana fikri, tam olarak bu kazan plakası kodlamasını önlemek ve birçok yerine sadece bir yapıcıya sahip olmaktır.
Kolya Ivankov

1
@KolyaIvankov C # bilmiyorum, ama mantığın aynı olduğu C ++ biliyorum. Ne daha iyi bilmiyorum, ama bence, aslında aynı boilerplate kodu C ++ / C # durumunda derleyici tarafından oluşturulur ve son ikili gidiyor.
peterh - Monica'yı

5
Her programlama dili (özellikle) bir Assembler ısıtıcı plakasından kaçınmanın bir yoludur, yanılıyor muyum? Soru sadece kullanışlı bir işlevsellik sağlayıp sağlamadığıdır.
Kolya Ivankov

2
İlk cümle retorik bir sorudur. İkinci cümledeki "soru" kelimesinin, ilk sorudaki retorik soru ile ilgisi yoktur.
Kolya Ivankov

1
Daha spesifik olmak gerekirse: diller, yazılanları kontrol edebileceğimiz şekilde programlar yazmamızı sağlayan araçlardır, derleme bir makineden ne istediğimizi anlatmanın bir yoludur. Bir araç, kazan plakasından kaçınmamıza izin verirse daha kullanışlıdır. Aslında, gnavi, C # için izin verdiği için, cevap olarak önerdiğiniz demirbaş kodu türünden tam olarak kaçınabileceklerini sordu.
Kolya Ivankov

24

Bunu JVM üzerinde çalışan ve Java programlarıyla uyumlu olan Scala'da yapabilirsiniz. http://www.scala-lang.org/

yani

class Foo(var prime: Boolean = false, val rib: String)  {}

58
Çok yaygın olmayan bir özellik elde etmek için yepyeni bir dil getirin mi?
om-nom-nom

8
@ om-nom-nom: Java asla var olmamalıdır. Bir özelliğin kullanılmadığını söylemek, kimsenin ihtiyaç duymadığına eşdeğerdir, Java'nın icat edilmeden önce popüler olmadığını söylemek Gosling'in onu tasarlamaya başlamaması gerektiği anlamına gelir.
Val

28
@Val, bunun toplarla kuş vurmak gibi olduğunu söylüyor
om-nom-nom

8
bunun OP'nin sorusuyla ilgisi yok
destan

Kotlin'de de çalışıyor. Ve harika. Ve C#. Ve Javascript. Ve gerçek insanlar ve problemler için yapılmış neredeyse tüm diğer diller.
spyro

17

Hayır , ancak bunu uygulamanın en basit yolu :

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

veya üçlü operatör yerine şunları kullanabilirsiniz if:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

2
Evet, bu yaklaşım diğer alternatiflerden en iyisi gibi görünüyor. Yine de Java'nın varsayılan değerleri benimsemesi iyi olurdu; Kotlin bunun yapılabileceğini gösterdi, bu yüzden Oracle'ın neden modern çağa girmediğinden emin değilim ve 1990'larda sanki java tasarlamaya devam ediyor. : D
shevy

13

Burada bariz belirtiyor olabilir ama neden sadece "varsayılan" parametresini kendiniz uygulamak değil?

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

varsayılan olarak,

func("my string");

ve varsayılanı kullanmak istemiyorsanız,

func("my string", false);

11
Poster, bu (oldukça çirkin) kalıbın önlenip önlenemeyeceğini sordu ... ;-) Daha modern dillerde (c #, Scala gibi) sadece daha fazla kod satırı oluşturan bu fazladan yüklemeye ihtiyacınız yok. Bir noktaya kadar varargs kullanabilirsiniz (statik int max (int ... dizi) {}), ancak bunlar sadece çok çirkin bir çözümdür.
Offler

2
Aşırı yükleme çirkin değildir ve farklı imzalara sahip farklı yöntem çağrıları gibi farklı işlevler gerçekleştirebilir. //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } }
Antony Booth

Eğer biri farklı davranışlar istiyorsa. Tek fark, hesaplamalarda vb.Küçük bir değişiklikse, çoklu imza oluşturmak için çaba harcamadan eminiz. Temerrütler, onlara ihtiyaç duyduğunuz her yerde anlamlıdır ... ve eksikliği, "yararsız" bir gereklilik olarak sınıflandırılmamalıdır.
Kapil

@Offler varsayılan parametrelerinin "modern dil" ile ilgisi yoktur. Onları 20 yıl önce Delphi'de kullandım ve muhtemelen Turbo Pascal'da var oldular.
İnanılmaz Ocak

Offler'a katılıyorum ve Antony Booth'a katılmıyorum. Sadece çirkin değil, aynı zamanda oldukça verimsiz buluyorum. Ruby veya python gibi diller varsayılan parametreleri kullanmayı önemsiz kılar; Java'nın ne yapmanızı gerektirdiğini tahmin ediyorum geçici çözümler bulmak (ve kullanmak). Null'a karşı açık çek en az çirkin bir seçim gibi görünüyor, çünkü bunu komut satırından da çağırabilirim (sadece bir şey sağlayıp sonra aklı varyantını işleyebilirim); operatör aşırı yükleme yaklaşımı ... çok ayrıntılı (null-check ile karşılaştırıldığında en az +3 satır ve kod daha karmaşıksa daha fazla satır gibi).
shevy

8

Scala'dan bahsedildiği gibi, Kotlin de bahsetmeye değer. Kotlin fonksiyon parametrelerinde varsayılan değerler de olabilir ve hatta diğer parametrelere de başvurabilirler:

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

Scala gibi Kotlin de JVM üzerinde çalışır ve mevcut Java projelerine kolayca entegre edilebilir.


6

Hayır.

Akıllı varsayılanlara sahip bir Nesneyi ileterek aynı davranışı elde edebilirsiniz. Fakat yine de, davanızın elinizin altında olmasına bağlıdır.


5

Hayır. Genel olarak Java'nın basit bir dil yapmaya çalıştıkları için çok fazla sözdizimsel şekeri yoktur.


26
Pek değil. Acı gerçek, takımın sıkı bir programda olması ve sözdizimsel şeker için zamanının olmamasıdır. Neden başka hiçbir uygulama olmayan constve gotoanahtar kelimeler rezerve edilecek? - Özellikle constacı bir şekilde özlediğim bir şey - finalyerine geçmiyor ve biliyorlardı. - Ve asla uygulamak için dikkatli bir karar verdiyseniz goto, anahtar kelimeyi ayırmanız gerekmez. - Ve daha sonra Java Ekibi, Label tabanlı breakve continuePascal kadar güçlü yaparak hile yaptı goto.
Martin

Bkz - "Basit, Nesne Tabanlı ve Tanıdık" gerçekten tasarım hedefi oldu oracle.com/technetwork/java/intro-141325.html
Mikera

1
tomjen şöyle dedi: "Hayır. Genel olarak Java'nın basit bir dil yapmaya çalıştıkları için çok fazla sözdizimsel şekeri yoktur". Yani bir çok gereksiz özelliği C ++ 'dan kaldırmanın bir Java'yı basit bir dil haline getirdiğini söylüyorsunuz, o zaman Java'nın neden varyasyon yöntemleri olduğunu söylüyorsunuz? Neden varargs var? Bunun yerine bir dizi nesneyi kullanabilmeniz gerekmez, değil mi? Böylece varargs dilden kaldırılabilir, çünkü gereksizdir. Bu, Java'yı şimdi olduğundan daha basit hale getirecektir. Haklı mıyım? Her yöntem için sonsuz adlara sahip olduğunuz için aşırı yükleme de kaldırılabilir.

1
ve bu yüzden basit dili alıp herhangi bir gerçek Java projesini sözdizimi ve kaynak plakasının bir
karışımına

Geliştirme araçlarını kod koduna ve karmaşık geçici çözümlere zorlamak "kolay" kelimesini anlamam değil. myFunction (a, b = yanlış, c = 3), kolay dediğim şey bu.
spyro

5

Kullanmak yerine:

void parameterizedMethod(String param1, int param2) {
    this(param1, param2, false);
}

void parameterizedMethod(String param1, int param2, boolean param3) {
    //use all three parameters here
}

Tek bir yöntem kullanarak java'nın İsteğe bağlı işlevini kullanabilirsiniz:

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
    param3 = Optional.ofNullable(param3).orElse(false);
    //use all three parameters here
}

Temel fark, nullgirişe izin vermek için ilkel Java türleri yerine sarmalayıcı sınıfları kullanmanızdır . Booleanyerine boolean, Integeryerine intvb.


4

Desteklenmez, ancak bazı sözdizimi şekeriyle parametre nesne desenini kullanma gibi birkaç seçenek vardır:

public class Foo() {
    private static class ParameterObject {
        int param1 = 1;
        String param2 = "";
    }

    public static void main(String[] args) {
        new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
    }

    private void myMethod(ParameterObject po) {
    }
}

Bu örnekte ParameterObjectvarsayılan değerlerle oluşturuyoruz ve bunları sınıf örneği başlatma bölümünde geçersiz kılıyoruz{ param1 = 10; param2 = "bar";}


3

Bu çözümü deneyin:

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}

3

Sen kullanabilirsiniz Java Yöntem çağırma Builder otomatik olarak varsayılan değerlerle oluşturucu üretmek için.

Sadece sınıfa veya arabirime @GenerateMethodInvocationBuilder ve @Default parametrelerini varsayılan değerleri istediğiniz yöntemlerde ekleyin. Ek açıklamalarınızla belirttiğiniz varsayılan değerler kullanılarak derleyici zamanında bir oluşturucu oluşturulur.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

Ve sonra yöntemleri çağırabilirsiniz.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

Veya varsayılan değerlerden herhangi birini başka bir şeye ayarlayın.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);

2

Java 8'de çalışan https://stackoverflow.com/a/13864910/2323964 için benzer bir yaklaşım , varsayılan alıcılarla bir arabirim kullanmaktır. Bu, daha fazla boşluklu bir ayrıntı olacak, ancak mockable olabilir ve parametrelere gerçekten dikkat çekmek istediğiniz bir sürü örneğiniz olduğunda harika.

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}

2

Şimdi değerleri döndüren yöntemlerle bu nasıl kullanılacağını anlamak için biraz zaman geçirdim ve şimdiye kadar herhangi bir örnek görmedim, ben buraya eklemek için yararlı olabilir düşündüm:

int foo(int a) {
    // do something with a
    return a;
}

int foo() {
    return foo(0); // here, 0 is a default value for a
}

1

Bu şekilde yaptım ... belki de tanımlanmış parametrenize karşı 'isteğe bağlı bir argüman' olması kadar uygun değil, ama işi hallediyor:

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

Dikkat sadece bir dize ile aynı yöntem adını çağırabilir veya bir dize ve bir boolean değeri ile çağırabilir. Bu durumda, wipeClean öğesini true olarak ayarlamak TextArea'mdaki metnin tamamını sağlanan dizeyle değiştirir. WipeClean öğesini false olarak ayarlamak veya hepsini bir arada bırakmak, sağlanan metni TextArea öğesine ekler.

Ayrıca iki yöntemde kod tekrarlamıyorum dikkat, ben sadece eklenen boole ile aynı ada sahip yeni bir yöntem oluşturarak TextArea sıfırlama işlevselliğini ekliyorum.

Aslında bu daha sonra varsayılan değerler vb kodlamak gerekir çünkü Java bizim parametreler için 'isteğe bağlı bir argüman' sağlanan daha biraz daha temiz olduğunu düşünüyorum. Bu örnekte, ben bunlardan herhangi biri için endişelenmenize gerek yok. Evet, sınıfıma başka bir yöntem daha ekledim, ancak uzun vadede mütevazi düşüncemle okumak daha kolay.


1

HAYIR, Ama fonksiyon aşırı yüklenmesi şeklinde bir alternatifimiz var.

parametre geçilmediğinde çağrılır

void operation(){

int a = 0;
int b = 0;

} 

"a" parametresi geçtiğinde çağrılır

void operation(int a){

int b = 0;
//code

} 

b parametresi geçtiğinde çağrılır

void operation(int a , int b){
//code
} 

1

Bunun gibi yarım düzine veya daha iyi sorun var, sonunda statik fabrika modeline ulaşıyorsunuz ... bunun için kripto API'sına bakın. Açıklamak zor, ancak bunu şu şekilde düşünün: Varsayılan veya başka bir yapıcıya sahipseniz, durumu kıvırcık parantezlerin ötesine yaymanın tek yolu bir Boolean isValid'e sahip olmaktır; (varsayılan değer v başarısız yapıcı olarak null ile birlikte) veya alan kullanıcılarından geri alırken hiçbir zaman bilgilendirici olmayan bir istisna atar.

Kod Doğru lanet olsun, bin satır kurucuları yazıyorum ve ihtiyacım olanı yapıyorum. Nesne yapımında - yani iki satırlı yapıcılarda - isValid kullanıyorum, ancak bir nedenle statik fabrika modeline geçiyorum. Sadece bir yöntem çağrısında çok şey yapabileceğiniz gibi görünüyor, hala sync () sorunları var ama varsayılanlar 'yerine' daha iyi (daha güvenli)

Burada ne yapmamız gerektiğini varsayılan değer vis-a-vis bir şey olarak null sorunu çözmek olduğunu düşünüyorum Bir = new String (""); üye değişkeni olarak, daha sonra yapıcıya iletilen dize atamadan önce null olup olmadığını kontrol edin.

Java'da yapılan ham, stratosferik bilgisayar biliminin miktarı çok dikkat çekici.

C ++ ve benzeri satıcı kütüphaneleri vardır, evet. Java, büyük bir araç kutusundan dolayı büyük ölçekli sunucularda onları aşabilir. Statik başlatıcı bloklarını inceleyin, bizimle kalın.



0

Aşağıdakileri kullanabilirsiniz.

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
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.