Как и обещал, предлагаю вашему вниманию следующие пять пунктов.
Малоизвестные особенности Java. Первая часть
6. Конфликт имён.
Если импортированы несколько классов с одним и тем же именем из разных пакетов, возникает конфликт имён. В таком случае при обращении к классу следует указывать его квалифицированное имя, то есть полное имя, включая и имя пакета, например java.lang.String.
Неужели ничего нельзя с этим поделать? Оказывается можно. Следующий код скомпилируется без проблем, несмотря на то, что класс List присутствует и в пакете java.awt, и в пакете java.util:
Достаточно дополнительно импортировать необходимый класс, java.util.List в данном примере.
Тут, как вы заметили, используются кириллические идентификаторы. Да! Для кого-то это станет откровением, но Java… такая Java. Идентификатор может состоять из совершенно любых букв, помимо цифр, знаков подчёркивания и валюты США (однако последний знак ($) использовать не рекомендуется, он предназначен для системных нужд). Но оно нам надо? Разве только в целях обфускации. Только представьте себе, сколько разных идентификаторов можно сгенерировать всего-то из символов «А» английского, русского и греческого алфавитов…
7. Инициализация коллекций.
К каким только хитростям не приходится прибегать, чтобы упростить инициализацию коллекций и облегчить восприятие кода. Благодаря переменному числу аргументов в методе (varargs), которое появилось в пятой версии SDK, а также заботливому обновлению разработчиками стандартного API, ситуация стала немного лучше:
Но этот код занимает две строки вместо одной и не кажется логически связанным. Можно использовать сторонние библиотеки, такие как Google Collections, или изобрести свой велосипед, но есть и более опрятный вариант:
А с появлением статического импорта во всё той же версии Java можно укоротить эту конструкцию ещё на одно слово:
Впрочем, если число элементов в коллекции изменяться не будет, мы можем написать совсем просто:
Эти приёмы позволяют инициализировать коллекции-наследники интерфейса Collection, простите за каламбур, но с картами так не получится, к сожалению. Хотя решение есть, смотрите предыдущую часть статьи.
8. Подсписки.
Интерфейс java.util.List, от которого наследуются в частности ArrayList и LinkedList, обладает замечательным методом: List.subList(). Он возвращает не новый список, как может показаться, а вид (view) списка, для которого этот метод был вызван, таким образом, что оба списка станут разделять хранимые элементы. Из этого вытекают прекрасные свойства:
В данном примере из списка someList будут удалены четыре элемента, с третьего по седьмой (не включительно).
Подсписки можно использовать в качестве диапазонов (ranges), которые являются довольно мощной идиомой программирования. Как часто вам требовалось обойти коллекцию, исключая первый или последний элемент, например? Теперь foreach становится ещё мощнее:
Подсписки следует использовать с осторожностью из-за особенностей, вытекающих из их сути (для подробностей смотрите документацию).
9. Cafe babe.
Все скомпилированные классы и интерфейсы хранятся в специальных файлах с расширением .class. В них содержится байт-код, интерпретируемый виртуальной машиной Java. Чтобы быстро распознавать эти файлы, в них, в первых четырёх байтах, содержится метка, которая в шестнадцатеричном виде выглядит так: 0xCAFEBABE.
Ну с первым словом всё ясно — Java, как известно, названа была не в честь тропического острова, а одноимённого сорта кофе, и среди знаков, используемых в шестнадцатеричной системе cчисления, литер «J» и «V» не нашлось. А вот чем руководствовались разработчики, выдумывая второе слово, остаётся только догадываться:)
10. Исключительные ситуации.
И напоследок небольшой кусочек кода:
Здесь выбрасывается NullPointerException и… теряется, исчезает без следа! Будьте бдительны.
Малоизвестные особенности Java. Первая часть
6. Конфликт имён.
Если импортированы несколько классов с одним и тем же именем из разных пакетов, возникает конфликт имён. В таком случае при обращении к классу следует указывать его квалифицированное имя, то есть полное имя, включая и имя пакета, например java.lang.String.
Неужели ничего нельзя с этим поделать? Оказывается можно. Следующий код скомпилируется без проблем, несмотря на то, что класс List присутствует и в пакете java.awt, и в пакете java.util:
import java.awt.*;
import java.util.*;
import java.util.List;
public class Класс {
public static void main(String... аргументы) {
List простоСписок = Collections.emptyList();
System.out.println(простоСписок);
}
}
Достаточно дополнительно импортировать необходимый класс, java.util.List в данном примере.
Тут, как вы заметили, используются кириллические идентификаторы. Да! Для кого-то это станет откровением, но Java… такая Java. Идентификатор может состоять из совершенно любых букв, помимо цифр, знаков подчёркивания и валюты США (однако последний знак ($) использовать не рекомендуется, он предназначен для системных нужд). Но оно нам надо? Разве только в целях обфускации. Только представьте себе, сколько разных идентификаторов можно сгенерировать всего-то из символов «А» английского, русского и греческого алфавитов…
7. Инициализация коллекций.
К каким только хитростям не приходится прибегать, чтобы упростить инициализацию коллекций и облегчить восприятие кода. Благодаря переменному числу аргументов в методе (varargs), которое появилось в пятой версии SDK, а также заботливому обновлению разработчиками стандартного API, ситуация стала немного лучше:
List<Integer> theNumbers = new LinkedList<Integer>();
Collections.addAll(theNumbers, 4, 8, 15, 16, 23, 42);
Но этот код занимает две строки вместо одной и не кажется логически связанным. Можно использовать сторонние библиотеки, такие как Google Collections, или изобрести свой велосипед, но есть и более опрятный вариант:
List<Integer> theNumbers = new LinkedList<Integer>(Arrays.asList(4, 8, 15, 16, 23, 42));
А с появлением статического импорта во всё той же версии Java можно укоротить эту конструкцию ещё на одно слово:
import static java.util.Arrays.*;
// ...
List<Integer> theNumbers = new LinkedList<Integer>(asList(4, 8, 15, 16, 23, 42));
Впрочем, если число элементов в коллекции изменяться не будет, мы можем написать совсем просто:
import static java.util.Arrays.*;
// ...
List<Integer> theNumbers = asList(4, 8, 15, 16, 23, 42);
Эти приёмы позволяют инициализировать коллекции-наследники интерфейса Collection, простите за каламбур, но с картами так не получится, к сожалению. Хотя решение есть, смотрите предыдущую часть статьи.
8. Подсписки.
Интерфейс java.util.List, от которого наследуются в частности ArrayList и LinkedList, обладает замечательным методом: List.subList(). Он возвращает не новый список, как может показаться, а вид (view) списка, для которого этот метод был вызван, таким образом, что оба списка станут разделять хранимые элементы. Из этого вытекают прекрасные свойства:
someList.subList(3, 7).clear();
В данном примере из списка someList будут удалены четыре элемента, с третьего по седьмой (не включительно).
Подсписки можно использовать в качестве диапазонов (ranges), которые являются довольно мощной идиомой программирования. Как часто вам требовалось обойти коллекцию, исключая первый или последний элемент, например? Теперь foreach становится ещё мощнее:
import static java.util.Arrays.*;
// ...
List<Integer> theNumbers = asList(4, 8, 15, 16, 23, 42);
int size = theNumbers.size();
for (Integer number : theNumbers.subList(0, size - 1)) {
System.out.print(number + ", ");
}
System.out.println(theNumbers.get(size - 1));
Подсписки следует использовать с осторожностью из-за особенностей, вытекающих из их сути (для подробностей смотрите документацию).
9. Cafe babe.
Все скомпилированные классы и интерфейсы хранятся в специальных файлах с расширением .class. В них содержится байт-код, интерпретируемый виртуальной машиной Java. Чтобы быстро распознавать эти файлы, в них, в первых четырёх байтах, содержится метка, которая в шестнадцатеричном виде выглядит так: 0xCAFEBABE.
Ну с первым словом всё ясно — Java, как известно, названа была не в честь тропического острова, а одноимённого сорта кофе, и среди знаков, используемых в шестнадцатеричной системе cчисления, литер «J» и «V» не нашлось. А вот чем руководствовались разработчики, выдумывая второе слово, остаётся только догадываться:)
10. Исключительные ситуации.
И напоследок небольшой кусочек кода:
try {
throw null;
} finally {
return;
}
Здесь выбрасывается NullPointerException и… теряется, исчезает без следа! Будьте бдительны.