Подтвердить что ты не робот

Почему Java 8 представила новый оператор "::" для ссылок на методы?

В Java 8 ссылки на методы выполняются с помощью оператора ::.

Пример

// Class that provides the functionality via it static method
public class AddableUtil {
  public static int addThemUp(int i1, int i2){
    return i1+i2;
  }
}

// Test class
public class AddableTest {
  // Lambda expression using static method on a separate class
  IAddable addableViaMethodReference = AddableUtil::addThemUp;
  ...
}

Вы можете видеть, что addableViaMethodReference теперь действует как псевдоним AddableUtil::addThemUp. Таким образом, addableViaMethodReference() выполнит то же действие, что и AddableUtil.addThemUp(), и вернет то же значение.

Почему они решили ввести новый оператор вместо использования существующего? Я имею в виду, выполните функцию, когда имя функции заканчивается на () и возвращает ссылку на функцию, если нет конечного ().

Выполнение метода

AddableUtil.addThemUp();

Ссылка на метод

AddableUtil.addThemUp;

Разве это не было бы намного проще и интуитивно понятным? AFAIK, AddableUtil.addThemUp в настоящее время (Java 7) не используется для других целей и генерирует ошибку компиляции. Почему бы не использовать эту возможность вместо создания совершенно нового оператора?

4b9b3361

Ответ 1

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

import java.util.function.IntBinaryOperator;

public class A {

  public static IntBinaryOperator addThemUp;

  public static int addThemUp(int i1, int i2) {
    return i1 + i2;
  }

  public static void main(String[] args) throws Exception {
    IntBinaryOperator operator = A::addThemUp;
  }
}

Неясно, относится ли A.addThemUp к общедоступному полю IntBinaryOperator или пытается создать ссылку на метод.

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

Ответ 2

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

Но я бы поставил вопрос: "перегружает" существующий синтаксис, как это действительно хорошая идея? (Ваш вопрос предполагает это, но это огромное предположение.) Существует большая разница между "методом вызова m/read field f" и "ссылаться на метод m/field f по имени". Разве два вида выражений не выглядят иначе? Какая польза от повторного использования существующего синтаксиса означает нечто совершенно иное?

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

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

Ответ 3

Может быть, они сделали это, чтобы заставить программистов на С++ больше приветствовать на Java?/* На мой взгляд (опасные слова для использования в качестве скептика), оператор:: более естественно использовать для статических методов, так как это оператор разрешения области в С++ */