Java нужны закрытия?

С Коллекции Eclipse (ранее коллекции GS ) будет работать метод removeIf, определенный на MutableCollection :

MutableList list = Lists.mutable.of(1, 2, 3, 4, 5);
list.removeIf(Predicates.lessThan(3));
Assert.assertEquals(Lists.mutable.of(3, 4, 5), list);

С синтаксисом Java 8 Lambda это можно записать следующим образом:

MutableList list = Lists.mutable.of(1, 2, 3, 4, 5);
list.removeIf(Predicates.cast(integer -> integer < 3));
Assert.assertEquals(Lists.mutable.of(3, 4, 5), list);

Необходим вызов Predicates.cast(), потому что по умолчанию removeIf метод был добавлен на интерфейс java.util.Collection в Java 8.

Примечание: я являюсь коммиттером для коллекций Eclipse .

45
задан Bill the Lizard 28 April 2015 в 19:43
поделиться

15 ответов

1
ответ дан jfs 26 November 2019 в 20:44
поделиться

Как Java-разработчик, который пытается преподавать себе шепелявость в попытке стать лучшим программистом, я сказал бы, что хотел бы видеть предложение Josh Block по реализованным закрытиям. Я использую анонимные внутренние классы выражать вещи как то, что сделать с каждым элементом списка при агрегации некоторых данных. К было бы хорошо представить это как закрытие, вместо того, чтобы иметь необходимость создать абстрактный класс.

2
ответ дан l0st3d 26 November 2019 в 20:44
поделиться

Java имел закрытия с тех пор 1.1, только очень громоздким и ограниченным способом.

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

А тривиальный пример для - каждый (хотя Java 1.5 уже имеет это). Пока можно реализовать forEach метод в Java как есть, это является слишком подробным, чтобы быть полезным.

пример, который уже имеет смысл с существующим Java, реализует, "выполняются вокруг" идиомы, посредством чего приобретение ресурса и выпуск абстрагированы. Например, открытый файл и близко может быть сделан в рамках попытки/наконец без клиентского кода, имеющего необходимость разобраться в деталях.

5
ответ дан Tom Hawtin - tackline 26 November 2019 в 20:44
поделиться

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

