Философия java онлайн. Вопросы и задания для русскоязычной книги Thinking in Java (Философия Java) Брюса Эккеля



Впервые читатель может познакомиться с полной версией этого классического труда, который ранее на русском языке печатался в сокращении. Книга, выдержавшая в оригинале не одно переиздание, за глубокое и поистине философское изложение тонкостей языка Java считается одним из лучших пособий для программистов. Чтобы по-настоящему понять язык Java, необходимо рассматривать его не просто как набор неких команд и операторов, а понять его “философию”, подход к решению задач, в сравнении с таковыми в других языках программирования. На этих страницах автор рассказывает об основных проблемах написания кода: в чем их природа и какой подход использует Java в их разрешении. Поэтому обсуждаемые в каждой главе черты языка неразрывно связаны с тем, как они используются для решения определенных задач.

Четвертое издание

Работая над новым изданием книги, я стремился реализовать в нем все, что узнал с момента выхода последнего издания. Часто эти поучительные уроки позволяли мне исправить какую-нибудь досадную ошибку или просто оживить скучный материал. Нередко в ходе работы над новым изданием у меня появлялись увлекательные новые идеи, а досаду от выявления ошибок затмевала радость открытия и возможность выражения своих идей в более совершенной форме.

Изменения

Компакт-диск, который традиционно прилагался к книге, в этом издании отсутствует. Важная часть этого диска - мультимедийный семинар Thinking in С (созданный для MindView Чаком Алисоном) - теперь доступна в виде загружаемой Flash-презентации. Цель этого семинара - подготовка читателей, незнакомых с синтаксисом С, к пониманию материала книги. Хотя в двух главах книги приведено неплохое вводное описание синтаксиса, для неопытных читателей их может оказаться недостаточно. Семинар Thinking in С поможет таким читателям подняться на необходимый уровень.

Пришлось, например, полностью переписать главу «Параллельное выполнение» (некогда «Многопоточность»), так чтобы материал соответствовал основным нововведениям Java SK5, но при этом в нем были отражены основные концепции многопоточности. Без такого фундамента понять более сложные вопросы многозадачности очень трудно. Я провел много месяцев в потустороннем мире «многопоточности», и материал, приведенный в конце главы, не только закладывает фундамент, но и прокладывает дорогу в более сложные территории.

Практически для каждой новой возможности Java SE5 в книге появилась отдельная глава, а другие новшества были отражены в изменениях существующего материала.

Мое изучение паттернов проектирования также не стояло на месте, поэтому в книге вы найдете описания новых паттернов.

Структура материала также претерпела серьезные изменения. В основном это объяснялось спецификой учебного процесса вместе с пониманием того, что мое представление о «главах» необходимо пересмотреть. Я был склонен бессознательно считать, что тема должна быть «достаточно большой» для выделения в отдельную главу. Но на семинарах (и особенно при описании паттернов проектирования) оказалось, что участники лучше всего воспринимают материал, если после описания одного паттерна мы немедленно выполняли упражнение, даже если теория излагалась недолго (также выяснилось, что такой темп изложения больше подходит мне как учителю). Итак, в этой версии я постарался разбить главы по темам, не обращая внимания на их объем. Думаю, книга от этого стала только лучше.

Я также осознал всю важность тестирования кода. Если каждый раз при сборке и запуске своей системы вы не выполняете встроенных тестов, то у вас нет возможности определить, насколько надежен ваш код. Специально для примеров данной книги была создана инфраструктура модульного тестирования, позволяющая показывать и проверять результаты работы каждой программы. (Инфраструктура написана на Python; вы найдете ее в загружаемом коде книги по адресу www.MindView.net.) Общие вопросы тестирования рассматриваются в приложении по адресу MindView.net/Books/ Betterjapa; на мой взгляд, это основополагающие навыки, которыми должен владеть каждый программист.

Вдобавок я просмотрел все примеры книги и для каждого из них задал себе вопрос: «Почему я написал это так?» Поэтому в большинстве случаев были добавлены некоторые улучшения и исправления, так чтобы в примерах прослеживалась общая тема и они демонстрировали то, что я считаю лучшими практическими приемами написания кода Java (по крайней мере, в материале вводного уровня). Некоторые из уже существовавших примеров были значительно переработаны. Те, которые потеряли свое значение, были удалены, их место заняли новые примеры.

