Java opcjonalne parametry

Jak używać opcjonalnych parametrów w Javie? Jaka Specyfikacja obsługuje opcjonalne parametry?

Author: Mike Pone, 2009-06-08

16 answers

Varargs mógłby to zrobić (w pewien sposób). Poza tym należy podać wszystkie zmienne w deklaracji metody. Jeśli chcesz, aby zmienna była opcjonalna, możesz przeciążyć metodę za pomocą podpisu, który nie wymaga parametru.

private boolean defaultOptionalFlagValue = true;

public void doSomething(boolean optionalFlag) {
    ...
}

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}
 416
Author: laginimaineb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-20 10:27:13

Istnieje kilka sposobów symulowania opcjonalnych parametrów w Javie:

  1. Metoda przeciążenia.

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

    Jednym z ograniczeń tego podejścia jest to, że nie działa, jeśli masz dwa opcjonalne parametry tego samego typu i każdy z nich można pominąć.

  2. Varargs.

    A) wszystkie opcjonalne parametry są tego samego typu:

    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) typy parametrów opcjonalnych mogą być różne:

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

    Główny wadą tego podejścia jest to, że jeśli opcjonalne parametry są różnych typów, tracisz sprawdzanie typu statycznego. Ponadto, jeśli każdy parametr ma inne znaczenie, musisz w jakiś sposób je rozróżnić.

  3. Nulls. aby rozwiązać ograniczenia poprzednich podejść, możesz zezwolić na wartości null, a następnie przeanalizować każdy parametr w ciele metody:

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

    Teraz muszą być podane wszystkie wartości argumentów, ale domyślne mogą być null.

  4. Klasa opcjonalna. to podejście jest podobne do NULL, ale używa opcjonalnej klasy Java 8 dla parametrów, które mają wartość domyślną:

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

    Opcjonalne sprawia, że umowa metody jest jednoznaczna dla rozmówcy, jednak może się okazać, że taki podpis jest zbyt gadatliwy.

    Update: Java 8 zawiera klasę java.util.Optional po wyjęciu z pudełka, więc nie ma potrzeby używania guava z tego konkretnego powodu w Javie 8. Nazwa metody jest nieco inna chociaż.

  5. Wzór budowniczego. wzorzec builder jest używany dla konstruktorów i jest zaimplementowany poprzez wprowadzenie oddzielnej klasy Builder:

     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. Mapy. gdy liczba parametrów jest zbyt duża i dla większości z nich zwykle używane są wartości domyślne, można przekazać argumenty metody jako mapę ich nazw/wartości:

    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 = (Integer)parameters.get("a");
        }
        if (parameters.containsKey("b")) { 
            //... 
        }
        //...
    }
    
    foo(ImmutableMap.<String, Object>of(
        "a", "a",
        "b", 2, 
        "d", "value")); 
    

Należy pamiętać, że można połączyć dowolne z tych podejść, aby osiągnąć pożądany wynik.

 1420
Author: Vitalii Fedorenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-02 02:36:14

Możesz użyć czegoś takiego:

public void addError(String path, String key, Object... params) { 
}

Zmienna params jest opcjonalna. Jest traktowana jako nullable tablica obiektów.

O dziwo, nie mogłem znaleźć nic na ten temat w dokumentacji, ale to działa!

Jest to "nowość" w Javie 1.5 i nowszej (nie jest obsługiwane w Javie 1.4 lub wcześniejszej).

Widzę, że user bhoot wspomniał o tym również poniżej.

 96
Author: theninjagreg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-03 21:41:36

W Javie 5.0 są opcjonalne parametry. Po prostu zadeklaruj swoją funkcję w ten sposób:

