Не в Java 7, но я подозреваю, что вы отметили этот java-7
только потому, что в этой версии введена попытка с ресурсами, и вас все еще интересуют возможные варианты использования за пределами Java 7 (я думаю, что этот вопрос очень интересен для Java >= 8) .
Я думаю, что нет ничего особенного, что связывает try-with-resources и аннотации, это не частный случай в грамматике; в этом отношении такие переменные (объявленные в операторе try-with-resources) точно такие же, как и другие локальные переменные, и грамматика также допускает аннотации:
- В Java 7 появились операторы try-with-resources, в которых вы можете объявить переменную, которая получит особый режим.
- Грамматика допускала аннотации к объявлениям локальных переменных еще в Java 5, когда аннотации были введены (но нам пришлось ждать Java 6, чтобы получить пригодный для использования API для обработки аннотаций).
- Но даже с Java 7 процессоры аннотаций не могли получить доступ к аннотациям локальных переменных. Единственной аннотацией к локальной переменной, которая была «пригодна для использования», была
@SuppressWarnings
, но она была специально обработана самим компилятором, и у вас не было возможности подключиться к ней.
- В Java 8 появился новый тип контекста аннотации, помимо «контекста объявления», теперь есть «контекст типа», и теперь аннотация
Target
может быть ElementType.TYPE_USE
Таким образом, ответ (с Java 8) такой же, как и для любой аннотации к локальным переменным.
(некоторые мелочи о новых «аннотациях типов» в Java 8)
... и вот здесь становится интересно: аннотирование любого типа!
Синтаксические области, в которых могут появляться аннотации, разделены на контексты объявлений , где аннотации применяются к объявлениям, и контексты типов, где аннотации применяются к типам, используемым в объявлениях и выражениях.
Такие аннотации не сохраняются во время выполнения, но могут использоваться во время компиляции для различных «проверок». См. среду проверки, созданную на основе работы, проделанной для JSR-308 (от тот же автор, если я правильно понимаю).
Очень быстро, потому что это весело, теперь мы можем сделать это:
@NonNull Object @Nullable [] array; // Nullable array of non-null objects
@Nullable Object @NonNull [] array; // Non-null array of nullable objects
@Foo List<@Foo Integer> doSomething(@Foo Integer @Foo [] arrayOfIntegers, @Foo long x) {
arrayOfIntegers[0] = (@Foo int) x;
return Arrays.asList(arrayOfIntegers);
}
Примеры таких "аннотаций типов":
Checker Framework предоставляет несколько аннотаций типов, которые могут быть полезны как разработчикам библиотек, так и разработчикам приложений, например:
@NonNull
— компилятор может определить случаи, когда путь кода может получить нулевое значение, без необходимости отлаживать исключение NullPointerException.
@ReadOnly
— компилятор будет помечать любую попытку изменить объект. Это похоже на Collections.unmodifiableList, но имеет более общий характер и проверяется во время компиляции.
@Regex
— Обеспечивает проверку во время компиляции того, что строка, предназначенная для использования в качестве регулярного выражения, является правильно отформатированным регулярным выражением.
@Tainted
и @Untainted
– Идентификационные типы данных, которые не следует использовать вместе, например удаленный пользовательский ввод, используемый в системных командах, или конфиденциальная информация в потоках журналов.
@m
– Единицы измерения обеспечивают использование и сравнение чисел, используемых для измерения объектов. правильно или подверглись надлежащему преобразованию единиц измерения.
Но ни один из них не особенно полезен в контексте оператора try-with-resources (я имею в виду, не больше и не меньше, чем где-либо еще).
Вернемся к вопросу: есть ли применение аннотациям к локальным переменным, которые были бы особенно интересны при объявлении в операторе try-with-resources?
Я думаю, что в этом случае приложения будут ограничены проверками во время компиляции, потому что такая аннотация будет либо в локальной переменной, либо в используемом типе, и ни одна из них не будет доступна во время выполнения (или не будет доступна). В самом деле):
Итак, я могу придумать одно «специальное» использование, но я даже не уверен, что это было бы очень полезно, поскольку, вероятно, есть другие способы сделать это: для некоторых конкретных типов ресурсов, которые вы объявляете в try-with-resources вам может потребоваться убедиться, что ресурс полностью использован, прежде чем он будет закрыт (я видел что-то подобное с клиентской библиотекой HTTP и частью API, которая читает заголовки — не могу вспомнить подробности ).
/* Say getResponse() taps into a third-party library that has a quirk:
* a response object must be consumed entirely before being closed. */
try(@MustConsumeEntirely Stream<String> lines = getResponse()) {
lines.findFirst().ifPresent(System.out::println);
/* The stream is not entirely consumed (unless it is only 1 line but there is no way to tell).
* A smart checker could catch this and issue a warning. */
}
Эта аннотация будет иметь цель ElementType.LOCAL_VARIABLE
(поэтому не потребуются новые типы аннотаций Java 8, но потребуется, чтобы Java 8 была обрабатываемой), и средство проверки, вероятно, должно проверить, что переменная эффективно объявлена в операторе try-with-resources (компилятор не может запретить использовать его для какой-либо локальной переменной), а затем проанализировать исходное дерево, чтобы определить, расходуются ли ресурсы в соответствии с требованиями. выглядит возможным проверить некоторые известные плохие шаблоны, и в основном это имеет смысл, когда целевая переменная объявляется в операторе try-with-resources.
Другая идея (все еще об использовании переменной, а не типа), также очень низкая полезность: @MustNotEscape
, если вы хотите контролировать, чтобы переменная не передавалась другому методу, потому что (по причинам, аналогичным вышеизложенным) вы хотите иметь возможность контролировать все, что происходит с объектом позади (например, как в предыдущей идее), и это было бы труднее выполнить, если бы переменная передавалась.
Чтобы проиллюстрировать, что такое смутно возможно, вот пример фреймворка который ожидает, что вы будете следовать их «встроенному DSL» внутри определенного блока, и не работает, если вы этого не сделаете. Можно представить себе аннотацию, помогающую проверить соответствие аналогичным ограничениям, наложенным гипотетической структурой на ресурс в блоке try-with-resources.
Не говорю, что это будет хороший дизайн... (Я В случае с ModelMapper DSL был всего лишь хитрым трюком, который они придумали до Java 8, и теперь у них есть лучшие и более безопасные решения с лямбда-выражениями)
person
Hugues M.
schedule
06.08.2017
RetentionPolicy.CLASS
, который полезен для шашек, но не доступны во время выполнения (за исключением, может быть, в лучшем случае самостоятельного разбора файла класса!) - person Hugues M.   schedule 07.08.2017TYPE_USE
хранятся в файле класса, и я полагаю, Майкл Эрнст думал об этом, когда делал это утверждение, поскольку вы можете видеть типичные аннотации средства проверки, такие как «non-null» и «nullable» как свойство типа. К сожалению, аннотации с цельюLOCAL_VARIABLE
по-прежнему не сохраняются. - person Holger   schedule 07.08.2017LOCAL_VARIABLE
илиTYPE_USE
), но мои данные неверны, и я исправлю соответствующую (неправильную) часть моего ответа - person Hugues M.   schedule 07.08.2017