Я получил от читателей очень много прекрасных отзывов о первых трех изданиях книги, и мне это было очень приятно. Однако всегда были и есть жалобы, и по какой-то причине постоянно существует недовольство по поводу того, что «книга очень велика». По-моему, это не очень строгая критика, если «очень много страниц» - ваше единственное замечание. (Оно напомнило мне замечание императора Австрии Моцарту о его композиции: «Очень много нот!» Заметьте, что я никоим образом не сравниваю себя с Моцартом.) Вдобавок, я могу предположить, что подобные замечания исходят от людей, не знакомых еще с «громадностью» самого языка Java и не видевших других книг, посвященных предмету обсуждения. Кроме того, в этом издании я попытался убрать из книги устаревшие части (или по крайней мере те, без которых можно обойтись). Так или иначе, я просмотрел весь материал, удалил все лишнее, включил изменения и улучши;! все, что только мог. Я легко расстался со старыми текстами, поскольку этот материал сохранился на сайте (www.MindView.net) в виде свободно доступных первых трех изданий, а также загружаемых приложений.

Для тех, кто все же не удовлетворен размером книги, я действительно приношу свои извинения. Верите вы или нет, но я очень старался уменьшить ее размер.


Чтобы изменить документ по умолчанию, отредактируйте файл "blank.fb2" вручную.

Предисловие 13

Java SE5 и SE6 14

Благодарности 14

Глава 1. Введение в объекты 17

Развитие абстракции 18

Объект имеет интерфейс 20

Объект предоставляет услуги 22

Скрытая реализация 23

Повторное использование реализации 24

Наследование 25

Взаимозаменяемые объекты и полиморфизм 29

Однокорневая иерархия 33

Контейнеры 33

Параметризованные типы 35

Создание, использование объектов и время их жизни 36

Обработка исключений: борьба с ошибками 38

Параллельное выполнение 38

Java и Интернет 39

Глава 2. Все является объектом 48

Все объекты должны создаваться явно 49

Объекты никогда не приходится удалять 53

Создание новых типов данных 54

Методы, аргументы и возвращаемые значения 56

Создание программы на Java 58

Ключевое слово static 60

Наша первая программа на Java 61

Комментарии и встроенная документация 64

Стиль оформления программ 70

Глава 3. Операторы 71

Простые команды печати 71

Операторы Java 72

Литералы 82

В Java отсутствует sizeof() 92

Резюме 100

Глава 4. Управляющие конструкции 101

Синтаксис foreach 105

break и continue 108

Нехорошая команда goto 109

Резюме 115

Глава 5. Инициализация и завершение 116

Конструктор гарантирует инициализацию 116

Перегрузка методов 118

Очистка: финализация и сборка мусора 130

Инициализация членов класса 137

Инициализация конструктором 140

Инициализация массивов 146

Резюме 151

Глава 6. Управление доступом 152

Пакет как библиотечный модуль 153

Спецификаторы доступа Java 159

Интерфейс и реализация 163

Доступ к классам 164

Резюме 167

Глава 7. Повторное использование классов 169

Синтаксис композиции 170

Синтаксис наследования 172

Делегирование 176

Сочетание композиции и наследования 178

Композиция в сравнении с наследованием 184

Восходящее преобразование типов 186

Ключевое слово final 188

Резюме 197

Глава 8. Полиморфизм 198

Снова о восходящем преобразовании. . . > 199

Особенности 201

Конструкторы и полиморфизм 208

Ковариантность возвращаемых типов 216

Разработка с наследованием 217

Резюме 220

Глава 9. Интерфейсы 221

Абстрактные классы и методы 221

Интерфейсы 224

Отделение интерфейса от реализации 227

Расширение интерфейса через наследование 233

Интерфейсы как средство адаптации 236

Вложенные интерфейсы 239

Интерфейсы и фабрики 242

Резюме 244

Глава 10. Внутренние классы 245

Создание внутренних классов 245

Связь с внешним классом 246

Конструкции.this и.new 248

Внутренние классы и восходящее преобразование 249

Безымянные внутренние классы 253

Внутренние классы: зачем? 261

Наследование от внутренних классов 272

Можно ли переопределить внутренний класс? 272

Локальные внутренние классы 274

