Apakah Java mendukung nilai parameter default?

1661

Saya menemukan beberapa kode Java yang memiliki struktur berikut:

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

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

Saya tahu bahwa di C ++ saya dapat menetapkan parameter sebagai nilai default. Sebagai contoh:

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

Apakah Java mendukung sintaks semacam ini? Adakah alasan mengapa sintaks dua langkah ini lebih disukai?

gnavi
sumber
85
Tidak. Namun, pola Builder dapat membantu.
Dave Jarvis
50
Saya sangat merindukan fitur ini. Ini sangat membantu ketika memodifikasi kode yang ada untuk mengambil parameter tambahan ke fungsi atau konstruktor
Jatin
4
@Jatin Dengan refactoring Eclipse "Ubah metode tanda tangan" Anda dapat menambahkan parameter dan memberikan nilai default yang akan digunakan oleh penjajah yang ada.
Erwin Bolwidt
2
@ErwinBolwidt Terima kasih. Saya menggunakan Android Studio, dan juga memiliki opsi untuk refactoring metode dan memberikan nilai default. Cukup berguna.
Jatin
3
@temporary_user_name public MyParameterizedFunction(String param1, int param2)adalah konstruktor, bukan metode, deklarasi.
Mario Ishac

Jawaban:

955

Tidak, struktur yang Anda temukan adalah bagaimana Java menanganinya (yaitu, dengan overloading bukan parameter default).

Untuk konstruktor, Lihat Tip Java yang Efektif: Memprogram Tip Item 1 Panduan Bahasa (Pertimbangkan metode pabrik statis alih-alih konstruktor) jika kelebihan beban semakin rumit. Untuk metode lain, mengganti nama beberapa case atau menggunakan objek parameter dapat membantu. Ini adalah ketika Anda memiliki kompleksitas yang cukup yang membedakan sulit. Kasus yang pasti adalah di mana Anda harus membedakan menggunakan urutan parameter, bukan hanya jumlah dan jenisnya.

Kathy Van Stone
sumber
135
@JarrodRoberson: Metode pabrik statis tidak lebih berbahaya daripada new. Mereka digunakan sepanjang waktu dalam kode baru. Pembangun untuk objek bernilai sederhana seringkali merupakan hasil rekayasa berlebihan.
Lii
12
@JarrodRoberson: Cara menarik untuk memaksa penggunaan yang benar melalui kompiler, terima kasih telah berbagi! Saran ramah untuk posting di masa mendatang: 300 baris kode sumber yang tidak diomentari mungkin agak banyak dicerna bagi kebanyakan orang (kode lebih sulit dibaca daripada menulis, setelah semua). Terima kasih lagi!
Christian Aichinger
17
@JarrodRoberson: Bagus, menantikannya! Apa yang ingin saya komunikasikan: sebagai pembaca blog Anda, contoh 50 baris dengan deskripsi teks singkat tentang apa yang terjadi akan membantu saya lebih dari 300 baris tanpa konteks.
Christian Aichinger
8
@ user177800 Tidak setuju - metode statis jika ditulis sebagai fungsi murni tidak masalah. Itu ketika fungsi statis bermutasi bahwa mereka menjadi masalah ...
Levi Fuller
642

Tidak, tetapi Anda dapat menggunakan Pola Builder , seperti yang dijelaskan dalam jawaban Stack Overflow ini .

Seperti dijelaskan dalam jawaban yang ditautkan, Pola Builder memungkinkan Anda menulis kode seperti

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

di mana beberapa bidang dapat memiliki nilai default atau opsional.

Eli Courtwright
sumber
142
Terakhir, contoh besar pola Builder yang kurang dari 2 halaman.
nevvermind
14
Saya penasaran, mengapa kita membutuhkan kelas builder ketika menggunakan pola builder. Saya sedang memikirkan Student s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr Hand);
ivanceras
52
@ivanceras: Ini relevan ketika kelas membutuhkan bidang, dan Anda tidak ingin dapat membuat instance kelas-kelas itu dalam keadaan tidak valid. Jadi jika Anda hanya mengatakan Student s1 = new Student().age(16);itu akan meninggalkan Anda dengan seorang Siswa tanpa nama, yang mungkin buruk. Jika tidak buruk, maka solusi Anda baik-baik saja.
Eli Courtwright
57
@ivanceras: alasan lain adalah Anda mungkin ingin kelas Anda tidak berubah setelah konstruksi, jadi Anda tidak ingin metode di dalamnya yang mengubah nilainya.
Jules
3
@ivanceras: Saya menggunakan Builder untuk 3 hal - menghilangkan argumen berganda dan inisialisasi lancar, imutabilitas dan yang paling penting saya merasa untuk memvalidasi objek domain dalam metode build (). Mengapa membuat instance objek jika tidak valid. Anda juga dapat membebani statis metode pabrik seperti dalam kasus di atas buildFreshman (), buildSenior () dll
Abhijeet Kushe
485

