Відповіді:
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");
Одне з обмежень цього підходу полягає в тому, що він не працює, якщо у вас є два необов’язкові параметри одного типу і будь-який з них можна опустити.
Вараги.
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);
Тепер усі аргументи повинні бути надані, але типові значення можуть бути нульовими.
Необов’язковий клас. Цей підхід схожий на нулі, але використовує клас 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
поза вікном, тому немає необхідності використовувати guava саме з цієї причини в Java 8. Хоча назва методу дещо інша.
Шаблон будівельника. Схема конструктора використовується для конструкторів і реалізується шляхом введення окремого класу 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"));
У Java 9 такий підхід став простішим:
@SuppressWarnings("unchecked")
static <T> T getParm(Map<String, Object> map, String key, T defaultValue)
{
return (map.containsKey(key)) ? (T) map.get(key) : defaultValue;
}
void foo(Map<String, Object> parameters) {
String a = getParm(parameters, "a", "");
int b = getParm(parameters, "b", 0);
// d = ...
}
foo(Map.of("a","a", "b",2, "d","value"));
Зверніть увагу, що ви можете комбінувати будь-який із цих підходів для досягнення бажаного результату.
a
змінна - String (літ є правильним).
Є додаткові параметри з Java 5.0. Просто оголосьте свою функцію так:
public void doSomething(boolean... optionalFlag) {
//default to "false"
//boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}
ви могли б зателефонувати з doSomething();
або doSomething(true);
зараз.
doSomething() { doSomething(true); }
без масивів для вирішення, двозначності
Ви можете використовувати щось подібне:
public void addError(String path, String key, Object... params) {
}
params
Змінна є необов'язковим. Це трактується як нульовий масив Об'єктів.
Як не дивно, я нічого не міг знайти про це в документації, але це працює!
Це "нове" в Java 1.5 і вище (не підтримується в Java 1.4 або новіших версіях).
Я бачу, що користувач bhoot згадав про це теж нижче.
На жаль, 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/Анотації
Повний приклад на веб- сторінці http://code.google.com/p/javadude/wiki/AnnotationsDefaultParametersExample
Згадано про VarArgs та перевантаження. Ще один варіант - це модель Builder, яка виглядатиме приблизно так:
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);
}
}
}
Ви можете зробити щось, використовуючи такий метод перевантаження.
public void load(String name){ }
public void load(String name,int age){}
Також ви можете використовувати @Nullable анотацію
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. Ось посилання на пояснення.
Ви можете використовувати клас, який працює як конструктор, щоб містити такі необов'язкові значення, як це.
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. Цей підхід буде ще кращим, якщо ви можете використовувати анотації та генерацію коду для створення класу «Параметри».
Java тепер підтримує додаткові додатки в 1.8, я застряг у програмуванні на android, тому я використовую нулі, поки не зможу перефактурувати код для використання додаткових типів.
Object canBeNull() {
if (blah) {
return new Object();
} else {
return null;
}
}
Object optionalObject = canBeNull();
if (optionalObject != null) {
// new object returned
} else {
// no new object returned
}
Аргументи за замовчуванням не можна використовувати в Java. У C #, C ++ та Python ми можемо їх використовувати ..
У Java нам потрібно використовувати 2 способи (функції) замість одного із параметрами за замовчуванням.
Приклад:
Stash(int size);
Stash(int size, int initQuantity);
Це старе питання, можливо, ще до того, як було введено фактичний необов'язковий тип, але в наші дні ви можете врахувати декілька речей: - використовувати перевантаження методу - використовувати опціональний тип, який має перевагу уникнути передачі NULL навколо опціонального типу, введеного в Java 8 перед тим, як його зазвичай використовували від сторонніх власників, таких як гуава Google. Використання необов'язкових як параметрів / аргументів можна вважати надмірним використанням, оскільки основною метою було використання його як часу повернення.
Посилання: https://itcodehub.blogspot.com/2019/06/using-optional-type-in-java.html
Ми можемо зробити необов'язковий параметр методом перевантаження або використанням DataType ...
| * | Спосіб перевантаження:
RetDataType NameFnc(int NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(String NamePsgVar)
{
// |* Code Todo *|
return RetVar;
}
RetDataType NameFnc(int NamePsgVar1, String NamePsgVar2)
{
// |* Code Todo *|
return RetVar;
}
Найпростіший спосіб
| * | Тип даних ... може бути необов'язковим параметром
RetDataType NameFnc(int NamePsgVar, String... stringOpnPsgVar)
{
if(stringOpnPsgVar.length == 0) stringOpnPsgVar = DefaultValue;
// |* Code Todo *|
return RetVar;
}
RetDtaTyp
... серйозно? Є RetDataType
занадто важко надрукувати?
Якщо ви плануєте використовувати інтерфейс з декількома параметрами , можна скористатися наступною структурною схемою та застосувати або застосувати заміщення - метод, заснований на ваших вимогах .
public abstract class Invoker<T> {
public T apply() {
return apply(null);
}
public abstract T apply(Object... params);
}
Якщо це кінцева точка API, елегантним способом є використання анотацій "Весна":
@GetMapping("/api/foos")
@ResponseBody
public String getFoos(@RequestParam(required = false, defaultValue = "hello") String id) {
return innerFunc(id);
}
Зауважте в цьому випадку, що InternalFunc вимагатиме змінної, і оскільки це не кінцева точка api, не можна використовувати цю весняну примітку, щоб зробити її необов'язковою. Довідка: https://www.baeldung.com/spring-request-param