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


1661

Я наткнулся на некоторый код 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 этот вид синтаксиса? Есть ли причины, по которым этот двухэтапный синтаксис предпочтительнее?


85
Нет. Однако шаблон Builder может помочь.
Дейв Джарвис

50
Я действительно скучаю по этой функции. Это очень помогает при изменении существующего кода, чтобы получить дополнительный параметр для функции или конструктора
Jatin

4
@Jatin С помощью рефакторинга Eclipse «Изменить сигнатуру метода» вы можете добавить параметр и указать значение по умолчанию, которое будут использовать существующие инициаторы.
Эрвин Болвидт

2
@ErwinBolwidt Спасибо. Я использую Android Studio, и он также имеет возможность рефакторинга метода и предоставления значений по умолчанию. Довольно полезно
Джатин

3
@tegoti_user_name public MyParameterizedFunction(String param1, int param2)- это конструктор, а не метод, объявление.
Марио Исхак

Ответы:


955

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

Конструкторы см. В разделе 1 «Эффективная Java: Руководство по языку программирования» (рассмотрим статические фабричные методы вместо конструкторов), если перегрузка усложняется. Для других методов может помочь переименование некоторых случаев или использование объекта параметра. Это когда у вас достаточно сложности, чтобы дифференцировать сложно. Определенный случай, когда вы должны различать, используя порядок параметров, а не только число и тип.



135
@JarrodRoberson: Статические фабричные методы не более вредны, чем new. Они используются все время в новом коде. Построители простых объектов значений часто являются результатом чрезмерного проектирования.
Ли

12
@JarrodRoberson: Интересный способ принудительного использования через компилятор, спасибо, что поделились! Дружественное предложение для будущих постов: 300 строк некомментированного исходного кода для большинства людей, вероятно, немного сложнее (в конце концов, код сложнее читать, чем писать). Еще раз спасибо!
Кристиан Айхингер,

17
@JarrodRoberson: Хорошо, с нетерпением жду этого! То, что я хотел сообщить: как читатель вашего блога, пример из 50 строк с кратким текстовым описанием того, что происходит, поможет мне более 300 строк без контекста.
Кристиан Айхингер,

8
@ user177800 Не согласен - статические методы, если они написаны как чистые функции, вполне хороши. Это когда статическая функция изменяет состояние, что они становятся проблемой ...
Леви Фуллер

642

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

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

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

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


142
Наконец, отличный пример шаблона «Строитель» размером менее 2 страниц.
Невверминд

14
Мне любопытно, зачем нам нужен класс построителя при использовании шаблона построителя. Я думал о Студенте s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr. Hand);
ivanceras

52
@ivanceras: это актуально, когда у классов есть обязательные поля, и вы не хотите иметь возможность создавать экземпляры этих классов в недопустимом состоянии. Так что, если бы вы только что сказали Student s1 = new Student().age(16);, это оставило бы вас со студентом без имени, что могло бы быть плохо. Если это не плохо, то ваше решение в порядке.
Эли Кортрайт

57
@ivanceras: еще одна причина в том, что вы можете захотеть, чтобы ваш класс был неизменным после создания, поэтому вам не нужны методы, которые изменяют его значения.
Жюль

3
@ivanceras: я использовал Builders для 3 вещей - устранение множественных аргументов и плавной инициализации, неизменности и, что наиболее важно, я чувствую, чтобы проверить объект домена в методе build (). Зачем создавать экземпляр объекта, если он недопустим. Вы также можете перегрузить статический фабричные методы, как в приведенном выше случае buildFreshman (), buildSenior () и т. д.
Abhijeet Kushe

485

Есть несколько способов симулировать параметры по умолчанию в 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. С переменным числом аргументов.

    а) Все необязательные параметры имеют одинаковый тип:

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

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

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

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

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

  4. Необязательный класс. Этот подход аналогичен пустым значениям, но использует необязательный класс 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());

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

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

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


1
Хорошее объяснение. Я никогда не видел, чтобы возвращаемые значения использовались так. Для 5) что return thisделать? Кроме того, не FooBuilder().setA("a").build();так ли (по определению) конструктор вызывается первым и FooBuilder()возвращает значение, не значит .setA("a"):ли это, что у него нет возможности быть вызванным?
Celeritas

3
@Celeritas return thisвозвращает тот же объект, для которого был вызван метод (в примере, FooBuilder). Это позволяет объединять методы в одном выражении, действующем для одного и того же объекта: и new FooBuilder().setA(..).setB(..).setC(..)т. Д., А не вызывать каждый метод в отдельном выражении.
ADTC