Ada beberapa cara untuk mensimulasikan parameter default di Java:

  1. Metode kelebihan beban.

    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");
    

    Salah satu batasan dari pendekatan ini adalah bahwa itu tidak berfungsi jika Anda memiliki dua parameter opsional dari jenis yang sama dan salah satu dari mereka dapat dihilangkan.

  2. Varargs.

    a) Semua parameter opsional memiliki tipe yang sama:

    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) Jenis parameter opsional mungkin berbeda:

    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");
    

    Kelemahan utama dari pendekatan ini adalah bahwa jika parameter opsional dari tipe yang berbeda Anda kehilangan pemeriksaan tipe statis. Lebih jauh, jika setiap parameter memiliki arti yang berbeda, Anda perlu cara untuk membedakannya.

  3. Nulls. Untuk mengatasi keterbatasan pendekatan sebelumnya, Anda dapat mengizinkan nilai nol dan kemudian menganalisis setiap parameter dalam tubuh metode:

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

    Sekarang semua nilai argumen harus disediakan, tetapi yang standar mungkin nol.

  4. Kelas opsional. Pendekatan ini mirip dengan nol, tetapi menggunakan kelas Java 8 Opsional untuk parameter yang memiliki nilai default:

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

    Opsional membuat metode kontrak eksplisit untuk penelepon, namun, orang mungkin menemukan tanda tangan seperti itu terlalu lisan.

  5. Pola pembangun. Pola pembangun digunakan untuk konstruktor dan diimplementasikan dengan memperkenalkan kelas Builder yang terpisah:

     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. Peta. Ketika jumlah parameter terlalu besar dan sebagian besar dari mereka nilai default biasanya digunakan, Anda bisa meneruskan argumen metode sebagai peta nama / nilai mereka:

    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")); 
    

Harap dicatat bahwa Anda dapat menggabungkan salah satu dari pendekatan ini untuk mencapai hasil yang diinginkan.

Vitalii Fedorenko
sumber
1
Penjelasan yang bagus. Saya belum pernah melihat nilai pengembalian yang digunakan seperti ini. Untuk 5) apa yang harus return thisdilakukan? Juga, bukan FooBuilder().setA("a").build();karena (menurut definisi) konstruktor dipanggil pertama dan FooBuilder()mengembalikan nilai, bukankah ini berarti .setA("a"):tidak mendapatkan kesempatan untuk dipanggil?
Celeritas
3
@Celeritas return thismengembalikan objek yang sama di mana metode dipanggil (dalam contoh, FooBuilder). Hal ini memungkinkan perangkaian metode dalam satu pernyataan yang bekerja pada objek yang sama: new FooBuilder().setA(..).setB(..).setC(..)dll sebagai lawan memanggil setiap metode dalam pernyataan terpisah.
ADTC
2
@Celeritas new FooBuilder()mengembalikan FooBuilderobjek tempat setAmetode ini dipanggil. Seperti setBtidak dipanggil, this.bmempertahankan nilai default. Akhirnya buildmetode ini dipanggil pada FooBuilderobjek ini . The buildMetode menciptakan dan mengembalikan sebuah Fooobjek yang diatur ke variabel Foo foo. Perhatikan bahwa FooBuilderobjek tidak disimpan dalam variabel apa pun.
ADTC
Anotasi juga dapat digunakan untuk membuat parameter default dan paling berguna saat diperlukan untuk koleksi polimorfik. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer
1
Lebih dari 900 suara naik pada jawaban yang sama di dua pertanyaan. Saya terkesan: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331
256

Sayangnya tidak.

