Философия Java3
Шрифт:
В последующих версиях Java поддержка контейнеров была значительно улучшена. Сейчас контейнеры превосходят массивы во всех отношениях, кроме быстродействия, хотя производительность контейнеров была значительно улучшена. С добавлением автоматической упаковки и параметризации хранение примитивов в контейнерах требует меньших усилий и способствует дальнейшему переходу с низкоуровневых массивов на контейнеры. Так как параметризация открыла доступ к типизованным контейнерам, в этом отношении массивы тоже утратили исходные преимущества.
Как было показано в этой главе, параметризация плохо сочетается с контейнерами. Даже если вам удастся тем или иным способом заставить
Все эти факторы показывают, что при программировании для последних версий Java следует отдавать предпочтение контейнерам перед массивами. На массивы следует переходить только при критичных требованиях по быстродействию — и только в том случае, если переход принесет ощутимую пользу.
Система
ввода/вывода
Java
Создание хорошей системы ввода/вывода является одной из труднейших задач разработчика языка. Доказательством этого утверждения служит множество подходов, используемых при разработке систем ввода/вывода.
Основная сложность состоит в том, что необходимо учесть все возможные ситуации. Это не только наличие множества источников и приемников данных, с которыми необходимо поддерживать связь (файлы, консоль, сетевые соединения), но и реализации различных форм этой связи (последовательный доступ, произвольный, буферизованный, двоичный, символьный, построчный, пословный и т. д.).
Разработчики библиотеки Java решили начать с создания огромного количества классов. Вообще говоря, в библиотеке ввода/вывода Java так много классов, что потеряться в них проще простого (парадоксально, но сама система ввода/вывода Java в действительности не нуждается в таком количестве классов). Потом, после выхода первой версии языка Java, в библиотеке ввода/вывода последовали значительные изменения: к ориентированным на посылку и прием байтов классам добавились основанные на Юникод классы, работающие с символами. В JDK 1.4 классы nio (от сочетания «new I/O», «новый ввод/вывод») призваны улучшить производительность и функциональность. В результате, чтобы понять общую картину ввода/вывода в Java и начать использовать ее, вам придется изучить порядочный ворох классов. Вдобавок не менее важно понять и изучить эволюцию библиотеки ввода/вывода, несмотря на вашу очевидную реакцию: «Избавьте меня от истории! Просто покажите, как работать с библиотекой!» Если не уяснить причины изменений, проведенных в библиотеке ввода/вывода, вскоре мы запутаемся в ней и не сможем твердо аргументировать сделанный нами выбор в пользу того или иного класса.
В этой главе мы познакомимся с различными классами, отвечающими за ввод/вывод в библиотеке Java, а также научимся использовать их.
Класс File
Перед тем как перейти к классам, которые осуществляют реальные запись и чтение данных, мы рассмотрим вспомогательные инструменты библиотеки, предназначенные для работы с файлами и каталогами.
Имя класса File весьма обманчиво: легко подумать, что оно всегда ссылается на файл, но это не так. Класс File может представлять как имя определенного файла, так, имена группы файлов, находящихся в каталоге. Если класс представляет каталог, его метод list возвращает массив строк с именами всех файлов. Использовать в данной ситуации массив (а не более
Список каталогов
Предположим, вы хотите получить содержимое каталога. Объект File позволяет получить этот список двумя способами. Если вызвать метод list без аргументов, то результатом будет полный список файлов и каталогов (точнее, их названий), содержащихся в данном каталоге. Но, если вам нужен ограниченный список — например, список всех файлов с расширением .java, — используйте «фильтр», то есть класс, который описывает критерии отбора объектов File.
Рассмотрим пример. Заметьте, что полученный список без всяких дополнительных усилий сортируется (по алфавиту) с помощью метода j a va. u ti L. Array. sort и объекта String.CASE_INSENSITIVE_ORDER:
//: io/DirList java
// Вывод списка каталогов с использованием регулярных выражений
// {Параметры- "D *\.java"}
import java.util regex.*.
import java io.*.
import java util *,
public class DirList {
public static void main(String[] args) { File path = new File(" "). StringC] list, if(args length == 0)
list = path listO.
else
list = path list(new DirFilter(args[0])); Arrays sortdist. String CASE_INSENSITIVE_ORDER). for(String dirltem list)
System.out.printin(dirltem).
class DirFiIter implements FilenameFilter { private Pattern pattern; public DirFilter(String regex) {
pattern = Pattern compile(regex);
}
public boolean accept(File dir. String name) { return pattern matcher(name) matchesO;
}
} /* Output DirectoryDemo java DirList java DirList2 java DirList3 java III ~
Класс DirFilter реализует интерфейс FilenameFilter. Посмотрите, как просто выглядит этот интерфейс:
public interface FilenameFilter {
boolean accept(File dir. String name).
}
Это показывает, что данный тип объекта должен поддерживать метод с именем accept, который вызывается методом list с целью определения того, какие имена файлов должны включаться в выходной список, а какие нет. Перед нами один из примеров паттерна «стратегия»: list реализует базовую функциональность, a FilenameFilter предоставляет алгоритм, необходимый для работы list. Так как метод list принимает в качестве аргумента объект Filename-Filter, ему можно передать любой объект любого класса, лишь бы он реализовы-вал интерфейс FilenameFilter (даже во время выполнения). Таким образом легко изменять результат работы метода list. Целью данного паттерна является обеспечение гибкости в поведении кода.
Метод accept получает объект File, представляющий собой каталог, в котором был найден данный файл, и строку с именем файла. Помните, что метод list вызывает accept для каждого файла, обнаруженного в каталоге, чтобы определить, какие из них следует включить в выходной список — в зависимости от возвращаемого значения accept (значение типа boolean).
Метод accept использует объект регулярного выражения matcher, чтобы посмотреть, соответствует ли имя файла выражению regex. Метод list возвращает массив.