public void doSomething(boolean... optionalFlag) {
    //default to "false"
    //boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
Możesz zadzwonić z doSomething(); lub doSomething(true); Teraz.
 88
Author: bhoot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-29 13:36:48

Niestety Java nie obsługuje bezpośrednio domyślnych parametrów.

Jednak napisałem zestaw adnotacji JavaBean, a jedna z nich obsługuje domyślne parametry, takie jak:

protected void process(
        Processor processor,
        String item,
        @Default("Processor.Size.LARGE") Size size,
        @Default("red") String color,
        @Default("1") int quantity) {
    processor.process(item, size, color, quantity);
}
public void report(@Default("Hello") String message) {
    System.out.println("Message: " + message);
}

Procesor adnotacji generuje przeciążenia metody, aby prawidłowo ją obsługiwać.

Zobacz http://code.google.com/p/javadude/wiki/Annotations

Pełny przykład na http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample

 47
Author: Scott Stanchfield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 17:00:09

Nie ma opcjonalnych parametrów w Javie. Możesz przeciążać funkcje, a następnie przekazywać wartości domyślne.

void SomeMethod(int age, String name) {
    //
}

// Overload
void SomeMethod(int age) {
    SomeMethod(age, "John Doe");
}
 43
Author: Dario,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 16:18:10

Warargi i przeciążenia zostały wymienione. Inną opcją jest wzorzec konstruktora, który wyglądałby mniej więcej tak:

 MyObject my = new MyObjectBuilder().setParam1(value)
                                 .setParam3(otherValue)
                                 .setParam6(thirdValue)
                                 .build();

Chociaż ten wzór byłby najbardziej odpowiedni, gdy potrzebujesz opcjonalnych parametrów w konstruktorze.

 21
Author: Yishai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-08 17:05:21

W JDK>1.5 można go używać w ten sposób;

public class NewClass1 {

    public static void main(String[] args) {

        try {
            someMethod(18); // Age : 18
            someMethod(18, "John Doe"); // Age & Name : 18 & John Doe
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void someMethod(int age, String... names) {

        if (names.length > 0) {
            if (names[0] != null) {
                System.out.println("Age & Name : " + age + " & " + names[0]);
            }
        } else {
            System.out.println("Age : " + age);
        }
    }
}
 12
Author: az3,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-24 10:44:38

To zależy od tego, co chcesz osiągnąć, varargs lub metody przeciążenia powinny rozwiązać większość scenariuszy.

Ale należy pamiętać, aby nie nadużywać metody przeciążenia. to wprowadza zamieszanie.

 8
Author: Marc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-22 10:19:36

Wersja skrócona:

Używając trzech kropek :

public void foo(Object... x) {
    String first    =  x.length > 0 ? (String)x[0]  : "Hello";
    int duration    =  x.length > 1 ? Integer.parseInt((String) x[1])     : 888;
}   
foo("Hii", ); 
foo("Hii", 146); 

(na podstawie odpowiedzi @ VitaliiFedorenko)

 5
Author: T.Todua,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 19:18:35

Możesz zrobić coś używając metody przeciążania w ten sposób.

 public void load(String name){ }

 public void load(String name,int age){}

Możesz również użyć adnotacji @ Nullable

public void load(@Nullable String name,int age){}

Po prostu podaj null jako pierwszy parametr.

Jeśli przekazujesz zmienną tego samego typu, możesz użyć tego

public void load(String name...){}
 4
Author: Ishan Fernando,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-19 11:33:36

Przeciążenie jest w porządku, ale jeśli istnieje wiele zmiennych, które wymagają wartości domyślnej, skończysz z :

public void methodA(A arg1) {  }
public void methodA( B arg2,) {  }
public void methodA(C arg3) {  }
public void methodA(A arg1, B arg2) {  }
public void methodA(A arg1, C arg3) {  }
public void methodA( B arg2, C arg3) {  }
public void methodA(A arg1, B arg2, C arg3) {  }

Proponuję więc użyć argumentu zmiennej dostarczonego przez Javę. Oto link do wyjaśnienia.

 2
Author: Jigar Shah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-16 02:24:37

Java obsługuje teraz opcje w 1.8, utknąłem z programowaniem na Androidzie, więc używam null, dopóki nie będę mógł refaktorować kodu, aby użyć opcjonalnych typów.

Object canBeNull() {
    if (blah) {
        return new Object();
    } else {
        return null;
    }
}

Object optionalObject = canBeNull();
if (optionalObject != null) {
    // new object returned
} else {
    // no new object returned
}
 1
Author: Pellet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-20 07:04:27

Możesz użyć klasy, która działa podobnie jak builder, aby zawierać opcjonalne wartości, takie jak ta.

public class Options {
    private String someString = "default value";
    private int someInt= 0;
    public Options setSomeString(String someString) {
        this.someString = someString;
        return this;
    }
    public Options setSomeInt(int someInt) {
        this.someInt = someInt;
        return this;
    }
}

public static void foo(Consumer<Options> consumer) {
    Options options = new Options();
    consumer.accept(options);
    System.out.println("someString = " + options.someString + ", someInt = " + options.someInt);
}

Użyj jak

foo(o -> o.setSomeString("something").setSomeInt(5));

Wyjście to

someString = something, someInt = 5

Aby pominąć wszystkie opcjonalne wartości, musisz wywołać je tak, jak foo(o -> {}); lub jeśli wolisz, możesz utworzyć drugą metodę foo(), która nie przyjmuje opcjonalnych parametrów.

Za pomocą tego podejścia można określić wartości opcjonalne w dowolnej kolejności bez żadnych niejasności. Można również mieć parametry różnych klas w przeciwieństwie do z varargsem. Takie podejście byłoby jeszcze lepsze, gdybyś mógł użyć adnotacji i generowania kodu do utworzenia klasy Options.

 1
Author: rybai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-15 23:49:01

Argumenty domyślne nie mogą być używane w Javie i C#. Gdzie w C++ i Pythonie możemy z nich korzystać..

W Javie musimy używać dwóch metod (funkcji) zamiast jednej z domyślnymi parametrami.

Przykład:

Stash(int size); 

Stash(int size, int initQuantity);

Http://parvindersingh.webs.com/apps/forums/topics/show/8856498-java-how-to-set-default-parameters-values-like-c-

 1
Author: Parvinder Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-11 14:22:33

Możemy wykonać opcjonalny parametr metodą przeciążenia lub za pomocą typu danych...

|*| metoda przeciążenia:

RetDtaTyp NamFnc(String NamPsgVar)
{
    // |* CodTdo *|
    return RetVar;
}

RetDtaTyp NamFnc(String NamPsgVar)
{
    // |* CodTdo *|
    return RetVar;
}

RetDtaTyp NamFnc(int NamPsgVar1, String NamPsgVar2)
{
    // |* CodTdo *|
    return RetVar;
}

Najprostszym sposobem jest

/ * / DataType... może być opcjonalnym parametrem

RetDtaTyp NamFnc(int NamPsgVar, String... SrgOpnPsgVar)
{
    if(SrgOpnPsgVar.length == 0)  SrgOpnPsgVar = DefSrgVar; 

    // |* CodTdo *|
    return RetVar;
}

 0
Author: Sujay U N,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 10:32:02