Rob H
sumber
34
Apakah ini sangat menyedihkan? Melakukan hal itu akan memperkenalkan tanda tangan fungsi yang berpotensi ambigu.
Trey
69
@Trey: bahasa dengan parameter default sering membuang fungsi berlebihan karena kurang menarik. Jadi tidak ada ambiguitas. Selain itu, Scala menambahkan fitur di 2.8, dan entah bagaimana menyelesaikan masalah ambiguitas (karena mereka menjaga kelebihan beban karena alasan kompatibilitas).
PhiLho
32
Saya gagal melihat bagaimana parameter default mencegah kelebihan fungsi. C # misalnya memungkinkan penggantian dan juga memungkinkan untuk inisialisasi default. Sepertinya pilihan sewenang-wenang, bukan pembatasan adalah alasannya.
FlavourScape
51
Ya, mari kita tukar membuat kompiler melakukan pekerjaan ekstra dan bukannya membuat kita semua menulis 100000 kelebihan untuk memberikan kenyamanan pengguna perpustakaan kami. Ide bagus.
28
@ user562566: Setiap kali saya mengerjakan proyek Java, saya mendapat kesan bahwa Java devs dibayar / diukur dengan berapa banyak baris kode yang mereka hasilkan per hari
Mark K Cowan
83

Sayangnya ya.

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

dapat ditulis dalam Java 1.5 sebagai:

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

Tetapi apakah Anda harus bergantung pada bagaimana perasaan Anda tentang pembuat kompiler a

new Boolean[]{}

untuk setiap panggilan.

Untuk beberapa parameter default:

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

dapat ditulis dalam Java 1.5 sebagai:

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;
}

Ini cocok dengan sintaksis C ++, yang hanya mengizinkan parameter default di akhir daftar parameter.

Di luar sintaks, ada perbedaan di mana ini telah menjalankan jenis waktu memeriksa untuk melewati parameter defaultable dan tipe C ++ memeriksa mereka selama kompilasi.

ebelisle
sumber
14
Pintar, tetapi varargs (...) hanya dapat digunakan untuk parameter terakhir, yang lebih membatasi daripada apa bahasa yang mendukung parameter default memberi Anda.
CurtainDog
6
itu pintar tapi agak berantakan dibandingkan dengan versi C ++
Seseorang di suatu tempat
5
Java pasti membutuhkan parameter default default sebagai C # dan yang lain memungkinkan ... sintaksanya jelas dan saya kira mereka dapat mengimplementasikan ini cukup sederhana bahkan dengan hanya mengkompilasi semua kombinasi yang mungkin ... Saya tidak bisa membayangkan mengapa mereka belum menambahkannya ke bahasa namun!
jwl
10
Seseorang seharusnya tidak pernah menggunakan assertkode produksi. Lempar pengecualian.
Michael Dorst
5
-1 Ini sebenarnya bukan untuk apa vararg. Ini adalah retasan. - dalam hal ini, menggunakan overload akan jauh lebih mudah dibaca (yang sangat disayangkan, karena tiga karakter tambahan lebih mudah dibaca daripada 5 baris sumber tambahan ...). - tetapi Java tidak mendukung parameter default.
BrainSlugs83
38

Tidak, tetapi Anda dapat dengan mudah meniru mereka. Apa yang ada di C ++ adalah:

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

Di Jawa, itu akan menjadi fungsi kelebihan beban:

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);
}

Sebelumnya disebutkan, bahwa parameter default menyebabkan kasus ambigu dalam fungsi yang berlebihan. Itu tidak benar, kita dapat melihat dalam kasus C ++: ya, mungkin itu dapat membuat kasus yang ambigu, tetapi masalah ini dapat dengan mudah ditangani. Itu tidak dikembangkan di Jawa, mungkin karena pembuatnya menginginkan bahasa yang lebih sederhana seperti C ++ - jika mereka benar, adalah pertanyaan lain. Tetapi kebanyakan dari kita tidak berpikir dia menggunakan Jawa karena kesederhanaannya.

peterh - Pasang kembali Monica
sumber
8
Ide utama notasi nilai default C # adalah untuk menghindari pengkodean boilerplate ini dan hanya memiliki satu konstruktor alih-alih banyak.
Kolya Ivankov
1
@ KolyaIvankov Saya tidak tahu C #, tapi saya tahu C ++ di mana alasannya sama. Saya tidak tahu apa yang lebih baik, tapi saya pikir, sebenarnya kode boilerplate yang sama dihasilkan oleh kompiler dalam kasus C ++ / C # dan akan menjadi biner akhir.
peterh
5
Setiap bahasa pemrograman adalah (khususnya) sarana untuk menghindari boilerplate Assembler, apakah saya salah? Pertanyaannya hanya apakah itu memberikan fungsionalitas yang praktis, atau tidak.
Kolya Ivankov
2
Kalimat pertama adalah pertanyaan retoris. Kata "pertanyaan" dalam kalimat kedua tidak ada hubungannya dengan pertanyaan retoris di kalimat pertama.
Kolya Ivankov
1
Menjadi lebih spesifik: bahasa adalah alat yang memungkinkan kita untuk menulis program dengan cara kita dapat memiliki kontrol atas apa yang ditulis, kompilasi adalah cara untuk memberi tahu mesin apa yang kita inginkan darinya. Alat lebih berguna jika memungkinkan kita menghindari boilerplate. Akibatnya, gnavi bertanya, apakah mereka dapat menghindari dengan tepat jenis kode boilerplate yang Anda usulkan sebagai jawaban, karena C # memungkinkan untuk itu.
Kolya Ivankov
24

