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

Нет. Однако шаблон Builder может помочь.
Dave Jarvis 27.05.2010 02:58:11
Я очень скучаю по этой функции. Это очень помогает при изменении существующего кода, чтобы получить дополнительный параметр для функции или конструктора
Jatin 1.01.2015 07:25:36
@Jatin С помощью рефакторинга Eclipse «Изменить сигнатуру метода» вы можете добавить параметр и указать значение по умолчанию, которое будут использовать существующие инициаторы.
Erwin Bolwidt 12.01.2015 15:17:19
@ErwinBolwidt Спасибо. Я использую Android Studio, и он также имеет возможность рефакторинга метода и предоставления значений по умолчанию. Довольно полезно
Jatin 14.01.2015 11:40:15
@tevent_user_name public MyParameterizedFunction(String param1, int param2)- это конструктор, а не метод, объявление.
Mario Ishac 24.01.2019 22:49:28
23 ОТВЕТА
РЕШЕНИЕ

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

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

946
13.09.2013 17:12:48
@JarrodRoberson: Статические фабричные методы не более вредны, чем new. Они используются все время в новом коде. Создатели простых объектов значений часто являются результатом чрезмерного проектирования.
Lii 22.01.2016 08:38:05
@JarrodRoberson: Интересный способ принудительного использования через компилятор, спасибо, что поделились! Дружеское предложение для будущих постов: 300 строк некомментированного исходного кода, вероятно, немного усвоить большинству людей (в конце концов, код сложнее читать, чем писать). Еще раз спасибо!
Christian Aichinger 27.01.2016 21:55:16
@JarrodRoberson: Хорошо, с нетерпением жду этого! То, что я хотел сообщить: как читатель вашего блога, пример из 50 строк с кратким текстовым описанием того, что происходит, поможет мне более 300 строк без контекста.
Christian Aichinger 27.01.2016 22:12:33
@ user177800 Не согласен - статические методы, если они написаны как чистые функции, вполне хороши. Это когда статическая функция изменяет состояние, что они становятся проблемой ...
Levi Fuller 18.12.2018 03:47:07

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

253
15.06.2009 18:05:16
Это так грустно? Это может привести к появлению потенциально неоднозначных сигнатур функций.
Trey 15.06.2009 19:46:24
@Trey: языки с параметрами по умолчанию часто перегружают функции, так как тогда они менее привлекательны. Так что никакой двусмысленности. Кроме того, Scala добавила функцию в 2.8 и каким-то образом решила проблему неоднозначности (поскольку они сохраняли перегрузку по причинам совместимости).
PhiLho 24.05.2011 13:09:32
Я не вижу, как параметры по умолчанию предотвращают перегрузку функций. Например, C # позволяет переопределять, а также позволяет инициализировать по умолчанию. Похоже, произвольный выбор, а не ограничение является причиной.
FlavorScape 30.11.2013 17:43:34
Да, давайте сделаем компромисс, заставляя компилятор выполнять дополнительную работу, и вместо этого заставим всех нас написать 100000 перегрузок, чтобы обеспечить удобство работы наших пользователей библиотеки. Хорошая идея.
user562566 13.05.2014 08:02:49
@ user562566: Всякий раз, когда я работаю над проектом Java, у меня складывается впечатление, что разработчики Java платят / измеряют по тому, сколько строк кода они производят в день
Mark K Cowan 16.10.2016 20:38:24

Нет.

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

6
13.09.2013 17:13:45

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

6
15.06.2009 18:49:17
Не совсем. Горькая правда в том, что у команды был плотный график, и у нее не было времени на синтаксический сахар. Зачем еще constи были gotoбы зарезервированы ключевые слова, у которых нет реализации? - Особенно constто, что я с горечью скучаю - finalэто не замена, и они это знали. - И если вы приняли осознанное решение никогда не внедрять, gotoвам не нужно резервировать ключевое слово. - А потом в Java Team обманули, сделав Label основанным breakи continueтаким же мощным, как Pascal goto.
Martin 18.09.2011 12:46:23
«Простой, объектно-ориентированный и Знакомые» была действительно цель проекта - см oracle.com/technetwork/java/intro-141325.html
mikera 2.09.2013 09:27:37
Томджен сказал: «Нет. В общем, у Java нет большого (какого-либо) синтаксического сахара, так как они пытались создать простой язык». Итак, вы говорите, что удаление большого количества ненужных функций из C ++ делает Java простым языком, а затем скажите мне, почему в Java есть переменные методы? Почему у него есть Varargs? Это не нужно, если вместо этого вы можете просто использовать массив объектов, я прав? Таким образом, varargs могут быть удалены из языка, потому что это не нужно. Это сделает Java проще, чем сейчас. Я прав? Перегрузка также может быть удалена, потому что у вас есть бесконечные имена для каждого метода.
user2133061 8.08.2017 15:58:57
и именно поэтому у нас есть весна и вещи, которые берут простой язык и превращают любой настоящий проект Java в кластерную смесь синтаксиса и шаблонов :-)
matanster 17.08.2019 08:54:05

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

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

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

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

