1


 
 
 

МЕХЗАВОД | Сайтостроение для начинающих

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Стоит ли учить Java новичку. Стажировка Java

Сообщений 1 страница 4 из 4

1

В этом видео речь пойдет о Java. Один из самых перспективных языков программирования. У Java программистов одни из самых высоких зарплат в it сфере. Сегодня мы обсудим стоит ли учить Java именно новичку и почему. Расскажу о нюансах

2

3

Недавно разгуливая по форумам заметил эту тему и ужаснулся требованиями.

Что Должен Знать Настоящий Java Разработчик

Вот перечисляю

1. OOA, OOD, gof и j2ee паттерны, свободное чтение УМЛ (особенно диаграммы классов, объектов, взаимодействия и состояния).

2. Нужно знать все базовые библиотеки (коллекции, сериализации, потоки ввода-вывода, работа с сеткой, рефлекшн, обработка событий, неблокирующий ввод-вывод, локализацию и т.п.). Особенно многопоточность!

3. Нужно понимать как работают виртуальная машина, загрузка классов, сборка мусора. Желательно знать базовые инструкции байт-кода.

4. Нужно уметь создавать апплеты и приложения на AWT, Swing и SWT. Естественно, и компонентную модель Java beans для элементов управления.

5. JDBC и какой-нибудь ОРМ, например Hibernate или JDO. Естественно понимать как такое отображение влияет на взаимодействие прикладных объектов и основные грабли с производительностью.

6. Java security (загрузка классов, верификация байт кода, полиси и пермишны, подписывание кода, сигнатуры, ключи и т.п.). Конечно же освоить следующие апи: JAAS, JCE, JSSE, JGSS.

7. Сервлеты, JSP, JSTL. (маленький такой пунктик)

8. Фреймворки для создания веб-приложений: Struts, JSF, Tapestry, Cocoon и т.п. Конечно же MVC должен быть на уровне рефлексов.

9. Tomcat, как туда деплоить и как поддерживать веб-приложения.

10. RMI, манипуляция удалёнными объектами.

11. Jini, технология создания распределённых приложений.

12. Парсинг XML, желательно попробовать SAX и все три апи (DOM, JDOM, DOM4J). Создание преобразований XSLT (синтаксис, семантика, часто-используемые конструкции и идиомы).

13. Веб-сервисы. Изучить JAX-RPC, SAAJ, JAXB, JAXM, JAXR. Конечно же Axis как одну из самых распространённых имплементаций SOAP.

14. Изучить лёгковесные фреймворки: Spring, Pico/NanoContainer. Знать что такое IoC и как он влияет на архитектуру.

15. Незаметный пунктик: J2EE. Разумеется не получится пройти мимо JNDI, JMS, JTA, JMX и javamail.

16. Знать, как конфигурить J2EE аппликейшн сервер, например JBOSS. Как использовать его встроенные сервисы (например, кластеризация, пулы коннекшнов, поддержку распределённых транзакций). Конечно же как деплоить/ундеплоить приложения туда, как настраивать производительность.

17. Понимать Аспектно-Ориентированное программирование. Умело распознавать границы применимости, и применять с использованием AspectJ.

18. То же самое для Атрибутно-Ориентированного программирования и AspectWerkz.

19. Знать следующие небольшие, но очень полезные фреймворки: Log4j (логгинг, трейсинг), Quartz (расписания), JCache (распределённое кэширование), Lucene (текстовый поиск) и т.д. Конечно же знать список того, что лежит в Jakarta Commons и для чего оно нужно.

20. Взаимодействие с нативным кодом — JNI, JCA.

21. Процесс формирования стандартов JCP и самые распространённые JSR.

22. Свободно владеть средами IntelliJ IDEA и Eclipse. Знать сочетания клавиш для самых распространённых операций (автодополнение, поиск/замена, рефакторинг: поменять имя, и т.п.).

Ещё нужно освоить vim и emacs (особенно в случае работы в терминале).