Резюме 276

Глава 11. Коллекции объектов 277

Параметризованные и типизованные контейнеры 277

Основные концепции 280

Добавление групп элементов 281

Итераторы 288

Множество 294

Очередь 298

PriorityQueue 299

Collection и Iterator 301

Идиома «метод-адаптер» 306

Резюме 309

Глава 12. Обработка ошибок и исключения 310

Основные исключения 310

Перехват исключений 312

Создание собственных исключений 314

Спецификации исключений 319

Перехват произвольных исключений 320

Стандартные исключения Java 328

Завершение с помощью finally 330

Использование finally с return 334

Ограничения при использовании исключений 336

Конструкторы 339

Идентификация исключений 343

Альтернативные решения 344

Резюме 351

Глава 13. Информация о типах 352

Необходимость в динамическом определении типов (RTTI) 352

Регистрация фабрик 372

Рефлексия: динамическая информация о классе 376

Динамические посредники 380

Объекты с неопределенным состоянием 384

Интерфейсы и информация о типах 390

Резюме 394

Глава 14. Параметризация 397

Простая параметризация 398

Параметризованные интерфейсы 404

Параметризованные методы 407

Построение сложных моделей 419

Ограничения 437

Метасимволы 440

Резюме 452

Глава 15. Массивы 454

Особенности массивов 454

Массив как объект 456

Возврат массива 458

Многомерные массивы 460

Массивы и параметризация 463

Создание тестовых данных 465

Создание массивов с использованием генераторов 470

Вспомогательный инструментарий Arrays 474

Резюме 482

Глава 16. Система ввода/вывода Java 483

Класс File 484

Ввод и вывод 489

Добавление атрибутов и интерфейсов 491

Классы Reader и Writer 494

RandomAccessFile: сам по себе 497

Типичное использование потоков ввода/вывода 498

Средства чтения и записи файлов 505

Стандартный ввод/вывод 507

Новый ввод/вывод (nio) 510

Сжатие данных 531

Сериализация объектов 536

Предпочтения 553

Резюме 555

Глава 17. Параллельное выполнение 557

Класс Thread 559

Исполнители 561

Совместное использование ресурсов 578

Взаимодействие между потоками 598

Взаимная блокировка 602

Новые библиотечные компоненты 607

CountDownLatch 607

CyclicBarrier 609

PriorityBlockingQueue 614

Семафоры 619

Моделирование 624

Резюме 629

Алфавитный указатель 631

Введение в объекты

Мы препарируем природу, преобразуем ее в концепции и приписываем им смысл так, как мы это делаем во многом, потому что все мы являемся участниками соглашения, которое имеет силу в обществе, связанном речью, и которое закреплено в структуре языка... Мы не можем общаться вовсе, кроме как согласившись с установленными этим соглашением организацией и классификацией данных.

Бенджамин Ли Ворф (1897-1941)

Возникновением компьютерной революции мы обязаны машине. Поэтому наши языки программирования стараются быть ближе к этой машине.

Но в то же время компьютеры не столько механизмы, сколько средства уси¬ления мысли («велосипеды для ума», как любит говорить Стив Джобе), и еще одно средство самовыражения. В результате инструменты программирования все меньше склоняются к машинам и все больше тяготеют к нашим умам, также как и к другим формам выражения человеческих устремлений, как-то: литера¬тура, живопись, скульптура, анимация и кинематограф. Объектно-ориентиро- ванное программирование (ООП) - часть превращения компьютера в средство самовыражения.

Эта глава познакомит вас с основами ООП, включая рассмотрение основ¬ных методов разработки программ. Она, и книга вообще, подразумевает нали¬чие у вас опыта программирования на процедурном языке, не обязательно С. Если вам покажется, что перед прочтением этой книги вам не хватает познаний в программировании и синтаксисе С, воспользуйтесь мультимедийным семина¬ром Thinking in С, который можно загрузить с сайта

В марте прошлого года обратился в филиал крупной международной компании в Самаре (да. наглости и амбиций у меня с детства в избытке). Знал на тот момент html, css, java, javascript (основы), pascal, visualbasic6, запросы mysql, php, общее представление: c++. Джаву я не знал вообще. Предложили работу верстальщика, но я отказался. Только программистом! Тогда дали список:

Брюс Эккель Thinking in Java (русский перевод 2го издания или оригинал 4го - прочел и то и другое)
-Стив Макконел - совершенный код.
-Банда четырех - Дизайн паттернов. (это почти азбука ООП)
-иметь максимально четкое представление разницы j2se и j2ee.

в декабре возникла необходимость работы. устроился в мелкую самарскую web-студию. сразу было ясно, что это мошенники, но нужны были любые работы, которые я смог бы показать будущим работодателям. платить не платили(хоть все уши обещаниями проели), но код к стандартам оформления приводили, а главное научили куда смотреть и что искать при ошибках, какие мелочи легко упустить.

Помимо литературы выше прошел курс intuit (сейчас понимаю, что он смехотворен по своему объему, но в принципе основы там есть)

В конце февраля я повторно выслал резюме и получил приглашение пройти собеседование. Всего собеседований оказалось 6 и длились 1.5 месяца. Два из них прошли по видеосвязи с Москвой. Вся картина напоминала кино "Приходите завтра". Но в конце-концов я получил предложение о работе. Договор был составлен на неполную занятость, т.к. на тот момент диплома у меня не было. В прошлом месяце я диплом получил и договор перезаключили на полный рабочий.

Текущая должность Soft-Engeneer. Оклад более чем устраивает. Вчера в связи с переходом на полный рабочий подняли на 30%.

Даже в той жуликовской конторе спрашивали примеры работ. Я предъявил работы, выполненные мною по фрилансу. Даже работы на других языках всегда значительно лучше отсутствия таковых.

Ps: Диплом синий по ФИЗИКЕ. я полностью самоучка, так что все в ваших руках. только еще английский со школы Free у меня (7 часов в неделю был). хотя американец, который к нам приезжал во время своей кругосветки его плохо знает. я еле половину понял из-за его акцента. но это в моем отделе не так критично. вся документация на английском - выучишь даже если не знал)))))

Отдельное спасибо этому форуму. я учился фактически здесь - ежедневно учил все топики, что попадутся)

Глава 11. Коллекции объектов

Вопросы
1. Что такое интерфейс Collection?

Ответ

Интерфейс Collection - корневой интерфейс, описывающий общую функциональность всех последовательных контейнеров (с. 301).


2. Могут ли контейнеры использоваться для хранения примитивов?

Ответ

Примитивы в качестве элементов контейнера выступать не могут. В контейнер можно поместить только ссылки на объекты. Однако механизм автоупаковки (Autoboxing) автоматически преобразует примитив в объектный тип. Следовательно программист может «забыть» про вышеупомянутое ограничение.
(ответ дан совместно с )


3. Какой метод добавления элементов в контейнер ArrayList является предпочтительным:
Arrays.asList или Collections.addAll и почему?

Ответ

Collections.addAll является предпочтительным в силу его большей производительности (с. 282).


4. Перечислите несколько методов, доступных при работе с ArrayList.

Ответ

«contains(Object o)» – проверить наличия элемента в массиве.
«indexOf(Object o)» – получить индекс элемента.
«subList(index1, index2)» - скопировать часть элементов в новый контейнер.
«containsAll(Object o)» - проверка наличия элементов в контейнере.


5. Что возвращает метод remove(), вызванный для контейнера типа Queue?

Ответ

Метод Queue.remove() не только удаляет головной элемент очереди, но и возвращает его строковое значение.


6. Какие операции производятся быстрее при работе с LinkedList по сравнению с ArrayList?

Ответ

Вставка и удаления элементов из середины списка в случае использования LinkedList осуществляется быстрее (с. 291).


7. Какие типы контейнеров можно реализовывать с помощью LinkedList?

Ответ

Стек, очередь, двустороннюю очередь.


8. Чем семейство контейнеров Set отличается семейства контейнеров List? (спасибо за правку)

Ответ

В семействе контейнеров Set данные могут храниться только в одном экземпляре (с. 294)


9. Произойдет ли исключение при попытке добавить в Set элемент, который уже в нем присутствует?

Ответ

Исключения не произойдет.


10. Чем контейнер PriorityQueue отличается от Queue?

Ответ

Элементы в PriorityQueue можно сортировать по определенным правилам.


11. Для чего используется Comparator в применении к PriorityQueue?

Ответ