Anda dapat melakukannya di Scala, yang berjalan pada JVM dan kompatibel dengan program Java. http://www.scala-lang.org/

yaitu

class Foo(var prime: Boolean = false, val rib: String)  {}
lythic
sumber
58
Bawalah seluruh bahasa baru untuk mendapatkan satu fitur yang tidak begitu umum?
om-nom-nom
8
@ om-nom-nom: Java seharusnya tidak pernah ada. Mengatakan bahwa suatu fitur tidak digunakan sama dengan tidak ada yang membutuhkannya mengatakan bahwa Java tidak populer sebelum diciptakan berarti Gosling tidak boleh mulai mendesainnya.
Val
28
@ Val hanya mengatakan bahwa ini seperti menembak burung dengan meriam
om-nom-nom
8
yang tidak ada hubungannya dengan pertanyaan OP
destan
Bekerja di Kotlin juga. Dan asyik. Dan C#. Dan Javascript. Dan hampir semua bahasa lain yang dibuat untuk orang-orang nyata dan masalah.
spyro
17

Tidak , tetapi cara paling sederhana untuk mengimplementasikan ini adalah:

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

atau alih-alih operator ternary , Anda dapat menggunakan if:

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

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

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}
simhumileco
sumber
2
Ya, pendekatan ini tampaknya menjadi yang terbaik dari alternatif lain. Tetap menyenangkan bagi Java untuk mengadopsi nilai default; Kotlin menunjukkan bahwa ini bisa dilakukan, jadi saya tidak yakin mengapa Oracle tidak memasuki era modern, dan terus mendesain java seolah-olah itu tahun 1990-an. : D
shevy
13

Saya mungkin menyatakan yang jelas di sini tapi mengapa tidak menerapkan parameter "default" sendiri?

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

untuk standarnya, Anda akan menggunakannya

func("my string");

dan jika Anda tidak ingin menggunakan default, Anda akan menggunakannya