23. Java достаточно многословна, поэтому обязательно изучить как генерить код с помощью XDoclet и XSLT.

24. JUnit. Как говорил Брюс Эккель — strong testing, not strong typing. Обязательно.

25. Инструменты для сборки: ant и maven. Не менее обязательно.

26. Освоить технологии производства ПО: RUP, XP, TDD и другие гибкие технологии.

Я из этого списка владею максимум третью и отнюдь не на уровне эксперта.

Интересует мнения опытных товарищей.

4

Объектно-ориентированное программирование в Java
Классы и объекты

Java — полностью объектно-ориентированный язык, поэтому, как мы уже отмечали, все действия, выполняемые программой, находятся в методах тех или иных классов.

Описание класса начинается с ключевого слова class, после которого указывается идентификатор — имя класса. Затем в фигурных скобках перечисляются атрибуты и методы класса. Атрибуты в языке Java называются полями (в дальнейшем мы будем использовать это наименование). Поля и методы называются членами класса.

Поля описываются как обычные переменные.

Правила записи методов рассматривались на предыдущем занятии.

Опишем для примера класс Dog (собака). У него будет два поля: кличка и возраст. При описании поведения собаки в этом простом примере ограничимся лаем. Конечно, лаять по-настоящему наша собака не будет (ведь это всего лишь программная конструкция), она будет выводить в консоль «гав-гав». Чтобы было интереснее, предположим, что все собаки, с которыми имеет дело наша программа, умны настолько, что когда их вынуждают лаять, они говорят «гав-гав» столько раз, сколько им лет.

Заметим, что в программе уже есть один класс (тот, в котором описан метод main()). Поскольку этот класс к собакам отношения не имеет, описывать новый класс Dog следует за его пределами.
class Dog {
int age; // возраст
String name; // кличка
public void voice() {
for (int i = 1; i <= age; i++) {
System.out.println("гав-гав");
}
}
}

Самое главное — понять, что означает, когда некоторые переменные (поля) и функции (методы) собраны (описаны) в каком-то классе.

Класс должен описывать некоторое законченное понятие. Это может быть понятие из предметной области программы (собака, велосипед, аквариум, сессия) или понятие, необходимое для работы самой программы (очередь, список, строка, окно, кнопка, программа*).

Полями класса должны быть данные, относящиеся к этому понятию. Для собаки это возраст, кличка, порода и т.д., а для сессии — дата начала, продолжительность и т.д.

Методы класса, как правило, работают с данными этого класса. Например, метод voice() в нашем примере обращается к полю age (возраст).

Когда какой-то класс описан, могут создаваться объекты этого класса и с ними можно работать, вызывая их методы (кормить собаку, выгуливать, просить ее лаять — словом делать все то, что позволяет поведение класса, т.е. совокупность его методов).

Для обращения к объектам удобно использовать переменные, имеющие тип класса. Например, для работы с собаками опишем переменную типа Dog:
Dog x;

Переменная типа класса является ссылочной переменной, она не хранит данные (как переменные простых типов int, char и т.д.), а указывает на место в памяти, где эти данные хранятся (как переменные типа массива). Данными, на которые указывает только что описанная переменная x, может быть объект класса Dog. Его необходимо предварительно создать командой new:
x = new Dog();

Теперь переменная x указывает на некий объект класса Dog, хранящий в памяти свои данные (возраст и кличку). Кроме того, эту собаку можно заставить лаять, вызвав соответствующий метод командой:
x.voice();

Для того, чтобы обратиться к члену класса, необходимо указать его имя после имени объекта через точку.

Обратите внимание, «залаяла» именно та собака, на которую «указывала» переменная x. Если в программе были созданы другие собаки, они будут молчать до тех пор, пока не будет вызван их метод voice().

Таким образом, когда данные (поля) и команды (методы) описываются в одном классе, они оказываются тесно связаны друг с другом в объектах этого класса. Метод вызывается не сам по себе, а для конкретного объекта и работает с полями именно этого объекта.

Поэтому команды
voice();
age += 1;

