Java 8: ссылка метода на статический метод нестатическим способом
Я изучаю новый Stream API для экзамена OCP и обнаружил что-то, чего я не совсем понимаю. Вот мой код:
void methodOne() {
this.compare(1, 2); // This works fine.
Stream.of(1,2,3)
.sorted(this::compare); // Compilation error.
}
static Integer compare(Integer s1, Integer s2) {
return 0;
}
Здесь у меня есть статический метод сравнения и нестатический метод сравнения. Если я вызываю метод сравнения из нестатического метода, я получаю предупреждение компилятора:
Метод сравнения (Integer, Integer) из типа TestStream должен быть доступен статическим способом.
Если вместо этого я использую ссылку на метод в том же методе в моем потоке, это предупреждение компилятора становится ошибкой компилятора с тем же сообщением.
Я знаю, почему я получаю предупреждение, но я не понимаю, почему это предупреждение становится ошибкой компиляции, если я использую ссылку на метод. В Интернете я тоже ничего не нашел. Может кто-нибудь объяснить это мне?
2 ответа
Доступ к статическому методу через ссылку до сегодняшнего дня считался ошибкой проектирования AFAIK. Вы даже можете сделать:
YourClass c = null;
c.compare (...)
И это будет работать нормально (хотя с предупреждением).
Когда функции java-8 были разработаны, это было исправлено, поэтому единственный способ получить доступ к статическому методу (для ссылки на метод) - через сам класс:
YourClass::compare
Я знаю, почему я получаю предупреждение, но я не понимаю, почему это предупреждение становится ошибкой компиляции, если я ссылаюсь на метод. В Интернете я тоже ничего не нашел. Может кто-нибудь объяснить это мне?
В обоих случаях это должна была быть ошибка компиляции, но более ранние версии Java допускали ее, потому что разработчики языка не знали этого лучше, и теперь для дальнейшей совместимости уже слишком поздно ее менять.
Тем не менее, ссылки на методы являются вновь созданным синтаксисом языка. Когда вы используете конструкцию <object instance>::<method name>
тогда, по определению, метод, на который вы пытаетесь ссылаться, не может быть статическим методом, поскольку вы обращаетесь к нему, указав, к какому экземпляру объекта вы хотите применить его, что статический метод не может сделать.
Делая это правильно в этот раз и отвергая недопустимые конструкции, которые пытаются получить доступ к статическим материалам через экземпляр, не нарушается какой-либо существующий синтаксис языка, который кто-то мог где-то использовать, хотя и неразумно. Таким образом, они сделали это правильно на этот раз. Не делайте недопустимых вещей, компилятор должен их отклонить, и в этом случае это произойдет.
Это также усложнило бы вывод параметров в случае перегруженных методов, некоторые статические и некоторые нестатические. Но это был бы не первый адский вывод, с которым им пришлось бы обходиться.