2
@Celeritas new FooBuilder()возвращает FooBuilderобъект, для которого setAвызывается метод. Как setBне вызывается, this.bсохраняет значение по умолчанию. Наконец buildметод вызывается для этого FooBuilderобъекта. buildМетод создает и возвращает Fooобъект , который устанавливается в переменную Foo foo. Обратите внимание, что FooBuilderобъект не хранится ни в одной переменной.
ADTC

Аннотация также может использоваться для создания параметров по умолчанию и наиболее полезна, когда это требуется для полиморфных коллекций. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Мартин Спамер,

1
Более 900 голосов против одного ответа на два вопроса. Я впечатлен: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331

256

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


34
Это так грустно? Это может привести к появлению потенциально неоднозначных сигнатур функций.
Трей

69
@Trey: языки с параметрами по умолчанию часто перегружают функции, так как тогда они менее привлекательны. Так что никакой двусмысленности. Кроме того, Scala добавила функцию в 2.8 и каким-то образом решила проблему неоднозначности (поскольку они сохраняли перегрузку по причинам совместимости).
Филу

32
Я не вижу, как параметры по умолчанию предотвращают перегрузку функций. Например, C # позволяет переопределять, а также позволяет инициализировать по умолчанию. Похоже на произвольный выбор, а не ограничение является причиной.
FlavorScape

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

28
@ user562566: Всякий раз, когда я работаю над проектом Java, у меня складывается впечатление, что разработчики Java платят / измеряют по тому, сколько строк кода они производят в день
Марк К Коуэн,

83

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

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

может быть написано в Java 1.5 как:

void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    bool param3 = params.length > 0 ? params[0].booleanValue() : false;
}

Но стоит ли вам зависеть от того, как вы относитесь к компилятору, генерирующему

new Boolean[]{}

за каждый звонок.

Для нескольких параметров по умолчанию:

void MyParameterizedFunction(String param1, int param2, bool param3=false, int param4=42) {}

может быть написано в Java 1.5 как:

void MyParameterizedFunction(String param1, int param2, Object... p) {
    int l = p.length;
    assert l <= 2;
    assert l < 1 || Boolean.class.isInstance(p[0]);
    assert l < 2 || Integer.class.isInstance(p[1]);
    bool param3 = l > 0 && p[0] != null ? ((Boolean)p[0]).booleanValue() : false;
    int param4 = l > 1 && p[1] != null ? ((Integer)p[1]).intValue() : 42;
}

Это соответствует синтаксису C ++, который допускает параметры по умолчанию только в конце списка параметров.

Помимо синтаксиса, есть различие, когда в нем есть проверка типов во время выполнения для переданных по умолчанию параметров, а тип C ++ проверяет их во время компиляции.


14
Умно, но varargs (...) можно использовать только для конечного параметра, который более ограничен, чем те языки, которые поддерживают параметры по умолчанию.
CurtainDog

6
это умно, но немного грязно по сравнению с версией C ++
Someone Somewhere

5
Java определенно нужны необязательные параметры по умолчанию, так как C # и другие позволяют ... синтаксис очевиден, и я предполагаю, что они могут реализовать это довольно просто, даже просто компилируя все возможные комбинации ... Я не могу представить, почему они не добавили его в язык еще!
JWL

10
Никогда не следует использовать assertв производственном коде. Брось исключение.
Майкл Дорст

5
-1 Это действительно не то, для чего нужен varargs. Это взломать - в этом случае использование перегрузок будет более читабельным (что не очень хорошо, поскольку три дополнительных символа более читабельны, чем 5 дополнительных строк исходного текста ...). - но Java не поддерживает параметры по умолчанию.
BrainSlugs83

38

Нет, но вы можете очень легко подражать им. Что в C ++ было:

public: void myFunction(int a, int b=5, string c="test") { ... }

В Java это будет перегруженная функция:

public void myFunction(int a, int b, string c) { ... }

public void myFunction(int a, int b) {
    myFunction(a, b, "test");
}

public void myFunction(int a) {
    myFunction(a, 5);
}

Ранее упоминалось, что параметры по умолчанию вызывали неоднозначные случаи перегрузки функций. Это просто не соответствует действительности, мы можем видеть в случае с C ++: да, возможно, он может создавать неоднозначные случаи, но эти проблемы могут быть легко решены. Он просто не был разработан в Java, возможно, потому, что создатели хотели гораздо более простой язык, чем был C ++ - если они имели право, это другой вопрос. Но большинство из нас не думают, что он использует Java из-за его простоты.


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