не имеют никакого смысла, если употребляются вне методов класса Dog. Обязательно указание на конкретный объект, с которым производится действие. Внутри метода указание на конкретный объект вовсе не обязательно: в рассмотренном примере запись
for (int i = 1; i <= age; i++)
о ключевом слове this

означает, что для определения «продолжительности» лая будет проверяться возраст того самого объекта, для которого будет вызван данный метод. Этот объект обозначается ключевым словом this.
Конструкторы классов

Конструктор — это особенный метод класса, который вызывается автоматически в момент создания объектов этого класса. Имя конструктора совпадает с именем класса.

Например, в классе Dog может быть конструктор с двумя параметрами, который при создании новой собаки позволяет сразу задать ее кличку и возраст.
public Dog(String n, int a) {
name = n;
age = a;
}

Конструктор вызывается после ключевого слова new в момент создания объекта. Теперь, когда у нас есть такой конструктор, мы можем им воспользоваться:
Dog dog1 = new Dog("Тузик", 2);

В результате переменная dog1 будет указывать на «собаку» по кличке Тузик, имеющую возраст 2 года. Кстати, этот возраст можно узнать, заставив собаку лаять командой
dog1.voice();*

Конструкторы добавляются в класс, если в момент создания объекта нужно выполнить какие-то действия (начальную настройку) с его данными (полями). Сразу задать кличку и возраст собаки более естественно, чем каждый раз порождать безымянного щенка, а затем давать ему имя и быстро выращивать до нужного возраста (с учетом того, что программа скорее всего обрабатывает данные о собаках, которые на самом деле уже давно родились). Хотя до появления ООП программисты часто делали именно так.
Наследование

Наследование — это отношение между классами, при котором один класс расширяет функциональность другого. Это значит, что он автоматически перенимает все его поля и методы, а также добавляет некоторые свои.

Наследование обычно возникает, когда все объекты одного класса одновременно являются объектами другого класса (отношение общее/частное). Например, все объекты класса Студент являются объектами класса Человек. В этом случае говорят, что класс Студент наследует от класса Человек. Аналогично класс Собака может наследовать от класса Животное, а класс Далматинец от класса Собака. Класс, который наследует, называется подклассом или потомком, а класс, от которого наследуют, называется суперклассом или предком.

Заметим, что если класс №2 является потомком класса №1, а класс №3 является потомком класса №2, то класс №3 является также потомком класса №1.

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

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

Например:
class Dalmatian extends Dog {
// дополнительные поля и методы
...
}
о классе Object

Если ключевое слово extends не указано, считается, что класс унаследован от универсального класса Object.
Модификаторы видимости

Доступ к любому члену класса — полю или методу — может быть ограничен. Для этого перед его объявлением ставится ключевое слово private. Оно означает, что к этому члену класса нельзя будет обратиться из методов других классов.

Ключевое слово public может употребляться в тех же случаях, но имеет противоположный смысл. Оно означает, что данный член класса является доступным. Если это поле, его можно использовать в выражениях или изменять при помощи присваивания, а если метод, его можно вызывать.

Ключевое слово protected означает, что доступ к полю или методу имеет сам класс и все его потомки.

Если при объявлении члена класса не указан ни один из перечисленных модификаторов, используется модификатор по умолчанию (default). Он означает, что доступ к члену класса имеют все классы, объявленные в том же пакете.

Перепишем класс Dog следующим образом:
class Dog {
private int age;// возраст
private String name; // кличка
public Dog(String n, int a) {
name = n; age = a;
}
public void voice() {
for(int i = 1; i <= age; i++) {
System.out.println("гав-гав");
}
}
}

Поля age и name окажутся скрытыми. Это значит, что мы не можем изменять их (или считывать их значение) где-либо за пределами класса*. Мы не сможем в методе main() создать объект класса Dog, а затем присвоить его полю age или name новое значение, как в следующем примере:
public static void main(String[] args) {
Dog dog1 = new Dog("Тузик", 4);
dog1.age = 10; // нельзя, поле age скрыто
dog1.name = "Жучка"; // переименовать собаку тоже нельзя, поле name скрыто
dog1.voice(); // это можно, метод voice() открытый
}

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

