Вопрос-ответ

Does Java support default parameter values?

Поддерживает ли Java значения параметров по умолчанию?

Я наткнулся на некоторый Java-код, который имел следующую структуру:

public MyParameterizedFunction(String param1, int param2)
{
this(param1, param2, false);
}

public MyParameterizedFunction(String param1, int param2, boolean param3)
{
//use all three parameters here
}

Я знаю, что в C ++ я могу присвоить параметру значение по умолчанию. Например:

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

Поддерживает ли Java такой синтаксис? Есть ли какие-либо причины, по которым этот двухэтапный синтаксис предпочтительнее?

Переведено автоматически
Ответ 1

Нет, структура, которую вы нашли, заключается в том, как Java обрабатывает это (то есть с перегрузкой вместо параметров по умолчанию).

Что касается конструкторов, смотрите в разделе "Эффективная Java: руководство по языку программирования" в пункте 1 совета (рассматривайте статические заводские методы вместо конструкторов), если перегрузка становится сложной. Для других методов может помочь переименование некоторых вариантов или использование объекта parameter.

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

Ответ 2

Нет, но вы можете использовать шаблон Builder, как описано в этом ответе Stack Overflow.

Как описано в связанном ответе, шаблон Builder позволяет писать код, подобный

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
.name("Spicoli")
.age(16)
.motto("Aloha, Mr Hand")
.buildStudent();

в котором некоторые поля могут иметь значения по умолчанию или иным образом быть необязательными.

Ответ 3

Существует несколько способов имитации параметров по умолчанию в Java:


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


    void foo(Строка a, целое число b) { //... }


    void foo(строка a) { foo(a, 0); // здесь 0 - значение по умолчанию для b }


    foo("a", 2); foo("a");



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


  1. Переменные.

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

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


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


    void foo(Строка a, целое число b, целое число c) { b = b != null? b: 0; c = c != null? c: 0; //... }


    foo("a", null, 2);



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


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


    void foo(строка a, необязательно bOpt) { Целое число b = bOpt.OrElse(0); //... }


    foo("a", необязательно.из(2)); foo("a", необязательно.отсутствует());


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



  2. Шаблон Builder. Шаблон 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();


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


    void foo(Map<Строка, объект> параметры) { Строка a = ""; Целое число b = 0; if (parameters.containsKey("a")) { if (!(parameters.get("a") экземпляр целого числа)) { создать новое исключение IllegalArgumentException("..."); } a = (Строка)parameters.get("a"); } else if (parameters.containsKey("b")) { //... } //... }


    foo(ImmutableMap.<Строка, объект>of( "a", "a", "b", 2, "d", "value"));



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

Ответ 4

К сожалению, нет.

2023-06-25 23:58 java