Ява-выражение Java 8 и значения первого класса

Являются ли Java 8 закрытием действительно первоклассными значениями или являются только синтаксическим сахаром?

Ответ 1

Я бы сказал, что блокировки Java 8 ( "Lambdas" ) не являются ни синтаксическим сахаром, ни являются первоклассными значениями.

Я рассмотрел проблему синтаксического сахара в ответе на другой вопрос StackExchange.

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

В некотором смысле лямбда хочет быть функцией, но Java 8 не добавляет типы функций. Вместо этого выражение лямбда преобразуется в экземпляр функционального интерфейса. Это позволило добавить lambdas в Java 8 с незначительными изменениями в системе типа Java. После преобразования результат является ссылкой, как и для любого другого ссылочного типа. Фактически, используя Lambda - например, в методе, который был передан лямбда-выражением в качестве параметра, неотличим от вызова метода через интерфейс. Метод, который получает параметр типа функционального интерфейса, не может определить, передано ли ему lambda-выражение или экземпляр некоторого класса, который реализует этот функциональный интерфейс.

Для получения дополнительной информации о том, являются ли лямбда объекты, см. Lambda FAQ Answer на этот вопрос.

Учитывая, что лямбды преобразуются в объекты, они наследуют (буквально) все характеристики объектов. В частности, объекты:

  • имеют различные методы, такие как equals, getClass, hashCode, notify, toString и wait
  • имеют хэш-код идентификации
  • может быть заблокирован блоком synchronized
  • можно сравнить с помощью операторов == и != и instanceof

и т.д. Фактически, все они не имеют значения для предполагаемого использования лямбда. Их поведение существенно undefined. Вы можете написать программу, которая использует любой из них, и вы получите какой-то результат, но результат может отличаться от версии для выпуска (или даже запускаться!).

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

Обновление 2013-10-24

Я уже думал об этой теме, так как уже несколько месяцев назад выложил свой ответ. С технической точки зрения все, что я написал выше, является правильным. Вывод, вероятно, выражен более точно, так как Java 8 lambdas не является чистым (в отличие от первоклассных) значений, поскольку они несут много предметного багажа. Однако только потому, что они нечистые, это не значит, что они не первоклассные. Рассмотрите определение Википедии первоклассной функции. Вкратце, критерии, перечисленные там для рассмотрения функций первого класса, - это способности:

  • передать функции в качестве аргументов для других функций
  • функции возврата из других функций
  • назначать функции переменным
  • хранить функции в структурах данных
  • имеют функции анонимного

Java 8 lambdas соответствуют всем по этим критериям. Таким образом, это делает их первоклассными.

В статье также упоминаются имена функций, не имеющие специального статуса, вместо этого имя функции - это просто переменная, тип которой является типом функции. Java 8 lambdas не соответствуют этому последнему критерию. Java 8 не имеет типов функций; он имеет функциональные интерфейсы. Они используются эффективно, как типы функций, но они вообще не являются типами функций. Если у вас есть ссылка, тип которой является функциональным интерфейсом, вы не знаете, является ли она лямбдой, экземпляром анонимного внутреннего класса или экземпляром конкретного класса, который реализует этот интерфейс.

Таким образом, ямбады Java 8 являются более первоклассными функциями, чем я думал изначально. Они просто не являются чистыми первоклассными функциями.

Ответ 2

Да, они являются значениями первого класса (или будут, как только Java 8 будет выпущен...)

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

См. также более подробное определение того, что означает "первый класс" в этом контексте:

Ответ 3

Как я вижу, это синтаксический сахар, но помимо вывода типа новый пакет java.util.functions и семантика внутренних классов он выглядит как первоклассное значение.

Ответ 4

Действительное замыкание с привязкой переменной к внешнему контексту имеет некоторые накладные расходы. Я бы счел реализацию Java 8 оптимальной, достаточно чистой.

Это не просто синтаксический сахар, по крайней мере.

И я бы не знал о более оптимальной реализации.

Ответ 5

Для меня Lambdas в Java 8 - это просто синтаксический сахар, потому что вы не можете использовать его как первый класс Citizen (http://en.wikipedia.org/wiki/First-class_function), каждая функция должна быть обернутым в объект, это накладывает много ограничений при сравнении с языком с чистой функцией первого класса, такой как SCALA. Закрытие Java 8 может только захватывать неизменяемые ( "эффективно конечные" ) нелокальные переменные.

Вот лучшее объяснение, почему это синтаксис-сахар Java Lambdas и Closures