Инкапсуляция означает сокрытие деталей реализации класса. Класс разделяется на две части: внутреннюю и внешнюю. Внешняя часть (интерфейс) тщательно продумывается исходя из того, каким образом могут взаимодействовать с объектами данного класса другие объекты программы. Внутренняя часть закрыта от посторонних, она нужна только самому классу для обеспечения правильной работы открытых методов.
Перегрузка

В одном классе можно создать несколько методов с одним и тем же именем, различающихся по своим параметрам. Этот прием называется перегрузкой методов. Когда один из этих методов будет вызван, произойдет сопоставление переданных ему параметров (их количества и типов) с параметрами всех методов класса с таким именем. Если подходящий метод будет найден, выполнится именно он.

Например, в дополнение к конструктору, который уже есть в классе Dog, мы можем описать конструктор без параметров:
public Dog() {
name = "Незнакомец";
}

В этом конструкторе объекту класса Dog (очевидно, собака с неизвестной кличкой) присваивается при регистрации в программе имя «Незнакомец». Теперь мы можем воспользоваться одним из двух конструкторов:
Dog dog1 = new Dog("Тузик", 2); // Собака по кличке Тузик, возраст 2 года
Dog dog2 = new Dog(); // Собака по кличке «Незнакомец», возраст 0
Dog dog3 = new Dog(10); // Неверно! Не существует конструктора с такими параметрами

Нельзя создавать несколько одноименных методов с одинаковым числом и типом параметров.
Упражнение

Добавьте в класс Dog третий конструктор для случаев, когда известен возраст, но неизвестная кличка собаки так, чтобы третья команда в примере имела смысл.
Полиморфизм

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

Изменить работу любого из методов, унаследованных от класса-предка, класс-потомок может, описав новый метод с точно таким же именем и параметрами. Это называется переопределением. При вызове такого метода для объекта класса-потомка будет выполнена новая реализация.

Пусть, к примеру, мы хотим расширить наш класс Dog классом BigDog, для того, чтобы наша программа особым образом моделировала поведение больших злых собак. В частности, большие собаки лают по-другому. Во-первых, громче, а во-вторых, они не умеют считать. Поэтому мы переопределим метод voice():
class BigDog extends Dog {
public void voice() {
for (int i = 1; i <= 30; i++) {
System.out.print("ГАВ-");
}
}
}

Теперь создадим в методе main() двух разных собак: обычную и большую и заставим их лаять.
Dog dog = new Dog("Тузик", 2);
dog.voice();
BigDog bigdog = new BigDog();
bigdog.voice();

Объект подкласса всегда будет одновременно являться объектом любого из своих суперклассов. Поэтому в том же примере мы могли бы обойтись и одной переменной:
Dog dog = new Dog("Тузик", 2);
dog.voice();
dog = new BigDog();
dog.voice();
о впечатляющих возможностях полиморфизма

Т.е. переменная dog имеет тип Dog, но в третьей строке она начинает указывать на объект класса BigDog, то есть БОЛЬШУЮ собаку, которая при вызове метода voice() будет лаять как БОЛЬШАЯ собака. Это одна из впечатляющих возможностей объектно-ориентированного программирования.
Конструктор по умолчанию

Если в классе не описан ни один конструктор, для него автоматически создается конструктор по умолчанию. Этот конструктор не имеет параметров, все что он делает — это вызывает конструктор без параметров класса-предка.

Поэтому мы и смогли создать объект класса BigDog в примере с большой собакой, хотя не описывали в классе никаких конструкторов. Если вспомнить конструктор без параметров, который у нас есть в классе Dog, мы поймем, что переменная bigdog в предыдущем примере ссылалась на собаку по кличке "Незнакомец".
Вызов конструктора суперкласса