638
23.05.2017 12:34:53
Наконец, отличный пример шаблона «Строитель» размером менее 2 страниц.
nevvermind 8.11.2012 21:38:43
Мне любопытно, зачем нам нужен класс построителя при использовании шаблона построителя. Я думал о Студенте s1 = new Student (). Name ("Spicolo"). Age (16) .motto ("Aloha, Mr Hand);
ivanceras 14.02.2013 08:32:08
@ivanceras: это актуально, когда у классов есть обязательные поля, и вы не хотите создавать экземпляры этих классов в недопустимом состоянии. Так что, если бы вы только что сказали Student s1 = new Student().age(16);, это оставило бы вас со студентом без имени, что могло бы быть плохо. Если это не плохо, то ваше решение в порядке.
Eli Courtwright 14.02.2013 18:33:54
@ivanceras: другая причина в том, что вы, возможно, захотите, чтобы ваш класс был неизменным после создания, поэтому вам не нужны методы, которые изменяют его значения.
Jules 27.02.2013 16:02:36
@ivanceras: я использовал Builders для 3-х вещей - устранение множественных аргументов и плавной инициализации, неизменности и, самое главное, я чувствую, чтобы проверить объект домена в методе build (). Зачем создавать экземпляр объекта, если он недопустим. Вы также можете перегрузить static фабричные методы, как в вышеприведенном случае buildFreshman (), buildSenior () и т. д.
Abhijeet Kushe 16.08.2015 22:00:50

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

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

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

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

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

1
24.10.2019 20:44:49

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

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 ++ проверяет их во время компиляции.

83
3.10.2013 21:37:48
Умно, но varargs (...) можно использовать только для конечного параметра, который более ограничен, чем те языки, которые поддерживают параметры по умолчанию.
CurtainDog 26.05.2010 22:20:00
это умно, но немного грязно по сравнению с версией C ++
Someone Somewhere 4.11.2011 18:27:57
Java определенно нуждается в необязательных параметрах по умолчанию, поскольку C # и другие позволяют ... синтаксис очевиден, и я предполагаю, что они могут реализовать это довольно просто, даже просто компилируя все возможные комбинации ... Я не могу представить, почему они не добавили его в язык еще!
jwl 23.02.2012 23:31:30
Никогда не следует использовать assertв производственном коде. Брось исключение.
Michael Dorst 1.10.2013 18:52:22
-1 Это действительно не то, для чего нужен varargs. Это взломать - в этом случае использование перегрузок будет более читабельным (что не очень хорошо, поскольку три дополнительных символа более читабельны, чем 5 дополнительных строк исходного текста ...). - но Java не поддерживает параметры по умолчанию.
BrainSlugs83 18.04.2015 18:43:55

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

т.е.

class Foo(var prime: Boolean = false, val rib: String)  {}
23
3.04.2012 13:58:02
Привести совершенно новый язык, чтобы получить одну не очень общую черту?
om-nom-nom 3.04.2012 13:59:11
@ om-nom-nom: Java никогда не должно существовать. Заявление о том, что функция не используется, равнозначно тому, что никому не нужно, это говорит о том, что Java не была популярна до ее изобретения, что означает, что Гослинг не должен начинать проектировать ее.
Val 15.06.2012 15:17:27
@Val просто говорю, что это похоже на стрельбу по пушкам с птицами
om-nom-nom 15.06.2012 15:22:29
это не имеет никакого отношения к вопросу ОП
destan 7.11.2016 15:45:19

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

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

4
13.12.2012 17:15:14

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

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);
12
24.10.2019 20:41:18
Постер спросил, можно ли избежать этого (довольно уродливого) паттерна ... ;-) В более современных языках (таких как c #, Scala) вам не нужны эти дополнительные перегрузки, которые только создают больше строк кода. До некоторой степени вы можете использовать varargs тем временем (static int max (int ... array) {}), но они являются лишь очень уродливым решением.
Offler 18.02.2013 14:10:57
Перегрузка не безобразна и имеет много преимуществ, например, различные вызовы методов с разными сигнатурами могут выполнять разные функции. //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 } } }
Antony Booth 14.11.2013 19:57:09
Хорошо, если кто-то хочет другого поведения. Если единственным отличием является небольшое изменение в вычислениях и т. Д., То создание нескольких подписей является пустой тратой усилий. Значения по умолчанию имеют смысл там, где они вам нужны ... и их отсутствие не следует классифицировать как "бесполезное" требование.
Kapil 20.01.2014 04:47:41
Параметры по умолчанию @Offler не имеют ничего общего с «современным языком». Я использовал их в Delphi 20 лет назад, и они, вероятно, уже существовали в Turbo Pascal.
The incredible Jan 6.04.2017 13:09:23
Я согласен с Оффлером и не согласен с Энтони Бутом. Я нахожу это не только уродливым, но и довольно неэффективным. Такие языки, как ruby ​​или python, упрощают использование параметров по умолчанию; Я думаю, что Java требует от вас, чтобы найти (и использовать) обходные пути. Явное сравнение с нулем кажется наименее уродливым выбором, так как я могу также вызвать это из командной строки (просто ничего не предоставлять, а затем обработать вменяемый вариант); подход с перегрузкой операторов кажется ... очень многословным (например, как минимум +3 строки по сравнению с нулевой проверкой и больше строк, если код более сложный).
shevy 3.03.2020 14:53:46

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

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

480
14.06.2018 23:10:44
Хорошее объяснение. Я никогда не видел, чтобы возвращаемые значения использовались так. Для 5) что return thisделать? Кроме того, не FooBuilder().setA("a").build();так ли (по определению) конструктор вызывается первым и FooBuilder()возвращает значение, не значит .setA("a"):ли это, что у него нет возможности быть вызванным?
Celeritas 18.07.2014 22:37:06
@Celeritas return thisвозвращает тот же объект, для которого был вызван метод (в примере, FooBuilder). Это позволяет объединять методы в одном выражении, действующем для одного и того же объекта: и new FooBuilder().setA(..).setB(..).setC(..)т. Д., А не вызывать каждый метод в отдельном выражении.
ADTC 27.08.2014 08:44:08
@Celeritas new FooBuilder()возвращает FooBuilderобъект, для которого setAвызывается метод. Как setBне вызывается, this.bсохраняет значение по умолчанию. Наконец buildметод вызывается для этого FooBuilderобъекта. buildМетод создает и возвращает Fooобъект , который устанавливается в переменную Foo foo. Обратите внимание, что FooBuilderобъект не хранится ни в одной переменной.
ADTC 27.08.2014 08:48:51
Аннотация также может использоваться для создания параметров по умолчанию и наиболее полезна, когда это требуется для полиморфных коллекций. docs.oracle.com/javase/tutorial/java/annotations/declaring.html
Martin Spamer 27.01.2015 09:47:59
Более 900 голосов против одного ответа на два вопроса. Я впечатлен: stackoverflow.com/questions/965690/java-optional-parameters/…
AdamMc331 28.11.2015 19:19:07

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

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

    return score;
}
3
3.09.2014 16:45:05