1
@KolyaIvankov Я не знаю C #, но я знаю C ++, где рассуждения такие же. Я не знаю, что лучше, но я думаю, что на самом деле тот же самый шаблонный код генерируется компилятором в случае C ++ / C #, и он входит в окончательный двоичный файл.
Петер - Восстановить Монику

5
Каждый язык программирования является (в частности) средством, позволяющим обойти шаблон Ассемблера, я не прав? Вопрос только в том, дает ли он удобную функциональность или нет.
Коля Иванков

2
Первое предложение - риторический вопрос. Слово «вопрос» во втором предложении не имеет ничего общего с риторическим вопросом в первом.
Коля Иванков

1
Точнее говоря: языки - это инструменты, которые позволяют нам писать программы так, чтобы мы могли контролировать то, что написано, компиляция - это способ сообщить машине, чего мы от нее хотим. Инструмент более полезен, если он позволяет нам избегать шаблонов. По сути, gnavi спросил, могут ли они точно избежать того типового кода, который вы предлагаете в качестве ответа, поскольку C # допускает это.
Коля Иванков

24

Вы можете сделать это в Scala, которая работает на JVM и совместима с Java-программами. http://www.scala-lang.org/

т.е.

class Foo(var prime: Boolean = false, val rib: String)  {}

58
Привести совершенно новый язык, чтобы получить одну не очень общую черту?
om-nom-nom

8
@ om-nom-nom: Java никогда не должно существовать. Заявление о том, что функция не используется, равнозначно тому, что никому не нужно, это говорит о том, что Java не была популярна до ее изобретения, означает, что Гослинг не должен начинать ее разработку.
Val

28
@Val просто говорю, что это похоже на стрельбу из пушек
om-nom-nom

8
это не имеет никакого отношения к вопросу ОП
дестан

Работает и в Котлине. И Groovy. И C #. И Javascript. И почти все остальные языки, которые созданы для реальных людей и проблем.
Spyro

17

Нет , но самый простой способ реализовать это :

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    param3 = param3 == null ? false : param3;
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

или вместо троичного оператора вы можете использовать if:

public myParameterizedFunction(String param1, int param2, Boolean param3) {

    if (param3 == null) {
        param3 = false;
    }
}

public myParameterizedFunction(String param1, int param2) {

    this(param1, param2, false);
}

2
Да, этот подход кажется лучшим из других альтернатив. Тем не менее, было бы неплохо для Java принять значения по умолчанию; Котлин показал, что это можно сделать, поэтому я не уверен, почему Oracle не входит в современную эпоху и продолжает разрабатывать Java, как если бы это было в 1990-х годах. : D
Шев

13

Я мог бы заявить об очевидном здесь, но почему бы просто не реализовать параметр «по умолчанию» самостоятельно?

public class Foo() {
        public void func(String s){
                func(s, true);
        }
        public void func(String s, boolean b){
                //your code here
        }
}

по умолчанию вы должны использовать

func("my string");

и если вы не хотите использовать значение по умолчанию, вы бы использовали

func("my string", false);

11
Постер спросил, можно ли избежать этого (довольно уродливого) паттерна ... ;-) В более современных языках (таких как c #, Scala) вам не нужны эти дополнительные перегрузки, которые только создают больше строк кода. До некоторой степени вы можете использовать varargs тем временем (static int max (int ... array) {}), но они являются лишь очень уродливым решением.
Оффлер

2
Перегрузка не безобразна и имеет много преимуществ, например, различные вызовы методов с разными сигнатурами могут выполнять разные функции. //This is better public class Foo() { /* This does something */ public void func(String s){ //do something } /* This does something else with b */ public void func(String s, boolean b){ // b was passed } } //Than this public class Foo() { /* This does something unless b = value, then it does something else */ public void func(String s, boolean b = value){ If (b){ // Do Something } else{ // Do something else } } }
Энтони Бут

Хорошо, если кто-то хочет другого поведения. Если единственным отличием является небольшое изменение в вычислениях и т. Д., То создание нескольких подписей является пустой тратой усилий. Значения по умолчанию имеют смысл там, где они вам нужны ... и их отсутствие не следует классифицировать как "бесполезное" требование.
Капил

Параметры по умолчанию @Offler не имеют ничего общего с «современным языком». Я использовал их в Delphi 20 лет назад, и они, вероятно, уже существовали в Turbo Pascal.
Невероятное

Я согласен с Оффлером и не согласен с Энтони Бутом. Я нахожу это не только уродливым, но и довольно неэффективным. Такие языки, как ruby ​​или python, упрощают использование параметров по умолчанию; Я думаю, что Java требует от вас, чтобы найти (и использовать) обходные пути. Ясно, что явная проверка по сравнению с нулем кажется наименее уродливым выбором, поскольку я могу также вызвать это из командной строки (просто ничего не предоставлять, а затем обработать вменяемый вариант); подход с перегрузкой операторов кажется ... очень многословным (например, как минимум +3 строки по сравнению с нулевой проверкой и больше строк, если код более сложный).
Шев

8

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

fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
    ...
}

