Аннотировать конструктор Java как реализующий @FunctionalInterface
Это все равно, что просить «Добавить угол к зеленому цвету». это не имеет никакого смысла.
Смысл FunctionalInterface заключается в том, чтобы пометить интерфейс как определяющий «функцию», в том смысле, что вы можете написать лямбда-синтаксис ((a, b) -> result
) или конструкцию ссылки на метод (foo::bar
) в месте, где значение этот интерфейс необходим, и тогда javac автоматически исправит все для вас, чтобы он работал.
Вы не аннотируете метод (или конструктор), который соответствует шаблону и может использоваться в качестве ссылки на метод.
Намного чище, но IDE и Sonar теперь жалуются на неиспользуемый параметр.
Вы слышали притчу о докторе?
Пациент спросил врача: Доктор, мне больно, когда я нажимаю сюда!
Врач сказал: Хорошо. Ну перестань так делать!
Проблема в вашей IDE/Sonar, а не в вашем коде. Выключите эту функцию «проверки» / «линтера», это глупо, и она отключена по умолчанию, поэтому кто-то включил ее, думая (ошибочно), что это полезная проверка.
Существует правильная версия этой проверки: тогда и только тогда, когда инструмент линтера имеет полное представление обо всей иерархии методов (то есть не только сам метод, но и все методы, которые его переопределяют, все методы, которые этот метод переопределяет, и все внешние по отношению к этой кодовой базе методы, которые могут переопределить его в будущем), и этот параметр игнорируется для всех этих методов, тогда можно предупредить об этом.
Учитывая, что у линтеров нет хрустального шара, он начинается с обеспечения того, чтобы метод был либо эффективно final
, либо эффективно (пакетно) приватным, чтобы уменьшить набор неизвестных внешних до 0. Проверка не может применяться к любому нефинальному общедоступному методу. что-нибудь: возможно, этот параметр существует для кода, который переопределит этот метод. (Подумайте об этом: когда у вас есть метод abstract
, все параметры «игнорируются», так как кода вообще нет!)
Если бы этот более интеллектуальный подход был включен, здесь не появилось бы никакого предупреждения: лямбда-выражения переопределяют что-то по определению.
Есть ли способ сообщить компилятору, что конструктор фактически реализует RowMapper @FunctionalInterface, чтобы он знал, что требуется второй аргумент, даже если он не используется?
Нет. Вы можете создать второй конструктор, который принимает второй параметр (типа int
), только для того, чтобы он полностью игнорировал этот параметр, но это будет фактически вызывать это предупреждение линтера, если это интеллектуальный линтинг, как конструкторы по определению не может быть переопределено что-то и не может быть переопределено, таким образом квалифицируя проверку «игнорируемого параметра» как полезную, разве это не иронично?
Я настоятельно рекомендую не создавать конструктор, который фактически нуждается в следующем javadoc:
/**
* This constructor completely ignores the second parameter.
* It is intended to be used in the form of `MyType::new`,
* when you need a `RowMapper`.
* <strong>NB: Any other use is neccessarily a bug</strong>.
*/
Потому что, ну, читай. Выделение предупреждений, выделенных жирным шрифтом, для объяснения того, что предполагаемое использование вещи вызывает удивление, — это плохо: вам не нужны сюрпризы в вашей кодовой базе, и вам не нужны методы, которые могут быть неправильно поняты без прочтения документации.
Я попытался создать эту аннотацию, чтобы аннотировать неиспользуемый параметр значимым именем, инкапсулируя детали реализации удаления предупреждений, но это тоже не работает
Это не работает; аннотации не «мета», как это. Вы можете аннотировать определение аннотации, но это не означает, что «аннотирование вещи этой аннотацией подразумевает, что вещь аннотирована всеми этими аннотациями». Это может означать это, но только если аннотация (и связанные с ней инструменты!) определены для такой работы, потому что они не встроены в java. @SuppressWarnings
так не работает.
Итак, что мне делать в этой ситуации?
Я предлагаю вам попробовать что-то вроде этого:
public class WhateverYouHaveThere {
public static RowMapper asRowMapper() {
return (rs, idx) -> new WhateverYouHaveThere(rs);
}
}
Этот метод не нуждается ни в javadoc, ни в комментариях: название метода + модификатор static
на 100% покрывает его назначение, и реализация не вызывает ни малейшего удивления.
И затем, конечно же, исправьте тупоголовую настройку в вашем линтере :) — тот факт, что он будет предупреждать об этом методе, является достаточным доказательством того, что он просто мешает и не дает вам никакой значимой информации о подозрительном коде.
Затем он позволяет вам написать:
public static final RowMapper<ValueObject> ROW_MAPPER = ValueObject.asRowMapper();
NB: вы также можете сделать это статическим полем:
public class ValueObject {
public static final RowMapper<ValueObject> ROW_MAPPER =
(rs, idx) -> new ValueObject(rs);
}
Но я бы не стал. Скорее стильная вещь. Здесь также применимо множество аргументов в пользу геттеров, а не публичных конечных полей. В основном: предоставьте себе больше гибкости в будущем, чтобы добавить ведение журнала, изменить реализации и т. д.
person
rzwitserloot
schedule
15.01.2021