Comparator позволяет задавать правила сортировки элементов PriorityQueue.


12. Что означают префиксы «Tree» и «Hash», «LinkedHash», например, для типа контейнера Set (TreeSet, HashSet, LinkedHashSet)

Ответ

Префикс «Tree» означает, что элементы контейнера хранятся в отсортированном порядке
(например, в алфавитном порядке или по возрастанию) Префикс «Hash» означает, что контейнер реализует хэширование для ускорения выборки. Префикс «LinkedHash» означает, что контейнере элементы хранятся в порядке вставки, и при этом обеспечивается быстрый доступ (c. 309)


13. Поддерживает ли контейнер типа «Map» интерфейс Iterable?

14. Работает ли синтаксис foreach для контейнера типа «Map»?

Ответ

Для контейнера типа «Map» синтаксис foreach не работает, потому что им не поддерживается интерфейс iterable


15. В чем заключается основное преимущество использования итератора для доступа к элементам контейнера?

Ответ

Итератор может быть использован для контейнеров различного типа (с. 290).


16. Какие новые возможности предоставляются итератором ListIterator по сравнению с обычным итератором?

Ответ

ListIterator предоставляет последовательный доступ к элементам не только из начала в конец контейнера, но и наоборот (с. 290).

Упражнения

11. 1. Создайте класс Fruit. Класс должен содержать поле int weight, конструктор с инициализацией этого поля и метод printWeight(), печатающий значение weight.
В методе main добавьте несколько объектов Fruit в контейнер List. Вызовите printWeight() для каждого из объектов следующими способами:
А) с помощью метода get();
Б) с помощью итератора.

Ответ

// Fruit.java public class Fruit { private int weight = 0; public Fruit(int weight) { this.weight = weight; } public void printWeight() { System.out.println("Weight is: " + weight); } } // Apply.java import java.util.*; public class Apply { public static void main(String args) { List fruits = Arrays.asList(new Fruit(10), new Fruit(20)); // a System.out.println("Task a: "); for (Fruit f: fruits) { f.printWeight(); } // b System.out.println("Task b: "); Iterator it = fruits.iterator(); while(it.hasNext()) { it.next().printWeight(); } } }

11.2. Класс Fruit из 11.1 поместите в контейнер map. Пусть в качестве ключа будет указано имя владельца, в качестве значения – объект типа Fruit. Реализуйте перебор каждого объекта Fruit по ключу и вызов метода printWeight() для найденного объекта: с помощью foreach; с помощью iterator.

Ответ

Спасибо за компактный вариант решения с итератором.
класс Fruit - см. задание 11.2