Нет, но вы можете очень легко подражать им. Что в 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 из-за его простоты.

37
18.10.2017 03:39:53
Основная идея нотации значений по умолчанию в C # состоит именно в том, чтобы избежать этого стандартного кодирования и иметь только один конструктор вместо многих.
Kolya Ivankov 17.10.2017 09:27:43
@KolyaIvankov Я не знаю C #, но я знаю C ++, где рассуждения такие же. Я не знаю, что лучше, но я думаю, что на самом деле тот же самый шаблонный код генерируется компилятором в случае C ++ / C #, и он входит в окончательный двоичный файл.
peterh - Reinstate Monica 17.10.2017 09:34:18
Каждый язык программирования является (в частности) средством, позволяющим обойти шаблон Ассемблера, я не прав? Вопрос только в том, дает ли он удобную функциональность или нет.
Kolya Ivankov 17.10.2017 11:45:48
Первое предложение - риторический вопрос. Слово «вопрос» во втором предложении не имеет ничего общего с риторическим вопросом в первом предложении.
Kolya Ivankov 17.10.2017 13:44:34
Точнее говоря: языки - это инструменты, которые позволяют нам писать программы таким образом, чтобы мы могли контролировать то, что написано, компиляция - это способ сообщить машине, чего мы от нее хотим. Инструмент более полезен, если он позволяет нам избегать шаблонов. По сути, gnavi спросил, могут ли они точно избежать того типового кода, который вы предлагаете в качестве ответа, поскольку C # допускает это.
Kolya Ivankov 17.10.2017 13:50:05

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

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
18.01.2015 15:40:19

Вы можете использовать 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);
3
13.06.2016 17:42:50

Аналогичный подход к 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
23.05.2017 11:47:32

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

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

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
1.09.2016 06:51:15

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

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);
}
16
27.06.2019 11:01:21
Да, этот подход кажется лучшим из других альтернатив. Тем не менее было бы неплохо для Java принять значения по умолчанию; Котлин показал, что это можно сделать, поэтому я не уверен, почему Oracle не входит в современную эпоху и продолжает разрабатывать Java, как если бы это было в 1990-х годах. : D
shevy 3.03.2020 14:54:04

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

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

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

7
26.11.2017 19:51:08

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

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

int foo() {
    return foo(0); // here, 0 is a default value for a
}
2
12.03.2019 12:17:20

Это не поддерживается в Java, как и в других языках, например. Котлин.

0
15.12.2019 17:11:05

Вы можете использовать следующие

public void mop(Integer x) {
  // Define default values
        x = x == null ? 200 : x;
}
0
30.12.2019 07:50:50

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

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
14.02.2020 11:52:10