16 ответов:
С varargs может сделать это (в сторону). Кроме этого, все переменные в объявлении метода должны быть предоставлены. Если вы хотите, чтобы переменная была необязательной, вы можете перегрузить метод с помощью подписи, которая не требует параметра.
private boolean defaultOptionalFlagValue = true; public void doSomething(boolean optionalFlag) { ... } public void doSomething() { doSomething(defaultOptionalFlagValue); }
существует несколько способов моделирования необязательных параметров в Java:
перегрузка методов.
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");одним из ограничений этого подхода является то, что он не работает, если у вас есть два необязательных параметра того же типа, и любой из них может быть опущен.
С 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);б) типов необязательные параметры могут быть разными:
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");основным недостатком этого подхода является то, что если необязательные параметры имеют разные типы, вы теряете статическую проверку типа. Кроме того, если каждый параметр имеет разное значение, вам нужно каким-то образом их различать.
нулями. чтобы устранить ограничения предыдущих подходов, вы можете разрешить нулевые значения, а затем проанализировать каждый параметр в теле метода:
void foo(String a, Integer b, Integer c) { b = b != null ? b : 0; c = c != null ? c : 0; //... } foo("a", null, 2);теперь все значения аргументов должны быть предоставлены, но значения по умолчанию могут быть null.
дополнительный класс. этот подход похож на null, но использует 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());Optional делает контракт метода явным для вызывающего абонента, однако, можно найти такую подпись слишком многословной.
обновление: Java 8 включает класс
java.util.Optionalиз коробки, поэтому нет необходимости использовать гуаву для именно по этой причине в java 8. Имя метода немного отличается, хотя.шаблон строителя. шаблон 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();карты. когда число параметров слишком велико и для большинства из них обычно используются значения по умолчанию, вы можете передать аргументы метода в виде карты их имена/значения:
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) { }The
paramsпеременной не является обязательным. Он рассматривается как массив объектов, допускающий значение null.странно, я не смог найти ничего об этом в документации, но это работает!
Это "новое" в 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, поэтому я использую null, пока не смогу рефакторинг кода для использования дополнительных типов.
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);
мы можем сделать необязательный параметр методом перегрузки или с помощью типа данных...
|*| перегрузка метода :
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; }
Comments