Необязательные параметры в Java

Как использовать дополнительные параметры в Java? Какая спецификация поддерживает дополнительные параметры?

16 ответов


varargs может сделать это (в некотором роде). Кроме этого, необходимо указать все переменные в объявлении метода. Если вы хотите, чтобы переменная была необязательной, вы можете перегрузить метод, используя подпись, которая не требует параметра.

private boolean defaultOptionalFlagValue = true;

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

public void doSomething() {
    doSomething(defaultOptionalFlagValue);
}

существует несколько способов моделирования необязательных параметров в Java:

  1. перегрузка методов.

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

    одним из ограничений этого подхода является то, что он не работает, если у вас есть два дополнительных параметра одного типа, и любой из них можно опустить.

  2. С varargs.

    a) все опционные параметры такого же типа:

    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) типы необязательные параметры могут отличаться:

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

    основным недостатком этого подхода является то, что если необязательные параметры имеют разные типы, вы теряете статическую проверку типа. Кроме того, если каждый параметр имеет разное значение, вам нужно каким-то образом их различать.

  3. Nulls. чтобы устранить ограничения предыдущих подходов, вы можете разрешить нулевые значения, а затем проанализировать каждый параметр в теле метода:

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

    теперь все значения аргументов должны быть предоставлены, но по умолчанию они могут быть null.

  4. дополнительный класс. этот подход похож на nulls, но использует дополнительный класс Java 8 для параметров, которые имеют значение по умолчанию:

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

    необязательно делает контракт метода явным для вызывающего абонента, однако можно найти такую подпись слишком многословной.

    обновление: Java 8 включает класс java.util.Optional из коробки, поэтому никакая потребность использовать гуава для этой цели в Java 8. Однако имя метода немного отличается.

  5. шаблон строителя. шаблон builder используется для конструкторов и реализуется путем введения отдельного класса 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. карты. когда количество параметров слишком велико и для большинства из них обычно используются значения по умолчанию, вы можете передать аргументы метода в виде карты их имена/значения:

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

обратите внимание, что вы можете комбинировать любой из этих подходов, чтобы добиться желаемого результата.


Вы можете использовать что-то вроде этого:

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

на params переменной не является обязательным. Он рассматривается как nullable массив объектов.

странно, я ничего не мог найти об этом в документации, но он работает!

Это "новое" в Java 1.5 и выше (не поддерживается в Java 1.4 или более ранней версии).

Я вижу, что пользователь bhoot упомянул об этом ниже.


есть дополнительные параметры с Java 5.0. Просто объявите свою функцию следующим образом:

public void doSomething(boolean... optionalFlag) {
    //default to "false"
    //boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}

вы можете позвонить с doSomething(); или doSomething(true); сейчас.


к сожалению, Java не поддерживает параметры по умолчанию напрямую.

однако я написал набор аннотаций JavaBean, и один из них поддерживает параметры по умолчанию, такие как:

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

обработчик аннотаций генерирует перегрузки метода для правильной поддержки этого.

см.http://code.google.com/p/javadude/wiki/Annotations

полный пример в http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample


в Java нет дополнительных параметров. Вы можете перегрузить функции, а затем передать значения по умолчанию.

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

// Overload
void SomeMethod(int age) {
    SomeMethod(age, "John Doe");
}

были упомянуты VarArgs и перегрузка. Другой вариант шаблона, который будет выглядеть примерно так:

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

хотя этот шаблон будет наиболее подходящим для того, когда вам нужны дополнительные параметры в конструкторе.


в JDK>1.5 вы можете использовать его как это:

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

Это будет зависеть от того, чего вы хотите достичь, varargs или перегрузка метода должны решить большинство сценариев.

но имейте в виду, чтобы не перегружать метод использования. это приводит в замешательство.


короткая версия :

используя три точки:

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

(на основе ответа @VitaliiFedorenko)


вы можете сделать это, используя метод перегрузки, как это.

 public void load(String name){ }

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

также вы можете использовать аннотацию @нам!--4-->

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

просто передать null в качестве первого параметра.

Если вы передаете переменную того же типа, вы можете использовать это

public void load(String name...){}

перегрузка в порядке, но если есть много переменных, которым нужно значение по умолчанию, вы получите :

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

поэтому я бы предложил использовать аргумент переменной, предоставленный Java. Вот ссылке для объяснения.


Java теперь поддерживает optionals в 1.8, я застрял с программированием на android, поэтому я использую nulls, пока не смогу рефакторировать код для использования дополнительных типов.

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

Object optionalObject = canBeNull();
if (optionalObject != null) {
    // new object returned
} else {
    // no new object returned
}

вы можете использовать класс, который работает как строитель, чтобы содержать ваши необязательные значения.

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

как

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

выход

someString = something, someInt = 5

чтобы пропустить все необязательные значения, вам нужно будет назвать его как foo(o -> {}); или если вы предпочитаете, вы можете создать второй foo() метод, который не принимает необязательные параметры.

используя этот подход, вы можете указать дополнительные значения в произвольном порядке без какой-либо двусмысленности. Вы также можете иметь параметры разных классов в отличие от varargs. Этот подход будет еще лучше, если вы можете использовать аннотации и генерацию кода для создания класса Options.


аргументы по умолчанию не могут использоваться в Java и C#. Где в C++ и Python мы можем их использовать..

в Java, мы должны использовать 2 метода (функции), а не с параметрами по умолчанию.

пример:

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-


мы можем сделать необязательный параметр методом перегрузки или с помощью типа данных...

|*| перегрузка метода :

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

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

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

самый простой способ-это

|*| тип данных... может быть необязательным параметром

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

    // |* CodTdo *|
    return RetVar;
}