Как и Scala, Kotlin работает на JVM и может быть легко интегрирован в существующие проекты Java.


6

Нет.

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


5

В общем, в Java нет большого (какого-либо) синтаксического сахара, так как они пытались создать простой язык.


26
Не совсем. Горькая правда в том, что у команды был плотный график, и у нее не было времени на синтаксический сахар. Зачем еще constи были gotoбы зарезервированы ключевые слова, у которых нет реализации? - Особенно constто, что я с горечью скучаю - finalэто не замена, и они это знали. - И если вы приняли осознанное решение никогда не внедрять, gotoвам не нужно резервировать ключевое слово. - А потом в Java Team обманули, сделав Label основанным breakи continueтаким же мощным, как Паскаль goto.
Мартин,

«Простой, объектно-ориентированный и Знакомые» была действительно цель проекта - см oracle.com/technetwork/java/intro-141325.html
mikera

1
Томджен сказал: «Нет. В общем, у Java нет большого (любого) синтаксического сахара, так как они пытались создать простой язык». Итак, вы говорите, что удаление большого количества ненужных функций из C ++ делает Java простым языком, а затем скажите мне, почему в Java есть переменные методы? Почему у него есть Varargs? Это не нужно, если вместо этого вы можете просто использовать массив объектов, я прав? Таким образом, varargs могут быть удалены из языка, потому что это не нужно. Это сделает Java проще, чем сейчас. Я прав? Перегрузка также может быть удалена, потому что у вас есть бесконечные имена для каждого метода.

1
и именно поэтому у нас есть весна и вещи, которые берут простой язык и превращают любой настоящий проект Java в кластерную смесь синтаксиса и шаблонов :-)
matanster

Принуждение разработчиков к шаблонному коду и сложным обходным путям - это не мое понимание слова «легко». myFunction (a, b = false, c = 3), это то, что я называю легким.
Spyro

5

Вместо использования:

void parameterizedMethod(String param1, int param2) {
    this(param1, param2, false);
}

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

Вы можете использовать дополнительные функции java, используя один метод:

void parameterizedMethod(String param1, int param2, @Nullable Boolean param3) {
    param3 = Optional.ofNullable(param3).orElse(false);
    //use all three parameters here
}

Основное отличие состоит в том, что вы должны использовать классы-обертки вместо примитивных типов Java, чтобы разрешить nullввод. Booleanвместо boolean, Integerвместо intи так далее.


4

Это не поддерживается, но есть несколько вариантов, например, использование шаблона объекта параметра с некоторым синтаксическим сахаром:

public class Foo() {
    private static class ParameterObject {
        int param1 = 1;
        String param2 = "";
    }

    public static void main(String[] args) {
        new Foo().myMethod(new ParameterObject() {{ param1 = 10; param2 = "bar";}});
    }

    private void myMethod(ParameterObject po) {
    }
}

В этом примере мы создаем ParameterObjectзначения по умолчанию и переопределяем их в разделе инициализации экземпляра класса.{ param1 = 10; param2 = "bar";}


3

Попробуйте это решение:

public int getScore(int score, Integer... bonus)
{
    if(bonus.length > 0)
    {
        return score + bonus[0];
    }

    return score;
}

3

Вы можете использовать Java Method Invocation Builder для автоматической генерации компоновщика со значениями по умолчанию.

Просто добавьте @GenerateMethodInvocationBuilder к классу или интерфейсу и @Default к параметрам в методах, где вы хотите использовать значения по умолчанию. Конструктор будет создан во время компиляции, используя значения по умолчанию, которые вы указали в своих аннотациях.