myArray.sort( (a, b) => a.myProperty().compareTo(b.myProperty() );

... взгляды чертова партия лучше, чем...

myArray.sort(new Comparator<MyClass>() {
   public int compare(MyClass a, MyClass b) {
      return a.myProperty().compareTo(b.myProperty();
   }
});
3
ответ дан benjismith 26 November 2019 в 20:44
поделиться

Java не нужны закрытия, Объектно-ориентированный язык может сделать все, что закрытие делает промежуточные объекты использования сохранить состояние или сделать действия (в случае Java внутренние классы). Но закрытия желательны как функция, потому что они значительно упрощают код и удобочитаемость увеличения и как следствие пригодность для обслуживания кода.

я не специалист Java, но я использую C# 3.5, и закрытия являются одной из моих любимых функций языка, например, берут следующее утверждение в качестве примера:

// Example #1 with closures
public IList<Customer> GetFilteredCustomerList(string filter) {
    //Here a closure is created around the filter parameter
    return Customers.Where( c => c.Name.Contains(filter)).ToList();
}

теперь берут эквивалентный пример, который не использует закрытия

//Example #2 without closures, using just basic OO techniques
public IList<Customer> GetFilteredCustomerList(string filter) {
    return new Customers.Where( new CustomerNameFiltrator(filter));
}
... 
public class CustomerNameFiltrator : IFilter<Customer> {
    private string _filter;
    public  CustomerNameFiltrator(string filter) {
         _filter = filter;
    }
    public bool Filter(Customer customer) {
        return customer.Name.Contains( _filter);
    }
}

, я знаю, что это - C# и не Java, но идея является тем же, закрытия полезны для краткости и делают код короче и более читаемый. Негласно, закрытия C# 3.5 делают что-то, что это - взгляды, очень похожие на пример № 2, означающий, что компилятор создает частный класс негласно и передает параметр 'фильтра' ему.

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

8
ответ дан Pop Catalin 26 November 2019 в 20:44
поделиться

Существуют некоторые очень полезные 'функции высшего порядка', которые могут сделать операции в списках с помощью закрытий. Функции высшего порядка являются функциями, имеющими 'функциональные объекты' как параметры.

, Например, это - очень общая операция для применения некоторого преобразования к каждому элементу в списке. Эта функция высшего порядка обычно вызывается 'карта', или 'собраться'. (См. *. оператор распространения Groovy).

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

List<Integer> squareInts(List<Integer> is){
   List<Integer> result = new ArrayList<Integer>(is.size());
   for (Integer i:is)
      result.add(i*i);
   return result;
}

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

is.map({Integer i => i*i})

(Существует возможная проблема производительности здесь относительно упаковки типов примитивов.)

, Как объяснил Pop Catalin существует другая функция высшего порядка, вызванная 'выбор' или 'фильтр': Это может использоваться для получения всех элементов в списке, соответствующем некоторому условию. Например:

Вместо:

void onlyStringsWithMoreThan4Chars(List<String> strings){
   List<String> result = new ArrayList<String>(str.size()); // should be enough
   for (String str:strings)
      if (str.length() > 4) result.add(str);
   return result;
}

Вместо этого Вы могли записать что-то как [1 114]

strings.select({String str => str.length() > 4});

использование предложения.

Вы могли бы посмотреть на синтаксис Groovy, который является расширением языка Java для поддержки закрытий прямо сейчас. См. главу по наборам Руководство пользователя Groovy для большего количества примеров, что сделать с закрытиями.

комментарий А:

существует, возможно, некоторое разъяснение, необходимое относительно термина 'закрытие'. Что я показал выше, строго говорятся никакие закрытия. Они - просто 'функциональные объекты'. Закрытие - все, что может получить - или 'закрываются по' - (лексический) контекст кода, окружающего его. В этом смысле существуют закрытия в Java прямо сейчас, т.е. анонимные классы:

Runnable createStringPrintingRunnable(final String str){
    return new Runnable(){
       public void run(){
          System.out.println(str); // this accesses a variable from an outer scope
       }
    };
}
12
ответ дан jrudolph 26 November 2019 в 20:44
поделиться

Я предполагаю для поддержки базовых понятий функционального программирования, Вам нужны закрытия. Делает код более изящным и компонуемым с поддержкой закрытия . Кроме того, мне нравится идея раздать строки кода как параметры к функциям.

18
ответ дан Gulzar Nazim 26 November 2019 в 20:44
поделиться

Самой очевидной вещью была бы псевдозамена для всех тех классов, которые просто имеют отдельный метод, названный выполненным () или actionPerformed () или что-то как этот. Таким образом вместо того, чтобы создать Поток со встроенным Выполнимым, Вы использовали бы закрытие вместо этого. Не более мощный, чем, что мы имеем теперь, но намного более удобный и краткий.

Так делают нас потребность закрытия? Нет. Они были бы хороши иметь? Несомненно, пока они не чувствуют себя соединенными болтом на, поскольку я боюсь, что они были бы.

36
ответ дан jodonnell 26 November 2019 в 20:44
поделиться

Они не делают Объектно-ориентированный язык лучше. Они делают практические языки более практичными.

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

На практике, это чрезвычайно удобно. Я действительно не хочу определять новый тип объекта содержать контекст, установить, "действительно наполняют" метод для него, инстанцируют его и заполняют контекст..., я просто хочу сказать компилятор, "посмотрите, посмотрите то, к чему у меня есть доступ прямо сейчас? Это - контекст, который я хочу, и вот код, я хочу использовать его для - держатся за это для меня, 'пока мне не нужен он".

Фантастический материал.

41
ответ дан Shog9 26 November 2019 в 20:44
поделиться

Как программист Lisp я пожелал бы, чтобы сообщество Java поняло следующее различие: функции как объекты по сравнению с закрытиями.

a) функции можно назвать или анонимные. Но они могут также быть объектами себя. Это позволяет функциям быть розданными как аргументы, возвращенные из функций, или сохранило в структурах данных. Это означает, что функции являются объектами первого класса на языке программирования.

Анонимные функции не добавляют много к языку, они просто позволяют Вам писать функции более коротким способом.

b) Закрытие является функцией плюс обязательная среда. Закрытия могут быть переданы вниз (как параметры) или возвращены вверх (как возвращаемые значения). Это позволяет функции относиться к переменным своей среды, даже если окружающий код больше не активен.

Если у Вас есть a) на некотором языке, то вопрос подходит, что сделать о b)? Существуют языки, которые имеют a), но не b). В мире функционального программирования a) (функции) и b (функции как закрытия) в наше время норма. Smalltalk имел a) (блоки являются анонимными функциями), в течение долгого времени, но затем некоторые диалекты Smalltalk добавленная поддержка b) (блоки как закрытия).

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

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

