Pertanyaan Apakah Java mendukung nilai parameter default?


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? Apakah ada alasan mengapa sintaks dua langkah ini lebih baik?


1311
2018-06-15 18:04


asal


Jawaban:


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

Untuk konstruktor, Lihat Java Efektif: Panduan Bahasa Pemrograman Item 1 tip (Pertimbangkan metode pabrik statis daripada konstruktor) jika kelebihan muatan semakin rumit. Untuk metode lain, mengganti nama beberapa kasus atau menggunakan objek parameter dapat membantu. Ini adalah ketika Anda memiliki cukup kompleksitas yang membedakannya sulit. Kasus yang pasti adalah di mana Anda harus membedakan menggunakan urutan parameter, bukan hanya jumlah dan jenis.


757
2018-06-15 18:14



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

Seperti yang dijelaskan dalam jawaban yang terhubung, 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 sebaliknya opsional.


541
2018-06-15 19:20



Ada beberapa cara untuk mensimulasikan parameter default di Java:

  1. Metode overloading.

    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 keterbatasan dari pendekatan ini adalah bahwa itu tidak bekerja 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 jenis yang berbeda Anda kehilangan pemeriksaan tipe statis. Selanjutnya, jika setiap parameter memiliki arti yang berbeda, Anda memerlukan beberapa cara untuk membedakannya.

  3. Nulls. Untuk mengatasi keterbatasan pendekatan sebelumnya Anda dapat memperbolehkan nilai nol dan kemudian menganalisa setiap parameter dalam badan 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 null, 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 kontrak metode eksplisit untuk pemanggil, namun, orang mungkin menemukan tanda tangan tersebut terlalu verbose.

  5. Pola pembangun. Pola builder digunakan untuk konstruktor dan diimplementasikan dengan memperkenalkan kelas Builder 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. Maps. Ketika jumlah parameter terlalu besar dan untuk sebagian besar nilai default biasanya digunakan, Anda dapat meneruskan argumen metode sebagai peta nama / nilainya:

    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.


348
2017-11-01 02:03



Sayangnya tidak.


197
2018-06-15 18:05



Sayangnya ya.

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

bisa ditulis di 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 Anda merasa tentang compiler menghasilkan

new Boolean[]{}

untuk setiap panggilan.

Untuk beberapa parameter yang dapat dinonaktifkan:

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

bisa ditulis di 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 sintaks C ++, yang hanya mengizinkan parameter default di akhir daftar parameter.

Di luar sintaks, ada perbedaan di mana ini telah menjalankan pengecekan jenis waktu untuk parameter default yang dapat diteruskan dan tipe C ++ memeriksa mereka selama proses kompilasi.


76
2018-05-26 21:51



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, ini akan menjadi fungsi yang 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 overloading. Itu tidak benar, kita dapat melihat dalam kasus C ++: ya, mungkin itu bisa membuat kasus-kasus 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 Java karena kesederhanaannya.


35
2017-11-04 09:12



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

yaitu

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

19
2017-07-21 16:26



Saya mungkin menyatakan yang jelas di sini tetapi mengapa tidak hanya 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 default Anda akan menggunakan eter

func ("string saya");

dan jika Anda tidak ingin menggunakan default, Anda akan menggunakannya

func ("my string", false);


11
2018-02-18 13:59



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


6
2018-06-15 18:49



Tidak.

Anda dapat mencapai perilaku yang sama dengan mengirimkan Objek yang memiliki default cerdas. Tetapi sekali lagi itu tergantung pada kasus Anda.


6
2018-06-15 18:16



Ini 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 contoh ini kami membangun ParameterObject dengan nilai default dan menimpanya di kelas bagian inisialisasi kelas { param1 = 10; param2 = "bar";}


3
2017-12-13 17:09