@GenerateMethodInvocationBuilder
public class CarService {
 public CarService() {
 }

 public String getCarsByFilter(//
   @Default("Color.BLUE") Color color, //
   @Default("new ProductionYear(2001)") ProductionYear productionYear,//
   @Default("Tomas") String owner//
 ) {
  return "Filtering... " + color + productionYear + owner;
 }
}

И тогда вы можете вызывать методы.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .invoke(instance);

Или установите любое другое значение по умолчанию.

CarService instance = new CarService();
String carsByFilter = CarServiceGetCarsByFilterBuilder.getCarsByFilter()//
  .withColor(Color.YELLOW)//
  .invoke(instance);

2

Аналогичный подход к https://stackoverflow.com/a/13864910/2323964, который работает в Java 8, заключается в использовании интерфейса с получателями по умолчанию. Это будет более детализированный пробел, но это будет насмешливо, и это здорово, когда у вас есть куча примеров, когда вы действительно хотите привлечь внимание к параметрам.

public class Foo() {
    public interface Parameters {
        String getRequired();
        default int getOptionalInt(){ return 23; }
        default String getOptionalString(){ return "Skidoo"; }
    }

    public Foo(Parameters parameters){
        //...
    }

    public static void baz() {
        final Foo foo = new Foo(new Person() {
            @Override public String getRequired(){ return "blahblahblah"; }
            @Override public int getOptionalInt(){ return 43; }
        });
    }
}

2

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

int foo(int a) {
    // do something with a
    return a;
}

int foo() {
    return foo(0); // here, 0 is a default value for a
}

1

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

public void postUserMessage(String s,boolean wipeClean)
{
    if(wipeClean)
    {
        userInformation.setText(s + "\n");
    }
    else
    {
        postUserMessage(s);
    }
}

public void postUserMessage(String s)
{
    userInformation.appendText(s + "\n");
}

Заметьте, что я могу вызвать одно и то же имя метода либо просто строкой, либо я могу вызвать его со строкой и логическим значением. В этом случае установка wipeClean в значение true заменит весь текст в моей TextArea указанной строкой. Если установить для параметра wipeClean значение false или оставить все вместе, просто добавьте предоставленный текст в TextArea.

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

Я на самом деле думаю, что это немного чище, чем если бы Java предоставил «необязательный аргумент» для наших параметров, поскольку нам нужно было бы затем кодировать значения по умолчанию и т. Д. В этом примере мне не нужно беспокоиться об этом. Да, я добавил еще один метод в свой класс, но, по моему скромному мнению, в долгосрочной перспективе его легче читать.


1

НЕТ, но у нас есть альтернатива в виде перегрузки функций.

вызывается, когда не передан ни один параметр

void operation(){

int a = 0;
int b = 0;

} 

вызывается при передаче параметра "a"

void operation(int a){

int b = 0;
//code

} 

вызывается при передаче параметра b

void operation(int a , int b){
//code
} 

1

Есть полдюжины или более проблем, таких как эта, в конце концов, вы получите статический шаблон фабрики ... см. API шифрования для этого. Сортировать сложно объяснить, но думайте об этом так: если у вас есть конструктор, по умолчанию или другой, единственный способ распространить состояние за пределы фигурных скобок - это либо иметь логическое значение isValid; (вместе со значением NULL в качестве значения по умолчанию v конструктор с ошибкой) или сгенерировать исключение, которое никогда не будет информативным при получении его от полевых пользователей.

Будь проклят код, я пишу тысячи конструкторов строк и делаю то, что мне нужно. Я использую isValid при построении объектов - другими словами, двухстрочные конструкторы - но по какой-то причине я перехожу на статический шаблон фабрики. Я просто думаю, что вы можете многое сделать, если вы в вызове метода, все еще есть проблемы с sync (), но значения по умолчанию можно «заменить» лучше (безопаснее)

Я думаю, что здесь нам нужно решить проблему с нулем как значение по умолчанию для чего-то String one = new String (""); в качестве переменной-члена, затем выполняет проверку на нулевое значение, прежде чем присваивать строку, переданную в конструктор.

Весьма примечательно, что на Яве сделано огромное количество необработанных стратосферных компьютерных наук.

C ++ и т. Д. Имеет библиотеки поставщика, да. Java может опередить их на крупных серверах, потому что это огромный набор инструментов. Изучите статические блоки инициализатора, оставайтесь с нами.



Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.