func("my string", false);
Serigala Besi
sumber
11
Poster bertanya apakah pola (agak jelek) ini dapat dihindari ... ;-) Dalam bahasa yang lebih modern (seperti c #, Scala) Anda tidak memerlukan kelebihan ini yang hanya membuat lebih banyak baris kode. Hingga titik tertentu Anda dapat menggunakan varargs sementara itu (static int max (int ... array) {}), tetapi mereka hanya solusi yang sangat buruk.
Offler
2
Overloading tidak jelek dan memiliki banyak manfaat, seperti panggilan metode yang berbeda dengan tanda tangan yang berbeda dapat melakukan fungsi yang berbeda. //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
Nah, jika seseorang menginginkan perilaku yang berbeda. Jika satu-satunya perbedaan adalah sedikit perubahan dalam perhitungan, dll., Itu pasti usaha yang sia-sia untuk membuat banyak tanda tangan. Defaultnya masuk akal di mana Anda membutuhkannya ... dan kekurangannya tidak boleh diklasifikasikan sebagai persyaratan "tidak berguna".
Kapil
@Offler, parameter default tidak ada hubungannya dengan "bahasa modern". Saya menggunakannya di Delphi 20 tahun yang lalu dan mereka mungkin sudah ada di Turbo Pascal.
Jan
Saya setuju dengan Offler, dan tidak setuju dengan Antony Booth. Saya menemukan itu tidak hanya jelek tetapi juga tidak efisien. Bahasa seperti ruby ​​atau python membuatnya sepele untuk menggunakan parameter default; Saya kira apa yang diminta oleh Java untuk Anda lakukan adalah menemukan (dan menggunakan) solusi. Pemeriksaan eksplisit versus nol tampaknya menjadi pilihan yang paling jelek, karena saya dapat menyebutnya dari commandline juga (hanya tidak memberikan apa-apa, dan kemudian menangani varian waras); pendekatan overloading operator tampaknya ... sangat verbose (seperti setidaknya +3 baris, dibandingkan dengan nol-periksa, dan lebih banyak baris jika kodenya lebih kompleks).
shevy
8

Seperti Scala disebutkan, Kotlin juga layak disebut. Di Kotlin, parameter fungsi dapat memiliki nilai default juga dan mereka bahkan dapat merujuk ke parameter lain:

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

Seperti Scala, Kotlin berjalan pada JVM dan dapat dengan mudah diintegrasikan ke dalam proyek Java yang ada.

Tuan
sumber
6

Tidak.

Anda dapat mencapai perilaku yang sama dengan melewati Obyek yang memiliki default pintar. Tetapi sekali lagi itu tergantung pada kasus Anda.

Santosh Gokak
sumber
5

Tidak. Secara umum Jawa tidak memiliki banyak gula sintaksis, karena mereka mencoba membuat bahasa yang sederhana.

Tomjen
sumber
26
Tidak terlalu. Kebenaran pahit adalah bahwa tim berada pada jadwal yang ketat dan tidak punya waktu untuk gula sintaksis. Kenapa lagi akan constdan gotoharus dilindungi kata kunci yang ada implementasi? - Terutama constadalah sesuatu yang saya rindukan - finaltidak ada pengganti dan mereka tahu itu. - Dan jika Anda membuat keputusan sadar untuk tidak pernah menerapkan gotoAnda tidak perlu memesan kata kunci. - Dan kemudian dalam Java Team ditipu dengan membuat Label berdasarkan breakdan continuesekuat Pascal goto.
Martin
"Sederhana, Berorientasi Objek, dan Akrab" memang tujuan desain - lihat oracle.com/technetwork/java/intro-141325.html
mikera
1
tomjen berkata: "Tidak. Secara umum Jawa tidak memiliki banyak gula sintaksis, karena mereka mencoba membuat bahasa yang sederhana". Jadi Anda mengatakan bahwa menghapus banyak fitur yang tidak perlu dari C ++ membuat Java menjadi bahasa yang sederhana, lalu beritahu saya mengapa Java memiliki metode variadic? Mengapa ada vararg? Ini tidak diperlukan jika Anda hanya dapat menggunakan array objek saja, apakah saya benar? Jadi vararg dapat dihapus dari bahasa, karena itu tidak perlu. Ini akan membuat Java lebih sederhana dari apa yang sekarang. Apakah saya benar? Overloading juga dapat dihapus, karena Anda memiliki nama tak terbatas untuk setiap metode.
1
dan itulah sebabnya kami mendapatkan pegas dan hal-hal yang menggunakan bahasa sederhana dan mengubah proyek Java nyata menjadi gugusan sintaks dan
pelat boiler
Memaksa pengembang untuk meningkatkan kode dan penyelesaian yang rumit bukanlah pemahaman saya akan kata "mudah". myFunction (a, b = false, c = 3), itulah yang saya sebut mudah.
spyro
5

Alih-alih menggunakan:

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

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

Anda dapat menggunakan fungsionalitas opsional java dengan memiliki satu metode:

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

Perbedaan utama adalah bahwa Anda harus menggunakan kelas wrapper alih-alih tipe Java primitif untuk memungkinkan nullinput. Booleanbukannya boolean, Integerbukannya intdan sebagainya.

Viktor Taranenko
sumber
4

Itu tidak didukung tetapi ada beberapa opsi seperti menggunakan pola objek parameter dengan beberapa gula sintaks:

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) {
    }
}

Dalam sampel ini kami membangun ParameterObjectdengan nilai default dan menimpanya di bagian inisialisasi instance kelas{ param1 = 10; param2 = "bar";}

hoaz
sumber
3

Coba solusi ini:

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

    return score;
}
Hamzeh Soboh
sumber
3

Anda dapat menggunakan Java Method Invocation Builder untuk secara otomatis menghasilkan builder dengan nilai default.

Cukup tambahkan @GenerateMethodInvocationBuilder ke kelas, atau antarmuka, dan @Default ke parameter dalam metode di mana Anda ingin nilai default. Builder akan dihasilkan pada waktu kompilasi, menggunakan nilai default yang Anda tentukan dengan anotasi Anda.

@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;
 }
}

Dan kemudian Anda dapat memanggil metode.

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

Atau atur nilai default apa pun ke sesuatu yang lain.

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