Закрытие (функция плюс привязка) позволяет Вам, например, создавать функцию, которая имеет доступ к некоторым переменным (например, к встречному значению). Теперь можно сохранить ту функцию в объекте, получить доступ к ней и вызвать ее. Контекст для функционального объекта является теперь не только объектами, он имеет доступ к, но также и переменные, к которым он имеет доступ через привязку. Это также полезно, но Вы видите, что привязки переменных по сравнению с доступом к переменным объекта теперь являются проблемой: когда должно быть что-то лексическая переменная (к которому можно получить доступ в закрытии), и когда должен это быть переменной некоторого объекта (слот). Когда что-то должно быть закрытием или объектом? Можно использовать обоих похожими способами. Обычное осуществление программирования для студентов, изучающих Схему (диалект Lisp), должно записать систему простого объекта с помощью закрытий.

Результатом является более сложный язык программирования и более сложная модель во время выполнения. Слишком сложный?

71
ответ дан Rainer Joswig 26 November 2019 в 20:44
поделиться

Не только, что benjismith, но и я люблю, как можно просто сделать...

myArray.sort {it.myProperty}

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

Я абсолютно люблю эту функцию.

0
ответ дан 26 November 2019 в 20:44
поделиться

Закрытия на императивном языке (примеры: JavaScript, C#, предстоящее обновление C++), не то же как анонимные внутренние классы. Они должны смочь получить модифицируемые ссылки на локальные переменные. Внутренние классы Java могут только получить локальный final переменные.

Почти любая функция языка может быть подвергнута критике как несущественная:

  • for, while, do все просто синтаксический законченный сахар goto/if.
  • Внутренние классы являются синтаксическим сахаром по классам с полем, указывающим на внешний класс.
  • Дженерики являются синтаксическим сахаром по броскам.

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

2
ответ дан Daniel Earwicker 26 November 2019 в 20:44
поделиться

Я читал много в последнее время о следующем выпуске Java, возможно поддерживающего закрытия. Я чувствую, что у меня есть симпатичное твердое схватывание на том, каковы закрытия, но я не могу думать о твердом примере того, как они сделали бы Объектно-ориентированный язык "лучше".

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

Например, в Python:

def reversecmp(x, y):
   return y - x

a = [4, 2, 5, 9, 11]
a.sort(cmp=reversecmp)

Это сортирует список в обратном порядке путем передачи пользовательского сравнения functoin reversecmp. Добавление оператора лямбды делает вещи еще более компактными:

a = [4, 2, 5, 9, 11]
a.sort(cmp=lambda x, y : y - x)

Java не имеет функциональных объектов, таким образом, он использует "классы функтора" для моделирования их. В Java Вы делаете эквивалентную операцию путем реализации пользовательской версии класса Компаратора и передачи этого функции вида:

class ReverseComparator implements Comparator {
   public compare(Object x, Object y) {
      return (Integer) y - (Integer) x;
   }

...

List<Integer> a = Arrays.asList(4, 2, 5, 9, 11);
Collections.sort(a, new ReverseComparator());

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

List<Integer> a = Arrays.asList(4, 2, 5, 9, 11);
Comparator reverse = new Comparator() {
   public Compare(Object x, Object y) {
       return (Integer) y - (Integer) x;
   }
}
Collections.sort(a, reverse);

Таким образом, я сказал бы, что комбинация классов функтора + анонимные внутренние классы в Java достаточна для компенсации из-за отсутствия истинных функциональных объектов, делая их дополнение ненужным.

8
ответ дан cygil 26 November 2019 в 20:44
поделиться

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

Они - синтаксический сахар в том же смысле, что Java является синтаксическим сахаром для ассемблера (что "ассемблер" мог быть байт-кодом ради аргумента). Другими словами, они повышают, они выравниваются абстракции, и это - важное понятие.

Закрытия продвигают концепцию функции поскольку объект к объекту первого класса - тот, который увеличивает выразительность кода, вместо того, чтобы создать помехи ему еще большим количеством шаблона.

Пример это близко моему сердцу, был уже упомянут Tom Hawtin - реализация Выполнения Вокруг идиомы, которая является примерно единственным способом получить RAII в Java. Я записал запись в блоге на точно, которые подвергают несколько лет назад, когда я сначала слышал, что закрытия могли бы происходить.

Как ни странно, я думаю самая причина, что закрытия были бы хороши для Java (больше выразительности с меньшим количеством кода) может быть тем, что пугает многих защитников Java. Java имеет мышление "написания все длинный путь". Это и то, что закрытия являются поклоном к более функциональному способу сделать вещи - который я также рассматриваю как Хорошую Вещь, но может смягчить чистое сообщение OO, что многие в сообществе Java дорожат.

3
ответ дан philsquared 26 November 2019 в 20:44
поделиться

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

0
ответ дан 26 November 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: