Чем отличается Closeable от AutoCloseable?
Интерфейс AutoCloseable представляет объект-хранилище некоего ресурса, пока тот не закрыт. В единственном его методе close() объявляется логика закрытия этого ресурса. Пример – дескриптор открытого файла (ObjectOutputStream).
Особенность этого интерфейса в том, что его применение позволяет использовать объект в языковой конструкции try-with-resource. Всё это появилось в Java версии 7.
До Java 7 уже существовал похожий интерфейс – Closeable. Смысл его точно такой же. Он всё еще доступен в стандартной библиотеке для обратной совместимости, но в новом коде рекомендуется использовать AutoCloseable. Чтобы экземпляры старого Closeable тоже можно было использовать в try-with-resource, новый интерфейс был добавлен его родителем.
Проблема старого интерфейса Closeable была в узости типа исключений, которые может выбрасывать close(). Ковариантность позволила расширить тип в базовом интерфейсе AutoCloseable с IOException до Exception.
Еще одно отличие – контракт метода close(). Старый Closeable требует его идемпотентности, тогда как новый AutoCloseable разрешает методу иметь побочные эффекты.
Интерфейс AutoCloseable представляет объект-хранилище некоего ресурса, пока тот не закрыт. В единственном его методе close() объявляется логика закрытия этого ресурса. Пример – дескриптор открытого файла (ObjectOutputStream).
Особенность этого интерфейса в том, что его применение позволяет использовать объект в языковой конструкции try-with-resource. Всё это появилось в Java версии 7.
До Java 7 уже существовал похожий интерфейс – Closeable. Смысл его точно такой же. Он всё еще доступен в стандартной библиотеке для обратной совместимости, но в новом коде рекомендуется использовать AutoCloseable. Чтобы экземпляры старого Closeable тоже можно было использовать в try-with-resource, новый интерфейс был добавлен его родителем.
Проблема старого интерфейса Closeable была в узости типа исключений, которые может выбрасывать close(). Ковариантность позволила расширить тип в базовом интерфейсе AutoCloseable с IOException до Exception.
Еще одно отличие – контракт метода close(). Старый Closeable требует его идемпотентности, тогда как новый AutoCloseable разрешает методу иметь побочные эффекты.
🔥11👍8😁2
Как Java выбирает перегруженный метод?
Метод может быть перегружен различными параметрами – в классе могут существовать несколько разных методов с одинаковым названием. При вызове такого метода выбор конкретного варианта происходит на этапе компиляции (раннее связывание). В деталях алгоритм выбора перегруженного метода описан в спецификации.
Выбор происходит в два шага. На первом выбирается одна из трех фаз – множество подходящих методов.
1. Методы, в которые переданные параметры подходят по типу либо как есть, либо с применением расширения (upcasting) примитивов или ссылочных типов, исключая vararg-параметры.
2. Если в фазе 1 подходящих методов не нашлось, к ее условиям добавляются возможность боксинга/анбоксинга параметров. Обратите внимание, в комбинации работает только боксинг+расширение, но не наоборот.
3. Если и для фазы 2 нет удовлетворительных сигнатур, к условиям поиска подключаются vararg-параметры.
В случае, когда ни один метод не нашелся ни в одной фазе, компиляция завершается ошибкой.
Когда в фазе имеется несколько подходящих методов, используется наиболее специфичный среди них (но только в рамках данной фазы!).
Метод A считается более специфичным чем B, когда типы параметров одного метода – подтипы типов параметров другого. То есть любые возможные значения аргументов A подошли бы и для B, но не наоборот.
В условии специфичности говорится о типах параметров метода, а не о типах передаваемых значений. Так что боксинг/анбоксинг не учитывается, и метод с параметром int не считается более специфичным, чем с параметром Object (в отличие от Integer). Хотя, целое число можно передавать и как Object, и как Integer. Подробное объяснение.
Когда среди методов невозможно выделить один наиболее специфичный, происходит ошибка компиляции.
@javatasks #java
Метод может быть перегружен различными параметрами – в классе могут существовать несколько разных методов с одинаковым названием. При вызове такого метода выбор конкретного варианта происходит на этапе компиляции (раннее связывание). В деталях алгоритм выбора перегруженного метода описан в спецификации.
Выбор происходит в два шага. На первом выбирается одна из трех фаз – множество подходящих методов.
1. Методы, в которые переданные параметры подходят по типу либо как есть, либо с применением расширения (upcasting) примитивов или ссылочных типов, исключая vararg-параметры.
2. Если в фазе 1 подходящих методов не нашлось, к ее условиям добавляются возможность боксинга/анбоксинга параметров. Обратите внимание, в комбинации работает только боксинг+расширение, но не наоборот.
3. Если и для фазы 2 нет удовлетворительных сигнатур, к условиям поиска подключаются vararg-параметры.
В случае, когда ни один метод не нашелся ни в одной фазе, компиляция завершается ошибкой.
Когда в фазе имеется несколько подходящих методов, используется наиболее специфичный среди них (но только в рамках данной фазы!).
Метод A считается более специфичным чем B, когда типы параметров одного метода – подтипы типов параметров другого. То есть любые возможные значения аргументов A подошли бы и для B, но не наоборот.
В условии специфичности говорится о типах параметров метода, а не о типах передаваемых значений. Так что боксинг/анбоксинг не учитывается, и метод с параметром int не считается более специфичным, чем с параметром Object (в отличие от Integer). Хотя, целое число можно передавать и как Object, и как Integer. Подробное объяснение.
Когда среди методов невозможно выделить один наиболее специфичный, происходит ошибка компиляции.
@javatasks #java
🔥9👍8👏3😁1
Для чего используются аннотации?
Удобно рассмотреть случаи применения аннотаций с точки зрения возможных значений их свойства RetentionPolicy:
SOURCE – аннотация присутствует только в исходном коде, но не вовлечена в компиляцию. Можно разделить их на две категории:
Первая – аннотации для программиста, а не для программы. Это всевозможные маркеры. Они добавляют аннотируемым элементам некоторую специальную семантику. Более формализованный вариант документации. Примеры – @Immutable и @ThreadSafe из Hibernate.
Вторая категория – инструкции для инструментов разработки. Примеры этой категории, @SuppressWarnings и @Override могут влиять на предупреждения и ошибки компиляции. IntelliJ IDEA умеет понимать @Nullable и @NonNull из Spring Framework, и предупреждать о возможных NullPointerException.
CLASS – самое экзотическое, но при том стандартное значение. Аннотация попадает в байткод .class-файла, но игнорируется загрузчиком классов. В результате такая аннотация недоступна для рефлекшна. Используется для сторонних инструментов, обрабатывающих байткод, например для обфускаторов.
RUNTIME – самое ходовое значение. Цель снабжается метаинформацией, доступной во время выполнения программы. Сама по себе аннотация всё так же не добавляет нового поведения. Для практической пользы runtime-аннотации в программе должен быть исполнен некоторый код процессинга, который прочитает метаинформацию инструментами Reflection API. Такой механизм широко используется во множестве популярных фреймворков: Spring, Hibernate, Jackson.
Удобно рассмотреть случаи применения аннотаций с точки зрения возможных значений их свойства RetentionPolicy:
SOURCE – аннотация присутствует только в исходном коде, но не вовлечена в компиляцию. Можно разделить их на две категории:
Первая – аннотации для программиста, а не для программы. Это всевозможные маркеры. Они добавляют аннотируемым элементам некоторую специальную семантику. Более формализованный вариант документации. Примеры – @Immutable и @ThreadSafe из Hibernate.
Вторая категория – инструкции для инструментов разработки. Примеры этой категории, @SuppressWarnings и @Override могут влиять на предупреждения и ошибки компиляции. IntelliJ IDEA умеет понимать @Nullable и @NonNull из Spring Framework, и предупреждать о возможных NullPointerException.
CLASS – самое экзотическое, но при том стандартное значение. Аннотация попадает в байткод .class-файла, но игнорируется загрузчиком классов. В результате такая аннотация недоступна для рефлекшна. Используется для сторонних инструментов, обрабатывающих байткод, например для обфускаторов.
RUNTIME – самое ходовое значение. Цель снабжается метаинформацией, доступной во время выполнения программы. Сама по себе аннотация всё так же не добавляет нового поведения. Для практической пользы runtime-аннотации в программе должен быть исполнен некоторый код процессинга, который прочитает метаинформацию инструментами Reflection API. Такой механизм широко используется во множестве популярных фреймворков: Spring, Hibernate, Jackson.
👍12🔥3❤2😁1
Зачем нужно ключевое слово assert?
assert – не то же самое, что методы вроде assertTrue() из тестовых библиотек. Это зарезервированное ключевое слово, унарный оператор.
Этот оператор ничего не возвращает, а принимает проверяемое утверждение типа boolean. Если значение оказывается false, проверка утверждения считается проваленной и выбрасывается AssertionError. Это похоже на сокращенную запись пары if и throw, с фиксированным типом исключения.
В Java до версии 4 слово assert не было ключевым. Поэтому для обратной совместимости механизм проверки утверждений выключен по умолчанию – логика программы никогда не должна полагаться на assert!
Включается флагом -ea или -enableassertions команды java. Можно указывать конкретные классы и пакеты в которых включить. Есть противоположный флаг -da (-disableassertions), эти флаги можно использовать в комбинации.
Assertion-ы используются в основном для дополнительной проверки инвариантов состояния объекта и для подстраховки в коде, который не должен никогда вызываться. Выброшенный AssertionError обычно означает ошибку программиста.
Дополнительно у оператора assert есть синтаксис передачи параметра detailMessage в конструктор AssertionError:
@javatasks #java
assert – не то же самое, что методы вроде assertTrue() из тестовых библиотек. Это зарезервированное ключевое слово, унарный оператор.
Этот оператор ничего не возвращает, а принимает проверяемое утверждение типа boolean. Если значение оказывается false, проверка утверждения считается проваленной и выбрасывается AssertionError. Это похоже на сокращенную запись пары if и throw, с фиксированным типом исключения.
В Java до версии 4 слово assert не было ключевым. Поэтому для обратной совместимости механизм проверки утверждений выключен по умолчанию – логика программы никогда не должна полагаться на assert!
Включается флагом -ea или -enableassertions команды java. Можно указывать конкретные классы и пакеты в которых включить. Есть противоположный флаг -da (-disableassertions), эти флаги можно использовать в комбинации.
Assertion-ы используются в основном для дополнительной проверки инвариантов состояния объекта и для подстраховки в коде, который не должен никогда вызываться. Выброшенный AssertionError обычно означает ошибку программиста.
Дополнительно у оператора assert есть синтаксис передачи параметра detailMessage в конструктор AssertionError:
assert 2*2==5 : "two times two is not five!";
@javatasks #java
👍7🔥7❤4
Что такое метки и как их использовать?
Наверняка вам приходилось писать неуклюжий код выхода из циклов нескольких уровней вложенности:
В Java существует полезный синтаксис, который упрощает код в таких ситуациях – метки (label).
Метка используется как пункт назначения для операторов break и continue. Помечать можно любой блок – цикл for, while, даже простой блок и операторы switch и if. Метки делают возможным использование оператора break вне цикла, хотя пользы в этом обычно немного.
Обязательное условие компилятора – метка должна использоваться только внутри помеченного блока. Перейти в соседний цикл не выйдет.
Наверняка вам приходилось писать неуклюжий код выхода из циклов нескольких уровней вложенности:
boolean flag = false;
for (...) {
for (...) {
if (...) { x = true; break; }
}
if (flag == true) break;
}
В Java существует полезный синтаксис, который упрощает код в таких ситуациях – метки (label).
Метка используется как пункт назначения для операторов break и continue. Помечать можно любой блок – цикл for, while, даже простой блок и операторы switch и if. Метки делают возможным использование оператора break вне цикла, хотя пользы в этом обычно немного.
Обязательное условие компилятора – метка должна использоваться только внутри помеченного блока. Перейти в соседний цикл не выйдет.
👍13🤔3
Что такое Keyword?
Зарезервированные слова в Java – это специальные последовательности символов, которые воспринимаются компилятором особым образом. Такие слова нельзя использовать как названия классов, переменных, и для других идентификаторов. Все зарезервированне слова можно разбить на три больших группы. Все они перечислены в таблице ниже.
1. 4 зарезервированных слова не являются ключевыми словами: это литералы true, false, null, и специальный идентификатор выводимого типа var.
2. 51 ключевое слово (keywords). В таблице мы сгруппировали их по смыслу.
3. 10 ограниченных ключевых слов (restricted keywords). Они считаются ключевыми словами только в контексте файла объявления модуля module-info. В обычных .java-файлах это разрешенные идентификаторы.
@javatasks #java
Зарезервированные слова в Java – это специальные последовательности символов, которые воспринимаются компилятором особым образом. Такие слова нельзя использовать как названия классов, переменных, и для других идентификаторов. Все зарезервированне слова можно разбить на три больших группы. Все они перечислены в таблице ниже.
1. 4 зарезервированных слова не являются ключевыми словами: это литералы true, false, null, и специальный идентификатор выводимого типа var.
2. 51 ключевое слово (keywords). В таблице мы сгруппировали их по смыслу.
3. 10 ограниченных ключевых слов (restricted keywords). Они считаются ключевыми словами только в контексте файла объявления модуля module-info. В обычных .java-файлах это разрешенные идентификаторы.
@javatasks #java
👍13
Что произойдет при попытке вставить в TreeSet объект, если его класс не pеализует интерфейс Comparable и не передан компаратор?
Anonymous Quiz
18%
Будет выброшено исключение ClassCastException только при попытке сортировки
11%
Элемент будет добавлен в конец коллекции
46%
Будет выброшено исключение ClassCastException
17%
Элемент будет вставлен, но без определенного порядка
8%
Будет выброшено исключение NullPointerException
👍12🔥5
Какой результат может вывести фрагмент кода?
Anonymous Quiz
5%
0
7%
1
45%
2
42%
Невозможно предсказать
🔥8👍5
Что будет выведено на экран?
Anonymous Quiz
2%
Исключение во время выполнения
80%
Child
6%
Ошибка компиляции
12%
Parent
🔥9👍5❤3😁1
👍14❤3🔥3🌚1
Как найти любой элемент в списке, который начинается с буквы "b"?
Anonymous Quiz
13%
list. filter(s -> s.startsWith("b")).findAny().ifPresent(System.out::println);
5%
list.stream().filter().findFirst().ifPresent(System.out::println);
25%
list.stream().findAny(s-> s.startsWith("b")).ifPresent(System.out::println);
50%
list.stream().filter(s -> s.startsWith("b")).findAny().ifPresent(System.out::println);
7%
list.stream().map(s-> s.startsWith("b")).findAny().ifPresent(System.out::println);
👍14🔥3❤1🥰1👏1
Как часто выполняется метод scheduledTask()?
Anonymous Quiz
3%
Каждые 5 минут
15%
Каждые 5000 секунд
13%
При каждом запуске приложения
68%
Каждые 5 секунд
1%
Каждый час
👍7🔥5❤2😐2
Какой интерфейс коллекций гарантирует отсутствие дубликатов?
Anonymous Quiz
1%
List
2%
Deque
87%
Set
8%
Мар
2%
Queue
❤11👍7🔥3
Что выведет этот фрагмент кода?
Anonymous Quiz
9%
Ничего не выведет
1%
4
62%
24
4%
10
20%
Произойдет ошибка
3%
12
👍8🔥2