В примере с большой собакой нам удалось создать ее с помощью конструктора без параметров, т.е. не указывая ее имя и возраст. Оказывается, если бы мы попытались сделать это по-другому, у нас бы не получилось. Дело в том, что конструкторы не считаются членами класса и, в отличие от других методов, не наследуются.
BigDog bigdog = new BigDog("Полкан", 8); // Ошибка. Такого конструктора в классе нет

Для того, чтобы мы могли создавать больших собак с интересующими нас именем и возрастом, необходимо написать подходящий конструктор. При этом не обязательно повторять те команды, которые мы писали в конструкторе класса Dog (их всего две, но ведь могло быть гораздо больше). Вместо этого мы можем написать:
BigDog (String n, int a) {
super(n, a);
}

Ключевое слово super означает суперкласс (в нашем случае это класс Dog). В примере мы вызываем с его помощью конструктор суперкласса. При этом мы передаем два параметра — строку и число, — так что из всех конструкторов будет выбран именно тот, который нас интересует.

Вызов конструктора суперкласса должен происходить в самом начале конструктора.

Вместо вызова конструктора суперкласса можно вызвать один из конструкторов того же самого класса. Это делается с помощью ключевого слова this() — с параметрами в скобках, если они нужны.

Если в начале конструктора нет ни вызова this(), ни вызова super(), автоматически происходит обращение к конструктору суперкласса без аргументов.
Приведение типов

Объект класса-потомка можно присвоить переменной типа класса-предка. При этом Java производит автоматическое преобразование типа, называемое расширением. Расширение — это переход от более конкретного типа к менее конкретному. Переход от byte к int — это тоже расширение.

Рассмотрим пример, имеющий отношение к основному заданию. В программе есть класс User, предназначенный для обработки информации о пользователях системы. В этом классе есть метод enter(String login, String password), который возвращает true, если переданные в метод логин и пароль совпадают с логином и паролем, скрытым в полях класса.

Мы наследуем от класса User два подкласса: Admin и, к примеру, Member (для программы координации участников встречи, см. задание 13). Класс Admin может понадобиться нам впоследствии для каких-то специфичных действий, связанных с управлением системой, а класс Member моделирует участников проекта, которые с помощью программы пытаются выбрать оптимальное место для встречи. Открытый метод addRequest(String place, int day, int from, int to) вызывается, когда участник проекта предлагает новый вариант времени и места встречи.

В главном классе программы мы храним массив* users, содержащий всех пользователей системы. Элементы этого массива имеют тип User, но мы можем присваивать им ссылки на объекты как класса Member, так и класса Admin. В этот момент и будет происходить расширение типа.
Member member = new Member(...);
users[3] = member; // Java проводит автоматическое преобразование типа Member к типу User, чтобы поместить переменную member в массив users

Для того, чтобы найти пользователя с введенными логином и паролем программа выполняет запрос:
for (int i = 0; i < users.length; i++) {
if (users[i].enter(log, passw)) currentUser = users[i];
}

Несмотря на то, что все объекты, добавленные в массив, сохраняют свой "настоящий" класс, программа работает с ними как с объектами класса User. Этого вполне достаточно, чтобы можно было найти нужного пользователя по логину и паролю (ведь метод enter() у них общий) и присвоить найденный объект переменной currentUser типа User. В этой переменной хранится текущий пользователь, авторизовавшийся в системе.

Предположим, нам известно, что переменная currentUser сейчас ссылается на объект класса Member и текущий пользователь предлагает встретиться у фонтана в среду с 17 до 19 часов. Необходимо вызвать метод addRequest(), но у нас не получится сделать это командой
currentUser.addRequest("Фонтан", 3, 17, 19);

поскольку в классе User нет метода addRequest().

Однако мы можем осуществить явное преобразование переменной currentUser к типу Member. Такое преобразование (переход от менее конкретного типа к более конкретному) называется сужением. Явное преобразование делается с помощью оператора, представляющего собой имя целевого типа в скобках.
((Member)currentUser).addRequest("Фонтан", 3, 17, 19);

