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

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

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

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

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

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

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

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

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

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

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

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

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

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

     void foo(String a, Optional bOpt) { Integer b = bOpt.isPresent() ? bOpt.get() : 0; //... } foo("a", Optional.of(2)); foo("a", Optional.absent()); 

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

  5. Рисунок Builder. Шаблон построителя используется для конструкторов и реализуется путем введения отдельного classа 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 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.of( "a", "a", "b", 2, "d", "value")); 

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

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

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

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

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

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

т.е.

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

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

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

по умолчанию вы будете использовать эфир

func («моя строка»);

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

func (“моя строка”, false);

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

Нет.

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

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

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

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

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

 public myParameterizedFunction(String param1, int param2, Boolean param3) { param3 = param3 == null ? false : param3; } public myParameterizedFunction(String param1, int param2) { this(param1, param2, false); } 

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

 public myParameterizedFunction(String param1, int param2, Boolean param3) { if (param3 == null) { param3 = false; } } public myParameterizedFunction(String param1, int param2) { this(param1, param2, false); } 

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

 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 со значениями по умолчанию и переопределяем их в разделе инициализации экземпляра classа { param1 = 10; param2 = "bar";} { param1 = 10; param2 = "bar";}

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

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

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

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

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

Очень примечательно количество сырой, стратосферной компьютерной науки, сделанной на Java.

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

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

 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 предоставила «необязательный аргумент» для наших параметров, поскольку нам нужно было бы затем кодировать значения по умолчанию и т. Д. В этом примере мне не нужно беспокоиться об этом. Да, я добавил еще один метод для своего classа, но его легче читать в долгосрочной перспективе по моему скромному мнению.

Аналогичный подход к 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; } }); } } 

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

Просто добавьте @GenerateMethodInvocationBuilder к classу или интерфейсу и @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); 

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

когда не передан параметр

 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 } 
  • Таблицы стилей CSS по умолчанию для браузеров
  • Можете ли вы вызвать метод по умолчанию родительского интерфейса из интерфейса, который подclassифицирует этот интерфейс?
  • Изменить статус по умолчанию Magento для дублированных продуктов
  • Почему «final» не допускается в методах интерфейса Java 8?
  • Интерфейс с методами по умолчанию vs Абстрактный class в Java 8
  • Принудительный клиент telnet в режиме символов
  • Почему компилятор Scala запрещает перегруженные методы с аргументами по умолчанию?
  • Инициализация нормального массива с одним значением по умолчанию
  • Создание (и доступ) разреженной матрицы с записями NA по умолчанию
  • Конструкторы и наследование по умолчанию в Java
  • Как загрузить пакеты в R автоматически?
  • Interesting Posts
    Давайте будем гением компьютера.