Import java.util.*; import java.util.Map.Entry; public class Apply { public static void main(String args) { // Используем HashMap, так как сортировка не нужна Map fruit = new HashMap(); fruit.put("Bob", new Fruit(10)); fruit.put("Mary", new Fruit(20)); // перебор с помощью foreach System.out.println("With foreach"); for (String key: fruit.keySet()) { fruit.get(key).printWeight(); } // перебор с использованием итератора System.out.println("With iterator"); Iterator> it = fruit.entrySet().iterator(); while (it.hasNext()) { it.next().getValue().printWeight(); } } }

11.3. Используя Comparator для PriorityQueue обеспечьте сортировку строковых переменных по размеру.

Ответ

Примечание: пример взят из интернета.
// StringComparator.java import java.util.Comparator; public class StringComparator implements Comparator { @Override public int compare(String s1, String s2) { if (s1.length() < s2.length()) { return -1; } if(s1.length() > s2.length()) { return 1; } return 0; } } // PriorityQueue.java import java.util.Comparator; import java.util.PriorityQueue; public class PriorityQueueUse { public static void main(String args) { Comparator comparator = new StringComparator(); PriorityQueue queue = new PriorityQueue(10, comparator); queue.add("abcde"); queue.add("abc"); queue.add("abcdefghi"); queue.add("a"); // Элементы в очереди НЕ размещены в порядке возрастания длины String System.out.println("Before removing:"); System.out.println(queue); // Но элементы удаляются из очереди В порядке возрастания длины String System.out.println(); System.out.println("Look at removing order: "); while (queue.size() != 0) { System.out.println(queue.remove()); } } }

Перевод упражнений из оригинала книги:
11.4. Создайте новый класс Gerbil с полем int gerbilNumber. Пусть поле инициализируется конструктором. Создайте также метод hop(), который печатает «Gerbil’s number which is hopping is: » и значение переменной gerbilNumber. Разместите объекты Gerbil в контейнер ArrayList. Реализуйте метод get() для прохода по списку с вызовом метода hop() для каждого из этих объектов.

11.5. Модифицируйте SimpleCollection.java так, чтобы использовать метод Set для переменной «с». Модифицируйте innerclasses/Sequence.java таким образом, чтобы туда можно было бы добавлять любое количество элементов.

11.6. Напишите класс Generator, в котором есть список имен героев ваших любимых фильмов (объекты типа String). Пусть каждый объект этого списка возвращается посредством метода next(). При достижении конца созданного списка необходимо вернуться обратно в начало списка.
Используйте класс Generator для заполнения контейнеров типа ArrayList, LinkedList, HashSet, LinkedHashSet, TreeSet. Напишите универсальный метод, который выводил бы содержание каждого из массивов.

11.7. Модифицируйте ListFeatures.java таким образом, чтобы в нем использовались объекты типа Integers вместо объектов типа Pets. Объясните различия в результатах работы, возникшие из-за этой модификации.

11.8. Повторите упражнение 11.7 для ListFeatures.java, но замените Pets на Strings.

11.9. Создайте класс, который генерирует инициализированный массив объектов другого класса. С помощью этого массива заполните контейнер типа List. Создайте еще один контейнер, используя subList() для List. Затем удалите элементы, которые вы извлекли с помощью subList(), из контейнера, из которого вы их извлекали.

11.10. Шутливое упражнение на использование различных контейнеров и их методов (придумано самостоятельно)
Пусть у нас есть список из расходов, изначально состоящий из 3-х элементов: «food», «medicine», «entertainment». Необходимо записать эти элементы в контейнер List, причем порядок их следования не должен измениться.

1) Мы вдруг поняли, что забыли добавить в список расходы на выплату кредитов. Необходимо разместить запись «taxes» между «food» и «medicine» без использования индексов записей напрямую.
2) Жена притащила дополнительный отдельный список расходов с записями: «coat», «restaurant». Делать нечего: прибавить расходы в конец списка (чтобы не обольщалась).
3) Однако, теща притащила нам еще пару пунктиков: «theater», «home decoration» и «medicine». Может быть, какой-то из этих пунктов у Вас уже был. На всякий случай копируем содержание первого контейнера в новый контейнер типа Set и после, не задумываясь, добавляем эти пунктики в конец списка.
4) Не долго думая, мы создали ассоциативный динамический список расходов map, где Integer – планируемые затраты на каждый из пунктов расходов (суммы выбирайте самостоятельно).
5) Мы резко разбогатели решили увеличить сумму всех затрат на 30%. Напишите метод, который это сделает за вас.
6) Стоп! Довольно с нас «home decoration!» И, пожалуй, на coat уходит слишком много. Занесите эти пункты в новый List и передайте методу, который, считав этот лист, в контейнере Map отыщет соответствующие статьи расходов и уменьшит их на … 80%!
7) Свалим-ка часть расходов на тещу. Причем, сделаем ей сюрприз! Сгенерим два случайных числа, которые будут определять начальный и конечный индексы, все расходы между которыми будут записаны в отдельный список List (который впоследствии будет теще подсунут). Не забудем обновить Map, выкинув из него соответствующие статьи расходов.
8) Напишем метод, который определит, на что уходит самая малая сумма расходов, напечатаем название этих расходов и с гордостью удалим этот элемент из списка.
9) Однако, к нам подвалили дополнительные расходики: «food» и «restaurant», оформленные в виде очередного массива! Проверим, есть ли они в нашем списке эти пункты? И если хотя бы один расход есть, то ни в коем случае не будем их добавлять! Если же ничего этого нет, то (ничего не поделаешь), добавляем сразу оба эти пункта (как я проголодался!).
10) Мы сошли с ума! Прочитаем из списка Map все Integer суммы оставшихся у нас расходов, запишем их в «какой-нибудь» контейнер, который сам их нам рассортирует по возрастанию, потом в ярости перемешаем и удалим с проходом в обратном порядке, неистово применив для этого специальный итератор.