Здесь мы, прежде чем вызвать метод addRequest(), преобразовали переменную currentUser к типу Member. Нам было позволено сделать это, поскольку Member является потомком User. Однако, если бы во время выполнения программы оказалось, что на самом деле переменная currentUser не ссылалась на объект класса Member, в программе возникла бы ошибка.
Оператор instanceof

Чтобы уточнить, соответствует ли текущее значение переменной конкретному типу, используется оператор instanceof.

Проверим, не является ли текущий пользователь администратором (в этом случае программа должна перейти в режим управления):
if (currentUser instanceof Admin) {...}
Анонимные и вложенные классы
о вложенных классах

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

Класс можно объявить внутри метода другого класса. В этом случае класс "виден" только внутри метода (за пределами метода нельзя объявить переменную типа этого класса).

Анонимным классом называется класс, не имеющий имени. Очевидно, если у класса имени нет, к нему нельзя обратиться из программы. Точнее, это можно сделать только один раз — в том месте, где класс объявляется.

Описание анонимного класса начинается с вызова конструктора его суперкласса, после чего в фигурных скобках описывается тело класса.

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

Пусть, например, в нашей программе собачьего питомника имеется массив dogs объектов типа Dog. И мы хотим добавить в этот массив совершенно уникальную собаку, которая не лает, а разговаривает. Необходимо описать класс, унаследованный от класса Dog, в котором будет соответствующим образом переопределен метод voice(). Но поскольку нам гарантированно понадобится только одна такая собака, мы можем описать анонимный класс прямо в месте добавления собаки в питомник (посадим ее в клетку № 10):
dogs[10] = new Dog(){
public void voice() {
System.out.println("Я уникальная говорящая собака.");
}
};

И, несмотря на то, что мы не сможем создавать переменных этого класса, мы спокойно можем пользоваться новой собакой как объектом класса Dog. А благодаря полиморфизму вызов метода
dogs[10].voice();

приведет к тому, что уникальная собака будет уникально подавать голос.
Модификатор static

Любой член класса можно объявить статическим, указав перед его объявлением ключевое слово static. Статический член класса «разделяется» между всеми его объектами.

Для поля это означает, что любое изменение его значения, сделанное одним из объектов класса, сразу же «увидят» все остальные объекты.

Метод, объявленный с модификатором static, "дает обещание" не изменять никаких полей класса, кроме статических.

Для обращения к статическому члену класса можно использовать любой объект этого класса. Более того, это обращение можно осуществлять даже тогда, когда не создано ни одного такого объекта. Вместо имени объекта можно просто указывать имя класса.
Упражнение

Модифицируйте класс Dog таким образом, чтобы можно было считать собак, созданных во время работы программы. Для этого введите статический атрибут count (изначально равный нулю) и увеличивайте его на единицу в каждом конструкторе. Создайте в методе main() несколько объектов класса Dog, а затем выполните для проверки команду:
System.out.println("Всего было создано собак: " + Dog.count);
Модификатор final
о модификаторе final

Любое поле класса можно объявить неизменяемым, указав перед его объявлением ключевое слово final. Неизменяемому полю можно присвоить значение только один раз (обычно это делается сразу при объявлении).

Константы в языке Java очевидным образом описываются путем совмещения модификаторов static и final. Например, мы можем объявить константу PI (лучше это делать в основном классе, а не в классе Dog*), написав:
final static double PI = 3.14;
Диаграммы классов в языке UML

Внимание! На данном этапе обучения вы уже должны владеть знаниями по этой теме. Если их нет, а материалы для повторения непонятны или недостаточны, вы с заданиями не справитесь! Необходимо срочно обратиться к литературе по данной теме.
Литература по теме:

1. Терри Кватрани. Rational Rose 2000 и UML. Визуальное моделирование.
Дополнительная литература

1. Вязовик Н.А. Программирование на Java. (главы 6—8)

2. Хабибуллин И.Ш. Самоучитель Java 2. (глава 2)
Задание

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



создать форум