Pendekatan serupa dengan https://stackoverflow.com/a/13864910/2323964 yang berfungsi di Java 8 adalah dengan menggunakan antarmuka dengan getter default. Ini akan menjadi lebih banyak spasi putih, tetapi bisa dipermainkan, dan itu bagus untuk ketika Anda memiliki banyak contoh di mana Anda benar-benar ingin menarik perhatian pada parameter.

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; }
        });
    }
}
Novaterata
sumber
2

Saya sekarang telah menghabiskan cukup banyak waktu untuk mencari tahu bagaimana menggunakan ini dengan metode yang mengembalikan nilai, dan saya belum melihat contoh sejauh ini, saya pikir mungkin berguna untuk menambahkan ini di sini:

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

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

Beginilah cara saya melakukannya ... mungkin tidak semudah mungkin memiliki 'argumen opsional' terhadap parameter yang Anda tentukan, tetapi menyelesaikan pekerjaan:

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");
}

Perhatikan saya bisa memanggil nama metode yang sama hanya dengan string atau saya bisa memohonnya dengan string dan nilai boolean. Dalam hal ini, pengaturan wipeClean ke true akan mengganti semua teks di TextArea saya dengan string yang disediakan. Mengatur wipeClean ke false atau membiarkannya bersama-sama cukup menambahkan teks yang disediakan ke TextArea.

Perhatikan juga saya tidak mengulangi kode dalam dua metode, saya hanya menambahkan fungsionalitas untuk dapat mengatur ulang TextArea dengan membuat metode baru dengan nama yang sama hanya dengan boolean yang ditambahkan.

Saya benar-benar berpikir ini sedikit lebih bersih daripada jika Java memberikan 'argumen opsional' untuk parameter kita karena kita perlu kode untuk nilai-nilai default dll. Dalam contoh ini, saya tidak perlu khawatir tentang semua itu. Ya, saya telah menambahkan metode lain ke kelas saya, tetapi lebih mudah untuk membaca dalam jangka panjang menurut pendapat saya.

Michael Sims
sumber
1

TIDAK, Tapi kami punya alternatif dalam bentuk fungsi kelebihan beban.

dipanggil ketika tidak ada parameter yang dilewati

void operation(){

int a = 0;
int b = 0;

} 

dipanggil ketika "a" parameter dilewatkan

void operation(int a){

int b = 0;
//code

} 

dipanggil ketika parameter b berlalu

void operation(int a , int b){
//code
} 
Umair Khalid
sumber
1

Ada setengah lusin masalah atau lebih baik seperti ini, pada akhirnya, Anda tiba di pola pabrik statis ... lihat API crypto untuk itu. Agak sulit untuk dijelaskan, tetapi pikirkan seperti ini: Jika Anda memiliki konstruktor, default atau sebaliknya, satu-satunya cara untuk menyebarkan keadaan di luar kurung kurawal adalah dengan memiliki Boolean yang valid; (bersama dengan null sebagai nilai default v gagal konstruktor) atau melemparkan pengecualian yang tidak pernah informatif ketika mendapatkannya kembali dari pengguna bidang.

Terkutuklah kode, saya menulis ribuan konstruktor garis dan melakukan apa yang saya butuhkan. Saya menemukan menggunakan isValid pada konstruksi objek - dengan kata lain, konstruktor dua baris - tetapi untuk beberapa alasan, saya bermigrasi ke pola pabrik statis. Saya sepertinya Anda bisa melakukan banyak hal jika Anda dalam pemanggilan metode, masih ada masalah sync () tetapi default dapat 'diganti' lebih baik (lebih aman)

Saya pikir apa yang perlu kita lakukan di sini adalah mengatasi masalah nol sebagai nilai default vis-a-vis sesuatu String one = new String (""); sebagai variabel anggota, kemudian melakukan pemeriksaan untuk null sebelum menetapkan string yang diteruskan ke konstruktor.

Sangat luar biasa jumlah ilmu komputer stratosfer mentah yang dilakukan di Jawa.

C ++ dan seterusnya memiliki lib vendor, ya. Java dapat berlari lebih cepat dari mereka di server skala besar karena itu adalah kotak peralatan besar. Pelajari blok penginisialisasi statis, tetap bersama kami.

Nicholas Jordan
sumber
1

Ini tidak didukung di java seperti dalam bahasa lain untuk ex. Kotlin.

Virendra Pal Singh
sumber
0

Anda dapat menggunakan berikut-

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
Sobhit Sharma
sumber