• Правила сохранения аннотаций определяют, в какой момент аннотации будут уничтожены.
• В языке Java описаны три таких правила — source, class и runtime, включенные в перечислимый тип java.lang.annotation.RetentionPolicy.
• Существует три правила:
1) SOURCE - Аннотация, заданная с правилом сохранения source, существует только в исходном тексте программы и отбрасывается во время компиляции.
2) CLASS - Аннотация, заданная с правилом сохранения class, помещается в файл .class в процессе компиляции. Но она не доступна в JVM во время выполнения.
3) RUNTIME - Аннотация, заданная с правилом сохранения runtime, помещается в файл .class в процессе компиляции и доступна в JVM во время выполнения. Следовательно, правило RUNTIME предлагает максимальную продолжительность существования аннотации.
Правило сохранения для аннотации задается с помощью одной из встроенных аннотаций @Retention. Ее синтаксическая запись приведена в следующей строке: @Retention (retention-policy)
В этой записи retention-policy задается одной из описанных ранее констант перечислимого типа. Если для аннотации не задано правило сохранения, по умолчанию задается правило CLASS.
Пример задания правила сохранения:
• @Retention(RetentionPolicy.RUNTIME)
• @interface myAnnotation { String str(); int val(); }
Получение информации об аннотациях производится средствами рефлексии. Вы можете получить конкретную аннотацию, связанную с объектом, с помощью вызова метода getAnnotation() или использовать метод getAnnotations() для получения массива всех аннотаций. Методы getAnnotation() и getAnnotations(), определены в новом интерфейсе AnnotatedElement, который включен в пакет Java.lang.reflect. Этот интерфейс поддерживает рефлексию для аннотаций и реализован в классах Method, Field, С onstructor, С lass и Package.
Использование значений по умолчанию
Вы можете передавать значения по умолчанию методам-членам аннотаций, которые будут использоваться, если не задано значение при вставке аннотации. Значение по умолчанию указывается с помощью ключевого слова default в объявлении метода-члена. Синтаксическая запись такого объявления приведена в следующей строке:
type member() default value;
В приведенной записи значение value должно иметь тип, совместимый с типом type.
Далее приведен фрагмент, в котором в объявление интерфейса @ MyAnnotation включены значения по умолчанию:
• @Retention(RetentionPolicy.RUNTIME)
• @interface MyAnnotation {
• String str() default “Testing”;
• int val() default 9000;
• }
• @MyAnnotation()
• @MyAnnotation(str = “some string”);
• @MyAnnotation(val = 100);
• @MyAnnotation(str = “Testing”, val = 100);
Аннотации-маркеры
Аннотация-маркер — это специальный тип аннотации, не содержащий методов-членов. Единственная цель такой аннотации — пометить объявление. В этом случае достаточно присутствия аннотации. Лучше всего для проверки наличия аннотации-маркера использовать метод isAnnotationPresent(), который определен в интерфейсе AnnotatedElement.
Пример аннотации-маркера:
@ interface MyMarker {}
Одночленные аннотации
Одночленная аннотация (single-member annotation) — это еще один специальный тип аннотации, содержащий единственный метод-член. Она применяется так же, как и обычная аннотация, за исключением того, что для этого типа аннотации допускается краткая условная форма задания значения для метода-члена. Если есть только один метод-член, вы можете просто указать значение для этого метода-члена, когда создается аннотация; при этом не нужно указывать имя метода-члена. Но для того чтобы воспользоваться краткой формой, следует для метода-члена использовать имя value.
@ interface MySingle {
int value(); //Имя только такое!
}
@MySingle(100)
Вы можете применять синтаксическую запись одночленной аннотации, когда создаете аннотацию, у которой есть и другие методы-члены, но для них должны быть заданы значения по умолчанию. В приведенном далее фрагменте добавлен метод-член xyz со значением по умолчанию, равным 0.
@interface SomeAnno {
int valuе();
int xyz() default 0;
}
Если Вы хотите использовать значение по умолчанию для метода xyz, можно создать аннотацию типа @SomeAnno, как показано в следующей строке, применяя синтаксическую запись для одночленной аннотации с указанием значения для метода value:
@SomeAnno(88)
В этом случае в метод xyz передается нулевое значение по умолчанию, а метод value получает значение 88. Конечно, передача в метод xyz значения, отличного от значения по умолчанию, потребует явного задания имен обоих методов-членов, как показано в следующей строке:
@ SomeAnno ( value = 88, xyz = 99)
Встроенные аннотации
В языке Java определено семь типов встроенных аннотаций:
• @Retention
Применяется к аннотациям, позволяет задать правило сохранения.
• @Documented
Применяется к аннотациям, указывает, что она должна быть документирована.
• @Target
Применяется к аннотациям, позволяет указать типы объектов, к которым данная аннотация может применяться.
• @Inherited
Применяется к аннотациям классов, указывает, что данная аннотация будет унаследована потомками класса.
• @Override
Применяется к методам, указывает, что метод обязан переопределять метод родительского класса.
• @Deprecated
Указывает на то, что объявление является устаревшим или вышедшим из употребления.
• @SupressWarnings
Указывает на то, что указанные виды предупреждений компилятора не будут показываться. Эти предупреждения задаются с помощью имен в строковой форме.
Особенности аннотаций
• Аннотация не может наследовать другую аннотацию
• Все методы, объявляемые в аннотации, не должны иметь параметров
• Все методы, объявляемые в аннотации должны возвращать один из перечисленных далее типов:
– примитивный тип ( int, double )
– объект типа String
– объект типа Class
– перечислимый тип ( enum )
– другой тип аннотации
– массив элементов одного из вышеперечисленных типов
• Аннотации не могут быть настраиваемыми. Другими словами, они не могут принимать параметры типа.
• В аннотациях нельзя задавать ключевое слово throws.
• Нововведения Java 7 .0
Структура языка
1.1 Использование строк в операторе switch
switch (param) {
case "plain":
System.err.println("bear");
break;
case "mountain":
System.err.println("tiger");
break;
case "swamp":
System.err.println("cockroach");
break;
case "forest": case "island":
System.err.println("snake");
break;
}
Подчеркивание в числах
int one_million = 1_000_000;
Multi-Catch
try {
...// we are using reflection here
} catch (ClassCastException e) {
doSomethingClever(e);
throw e;
} catch(InstantiationException |
NoSuchMethodException |
InvocationTargetException e) {
log(e);
throw e;
}
1.4 оператор <> - diamond (брилиант)
List<String> strList = new ArrayList<>();
2) • Библиотеки
a. • NIO2
Имеется полный доступ к файловой системе: можно писать в файл через потоки или каналы, перебирать, копировать, перемещать и удалять файлы, создавать ссылки, получать атрибуты, сравнивать пути, «подсматривать» за файловой системой.
b. • Concurrency
• Удобный фреймворк для распараллеливаемых задач Fork/Join
• Новый класс синхронизации Phaser (барьер, в дополнение к CyclicBarrier и CountDownLatch)
• Новый интерфейс TransferQueue (расширяет BlockingQueue, имплементирован в LinkedTransferQueue)
с. • Client features
• Nimbus LaF – новый кроссплатформенный look-and-feel
• JLayer – декоратор для swing-компонент
• XRender pipeline – использование ресурсов графических видеокарт для отрисовки Java2D для повышения производительности.
• новый API AWT (полупрозрачные и фигурные окна, смешивание "тяжелых" и "лёгких" компонент (HW/LW))
3) • Виртуальная Машина
a. • The DaVinci Machine project
Этот проект прототипирует ряд расширений для JVM, таким образом, что она может запускать приложения, написанные не на Java, с уровнем производительности, сравнимым с самой Java. Акцент делается на доработке существующего байт-кода и архитектуры выполнения с расширениями общего назначения для работы с отличными от Java языками.
b. • InvokeDynamic bytecode
Исполнение метода требовало точного имени метода, списка параметров и возвращаемого значения на этапе компиляции. Новая инструкция Байткода InvokeDynamic позволяет использовать позднее связывание для методов с помощью MethodHandler. При первом вызове метода находится метод и создаётся handler. Последующие вызовы его переиспользуют.
• Нововведения Java 8 .0
• Java
– Ламбда-выражения;
– Ссылки на методы;
– Повторяемые аннотации;
– Аннотации на типы данных;
– Рефлексия для параметров методов;
– Методы по-умолчанию.
• Коллекции
– Новый API для потоков;
– Параллельная сортировка массивов;
– Улучшение производительности HashMaps.
• Компактные сборки Java
– Возможность создания профилей для платформы Java SE, которые включают в себя не всю платформу целиком, а некоторую ее часть.
• Безопасность
– Новая реализация AccessController.doPrivileged, позволяющая устанавливать подмножество привелегий без необходимости проверки всех остальных уровней доступа;
– Password-based алгоритмы стали более устойчивыми;
– Добавлена поддержка SSL/TLS Server Name Indication (NSI) в JSSE Server;
– Улучшено хранилище ключей (KeyStore);
– Добавлен алгоритм SHA-224;
• Инструменты
– Добавлена команда jjs для использования нового JavaScript-движка Nashorn;
– Команда java может запускать JavaFX приложения;
– Добавлена команда jdeps для анализа .class-файлов.
• Интернационализация
– Добавлена поддержка Unicode 6.2.0;
– Добавлен новый API для Calendar и Locale;
• Новый API Date/Time;
• Новый движок JavaScript Nashorn;
• [N]IO
– Улучшена производительность конструктора java.lang.String(byte[], *) и метода java.lang.String.getBytes().
• Добавлен стандартный класс для работы с Base64;
• Добавлена поддержка беззнаковой арифметики;
• Удален мост JDBC-ODBC;
• Удален PermGen, изменен способ хранения мета-данных классов.
• Добавлено несколько новых классов для потокобезопасной работы с ConcurrentHashMap, Atomics, ForkJoinPool, Locks.
Ламбда-выражения
Наиболее значимым нововведением в Java 8 являются ламбда-выражения (Проект Ламбда). Они позволяют заменить анонимные классы на функции.
Структура ламбда-выражения выглядит так:
параметры -> тело
Ламбда-выражения обладают несколькими свойствами:
1. Задание типов параметров не является обязательным;
2. Использование скобок, заключающих параметры ламбда-выражения не обязательно;
3. Использование фигурных скобок в теле ламбда-выражения не обязательно, если тело состоит из одного оператора;
4. Ключевое слово return не является обязательным, если тело ламбда-выражения состоит из одного оператора.
Примеры ламбда-выражений:
Вот так будет выглядеть сортировка массива строк:
String [] strArray = {"1","30","200"};
Arrays . sort ( strArray , ( String s1 , String s2 ) -> s2 . length () - s1 . length ());
В ламбда-выражениях могут использоваться методы класса, в котором определено выражение, а также переменные с модификатором final и переменные, инициализированные только раз.
Например, так выглядит доступ к экземпляру класса и его методам:
import static java.lang.System.out;
public class Hello {
Runnable r1 = () -> out.println(this);
Runnable r2 = () -> out.println(toString());
public String toString() { return "Hello, world!"; }
public static void main(String... args) {
new Hello().r1.run(); //Hello, world!
new Hello().r2.run(); //Hello, world!
}
}
Ссылки на методы
Ссылки на методы могут указывать на:
1. Статические методы;
2. Методы объектов;
3. Конструкторы.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.forEach(value -> System.out.println(value));
numbers.forEach(System.out::println);
Методы по умолчанию
Для реализации нового потокового API, в языке Java потребовалось ввести новую конструкцию - методы по умолчанию (Default Methods, также извесные как Defender Methods или Virtual Extension Methods).
Методы по умолчанию могут быть добавлены в любой интерфейс, и такие методы в интерфейсах имеют реализацию, что необычно для интерфейсов, т.к. ранее запрещалось размещать тело функции в описании интерфейса.
Допустим, класс наследует два интерфейса, и в каждом из них есть default метод. При компиляции возникнет ошибка.
public interface A {
default void hello() { System.out.println("Hello World from A"); }
}
public interface B {
default void hello() { System.out.println("Hello World from B");
}
public class D implements A,B {}
Разберем другой пример:
public interface A {
default void hello() { System.out.println("Hello World from A"); }
}
public interface B extends A {
default void hello() { System.out.println("Hello World from B"); }
}
public class C implements B, A {
public static void main(String... args) {
new C().hello();
}
}
В данном случае победит ближайший в иерархии, то есть интерфейс B. Ну а если хочется использовать метод интерфейса А, то нужно:
interface A {
default void hello() { System.out.println("Hello World from A"); }
}
interface B {
default void hello() { System.out.println("Hello World from B"); }
}
class C implements B, A {
public void hello() {
A.super.hello();
}
public static void main(String... args) {
new C().hello();
}
}
Разберем третий пример: есть конфликтующий метод у абстрактного класса и интерфейса. В этом случае побеждает всегда класс.
abstract class A {
public void hello() {System.out.println("Hello World from A");}
}
interface B {
default void hello() { System.out.println("Hello World from B"); }
}
class C extends A implements B {
public static void main(String... args) {
new C().hello();
}
}
Таким образом, проблема решена:
· если конфликт на одном уровне иерархии — компилятор не даст сему случиться;
· если на разных уровнях — победит ближайший;
· если интерфейс против класса — побеждает класс.
В интерфейсах появилась возможность определять полноценные статические методы:
Литература :
1. Арнольд Кен, Гослинг Джеймс, Холмс Дэвид. Язык программирования Java. 3-е изд.: Пер. с англ. – М.: Издательский дом «Вильямс», 2001. – 624 с.: ил. ISBN 5-8459-0215-0 (рус.).
2. Хорстманн Кей С., Корнелл Гари. Java`2. Библиотека профессионала, том 1. Основы. 8-е издание.: Пер. с англ. – М.: ООО «И.Д. Вильямс», 2008. – 816 с.: ил. ISBN 978-5-8459-1378-4 (рус.).
3. Хорстманн Кей С., Корнелл Гари. Java`2. Библиотека профессионала, том II. Тонкости программирования. 7-е издание.: Пер. с англ. – М.: Издательский дом «Вильямс», 2008. – 1168 с.: ил. ISBN 978-5-8459-1033-2 (рус.).
4. Вязовик Н.А. Программирование на Java – М.: Интернет-Ун-т Информ. Технологий, 2003.
5. Шилдт Г. Java 2, v5.0 (Tiger). Новые возможности: Пер. с англ. – СПб.: БХВ-Петербург, 2005.
6. Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж. Приемы объектно-ориентированного проектирования. Паттерны проектирования – СПб.: Питер, 2001
7. JDK7: новые возможности Java SE. Сергей Гринев, Oracle.
8. http://microfork.com/whats-new-in-java-8/
9. https://habrahabr.ru/post/203026/
Дата: 2019-02-19, просмотров: 261.