Материалы занятий

Общую информацию о курсе см. на странице Общая информация

Неделя 2015-02-09


1 Создаем папки, настраиваем пути

1 На диске D: (или E:) создать папку "oop", в ней - папку со своей фамилией (желательно - латиницей и без пробелов).
2 Внутри этой папки создать папку "workspace" (в ней будем создавать проекты).
3 В папке со своей фамилией создать ярлык на exe-шку eclipse'а (поищите ее в c:\program files\eclipse\eclipse.exe).
4 В свойствах ярлыка в поле "target" к уже записанному там пути к exe-шке дописать (через пробел) путь к папке workspace следующим образом: -data d:\oop\ваша_фамилия\workspace
Должно получиться примерно так:

5 Запустить Eclipse с помощью только что созданного ярлыка.

2 Пишем "Hello, world" в Eclipse

1 Создать проект: File->New->Java Project.

2 Убедиться, что в поле "Location" указан путь к той самой папке workspace, которую вы только что создали.

3 Прописать имя проекта: "2015_01_09_hello". Finish.

4 Убедиться, что проект с таким именем появился в project explorer'е в левой части экрана. Если на экране нет никакого project exolorer'а - см. window->show view->project explorer


5 Нажать правой кнопкой на папке src в проекте -> New -> Class, ввести первое пришедшее вам в голову имя класса (классы принято называть с большой буквы, латиницей).
6 Поставить галочку "public static void main(String[] args)" - чтобы машинка сама вам сгенерировала функцию main. Нажать Finish:

7 Внутри функции main (между скобками "{" и "}") пишем собственно вывод на экран:

System.out.println("Hello, world");

8 Не забываем периодически сохряняться: Ctrl+s.
9 Запускаем: Run->Run. В окне Console наблюдаем заветную фразу.

3 Регистрация в системе тестирования Ejudge

1 Заходим на ejudge.litvinov.in.ua, выбираем контест №11 (Практика 2 семестр ООП).

2 Т.к. у нас нет аккаунта - нажимаем "Create account", вводим желаемый логин и свою настоящую почту. На почту придет письмо с паролем.

3 Перейдя по ссылке из письма и успешно залогинившись, нажимаем [Confirm registration].

4 Чтобы вас можно было идентифицирвать, как реального студента ХНУ, жмем на Edit ("General information [Edit]") - и вводим в поле "Team name" свою фамилию и имя (именно в таком порядке) на русском языке. Нажимаем сохранить.


5 Нажимаем "Participate" и видим список "пре-лаб" - заданий на 1 балл, предназначенных для первичного ознакомления с темой соответствующей лабораторной работы.

6 При желании - меняем пароль на какой-нибудь более привычный.

4 Отправка программы на тестирование

1 Прочитайте условие задачи "a_plus_b". Обратите внимание на примеры входных и выходных данных, а также на поля "Time limit" и "Memory limit". В будущем они нам понадобятся.

2 Найдите в интернете, как считать с клавиатуры 2 числа, сложить их и вывести на экран. Запрос в гугле "java a+b" вполне подойдет.

3 Создайте в Eclipse'е проект 2015_02_09_a_plus_b и реализуйте в нем эту программу (тот из вариантов, где используется Scanner, а не InputStreamReader).

4 Не используйте Ctrl+c, Ctrl+v! Попытайтесь понять, зачем нужна каждая из строк этой программы!

5 Протестируйте свою программу (в Eclipse) на данных из примера, который приведен в условии задачи.

6 Когда заработает, помогите соседу (устно, т.е. не трогая его мышь и клавиатуру!).

7 На странице задачи в ejudge выберите "язык" javac - Java JDK 1.6.0_34 и файл с исходным кодом программы (.java). Send!

8 Когда в таблице внизу экрана появится слово "Compiling", не ждите, что оно само исчезнет - жмите F5, чтобы обновить страницу.

9 Далее будет либо OK, либо "Compilation error".

10 В обоих случаях жмите на "view report":


11 Разберитесь, что означают ссылки "I", "O", "A", "E", "C".
12 Сделайте одну корректную отправку, одну с ошибкой компиляции и одну с неправильным результатом.
13 Покажите преподавателю результаты своей работы (программы и протоколы их тестирования), расскажите о смысле ссылок "I", "O", "A", "E", "C", покажите, как вы тестировали свою программу на примере входных/выходных данных из условия задачи и получите 1 балл за работу на занятии.

Д/з

  1. Настроить у себя дома среду разработки. Проверить, что работает "Hello, world". Скачать книги Хорстманна и Шилдта - выбрать из них более понятную. (детали)
  2. Л.р.№1 пока официально не "задана", но тем, кто ее зальет на сервер и принесет готовую на следующее занятие, будет бонус.
  3. Задание на л.р.1 тут: http://ejudge.litvinov.in.ua/cgi-bin/new-register?contest_id=9. Подробные инструкции по ее выполнению - тут: ВАЖНЫЕ пояснения к заданиям на лабы

Неделя 2015-02-16


1 Выводы по предыдущему занятию

  • Если в Eclipse'е исчезло какое-то окно - см. меню Window->Show View -> (Project Explorer | Console | etc).
  • Ваша программа - это, собственно, файл с расширением .java, который создается в папке проекта (его надо отправлять на проверку, и его забирать на флешке домой).
  • Программа, отправляемая на проверку на сервер (ejudge), не должна выводить на экран ничего лишнего: например, приглашений для ввода данных ("Введите a и b:"...).
  • В настройках ejudge обязательно надо указать свою настоящую фамилию и имя - чтобы потом от своего имени сдавать лабы.

2 Простые и ссылочные типы данных

В Java есть восемь простых ("primitive") типов данных: byte, short, int, long, float, double, boolean, char. Подробнее

Все остальные типы - массивы, классы, иногда перечисления - коструируются на их основе. Все они являются ссылочными.

Простые типы
Ссылочные типы
  • переменная хранит непосредственно данные;
  • переменная занимает столько места в памяти, сколько хранящиеся в ней данные;
  • операция присваивания (=) изменяет сами данные в переменной;
  • операция сравнения (==) сравнивает непосредственно данные;
  • при передаче парамера в функцию создается копия данных.
  • переменная хранит ссылку на данные;
  • переменная занимает фиксированный объем памяти (чаще всего, 4 байта);
  • операция присваивания (=) заставляет переменную "ссылаться" на другие данные, старые данные при этом становятся недоступными (т.к. потеряна ссылка);
  • операция сравнения (==) сравнивает ссылки;
  • при передаче параметра в функцию создается копия ссылки (которая ссылается на те же данные).

Пример:

Простые типы Ссылочные типы
// 1 Инициализируем 2 переменные
int a = 2;
int b = 10;

// 1 Инициализируем 2 переменные
int[] a = new int[3];
a[0] = 1; a[1] = 2; a[2] = 3;             // a = [1, 2, 3]

int[] b = new int[3];
b[0] = 11; b[1] = 12; b[2] = 13;       // b = [11, 12, 13]
// 2 "Приравниваем"
b = a;        // a=2, b=10
// 2 "Приравниваем"
b = a;                              // a = [1, 2, 3], b = [1, 2, 3]
// 3 Меняем a:
a++;          // a=3
// 3 Меняем a:                      // a = [100, 2, 3]
a[0] = 100;
4 какое значение b? 4 какое значение b?

Задание:

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

Примечание: Для вывода массива на экран используйте либо цикл, либо просто поэлементый вывод System.out.println(a[0] + " " + a[1] + " " + a[2]).

Примечание 2: Если массив вывести на экран как "обычную" переменную: System.out.println(a) - то увидим на экране значение ссылки! (на самом деле - адрес в памяти)

Примечание 3: Примеры кода, работающего с массивами и циклами, тут и тут.

3 Побитовые операции

В чем разница между операторами '&&' и '&'? Между операторами '||' и '|'?

Логические операторы
Побитовые оператиры
  • оперируют с булевыми значениями:
  • (x > 0) && (x < 5)
  • a || b // где a и b - boolean
  • если применить их к целым числам, то 0 считается false, а любой не-ноль - true:
  • 6 || 35 // -> true
  • оперируют с целыми числами;
  • 6 | 5 // что получится?
  • a & b  // где a и b - целые

Задание: протестируйте программу из туториала от Sun: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

  1. Объясните, почему она выдает именно такой результат.
  2. Объясните (если надо - проведите эксперименты), как работают примеры, приведенные в таблице выше.
  3. Найдите в туториале описание всех побитовых операций в Java. Объясните преподавателю, в чем их суть.
  4. Если есть время - поэкспериментируйте с операторами битовой инверсии и сдвига (с положительными и отрицательными числами, на разных типах данных).

Неделя 2015-02-23

1 Теория

Когда вы разрабатываете приложние на Java, вы создаете его в виде набора текстовых файлов с расширением .java. Каждый такой файл содержит определение ровно одного класса (если быть более точным - одного public-класса).

Далее, компилятор (javac.exe) превращает каждый ваш .java-файл в .class-файл с тем же именем. Этот файл содержит скомпилированный (в байт-код Java-машины) код вашего класса.

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

Помимо текущей папки, классы также ищутся по адресам, указанным в параметре CLASSPATH (задается либо переменной окружения CLASSPATH, либо через параметр "-cp" командной строки). Если класс принадлежит какому-либо пакету (например java.util), то он ищется в папках, структура вложенности которых повторяет структуру вложенности пакетов (в нашем примере это папка java/util).

2 Основы работы в командной строке

См. также тут.

  • Запуск интерпретатора команд осуществляется путем ввода команды "cmd" в окне "Выполнить..." (нажмите windows+R).
  • Путь к текущей директории ("папке") отображается в самой нижней строке.
  • Посмотреть ее содержимое - комана "dir" (от слова directory).
  • Зайти в дочернюю папку - команда "cd имя_папки" (от слов change directory).
  • Перейти в папку на уровень выше - "cd .." (две точки друг за другом).
  • Перейти на другой диск - "буква:".
  • Перейти в "корень" текущего диска - "cd \".
  • Запустить программу - "имя_программы параметр1 параметр2" (exe-шка программы ищется в текущей директории, а также по путям из переменной окружения PATH).
  • Очистить экран - "cls".
  • Создать директорию - "md имя", удалить файл - "del имя".

3 Ручная компиляция и запуск "Hello, world"

  1. javac имя_файла
  2. java имя_класса
  3. Подробнее см. http://docs.oracle.com/javase/tutorial/getStarted/cupojava/win32.html

Задание

Создайте в текстовом редакторе файл с программой "Hello, world", откомпилируйте и запустите его из командной строки.

Примечание: создайте в своей папке на диске D: для этого эксперимента отдельную папку! (например 2015_mm_dd_cmd)

Разберитесь с основными командами cmd, почитайте про переменные окружения PATH и CLASSPATH (и какое они имеют отношение к виртуальной машине Java).

Неделя 2015-03-02

1 Три кита ООП

 Инкапсуляция     Наследование
 Полиморфизм
  • "код и данные вместе";
  • ключевые слова private, protected и public тут ни при чем!
  • список полей = список характеристик объекта (т.е. счетчику цикла с составе полей делать нечего!).
  • "студент тоже человек" (множество студентов - это подмножество людей);
  • наследник = предок + свои поля и методы => занимает больше памяти;
  • наследник может менять унаследованное поведение путем переопределения ("замещения" - overriding) методов.
  • наследник всегда может быть подставлен на место предка (т.к. "студент тоже человек").
  • "кнопки на видеомагнитофоне";
  • возможность взаимодействовать с объектом, не зная его точный тип.

  1. Инкапсуляция - "код и данные вместе".
  2. Наследование - "студент тоже человек".
  3. Полиморфизм - возможность взаимодействовать с объектом, не зная его точного типа ("кнопки на видеомагнитофоне").

2 Из чего состоит класс

public class Stakan{
    private float масса;                       // 1 поля
    private float объем;

    public Stakan(){                           // 2а конструктор по умолчанию
        инициализировать поля "дефолтными" значениями;
    }

    public Stakan(float m, float v){           //2b конструктор с параметрами
        явно инициализировать поля;
    }

    public float getMass(){...}                // 3 setter'ы и getter'ы
    public boolean setMass(float m){...}

    public void print(){                       // 4 операции с объектом. Самая популярная - print()
        распечатать информацию на экране в определенном формате
    }
}
...в main():
Stakan a = new Stakan();
Stakan b = new Stakan(20, 200);
Stakan[] m = new Stakan[n];
for(int i=0; i<m.length; i++){
    m[i] = new Stakan();
}
a.print();
b.setMass(b.getMass() - 10);
и т.п...

3 Как тестируются классы в Ejudge (используйте javac_recompile!)

  • От вас требуется не программа - а класс. Т.е. функцию main() можно не писать (когда она бывает нужна - это явно оговорено в задании).
  • Разные функции main() автоматически "пристыковываются" к вашему классу и тестируют его.
  • Строго соблюдайте формат вывода: один лишний пробел, одна маленькая буква вместо большой - и тест не пройден.
  • Всегда объявляйте главный класс как "public class". Если классов несколько - поместите их все в один файл, но только один класс объявите как public.
Задание
Класс Stakan (задание 2_pre).

Неделя 2015-03-10

1 "Резиновый массив"

"Резиновый массив", или - в простонаречии - вектор - структура данных, в которой n однотипных элементов хранятся непосредственно друг за другом (без пропусков) в памяти, и котоая автоматически расширяется при добавлении новых элементов.

Поддерживает 3 основные операции:

  • прочитать элемент в заданной позиции;
  • поменять (существующий!) элемент в заданной позиции;
  • добавить новый элемент в заданную позицию (со сдвигом остальных элементов вправо);
  • удалить элемент в заданной позиции (со сдвигом остальных элементов влево).

Типичная реализация (только операция добавления в конец):

static double[] arr = new double[10];

static int size = 0;            // изначально - пусто

static void add(double val){

    if(еще есть место){

        arr[size] = val;

        size++;

    }else{

        создать новый массив в 2 раза больше

        скопировать в него элементы

        присвоить ссылку на него "старому" массиву arr

        теперь место есть, и можно добавлять элемент так же, как показано выше в части if(){...}

    }

}

2 Assert

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

Важно! Чтобы assert'ы не игнорировались java-машиной, включите их с помощью опции "-ea": java -ea MyClass. В Eclipse - Run->Run/Debug Config->Arguments->VM Arguments (прописать "-ea")

См. также http://prog-school.ru/2010/03/zashhitnoe-programmirovanie-kak-pravilno и http://habrahabr.ru/post/191548/.

Замечание: иногда в настройках Eclipse у вас может быть указана неправильная версия JDK (тогда редактр подчеркивает строки с assert). Как правило, это вызвано тем, что у вас не совсем корректно установлен JDK. Обычно это можно исправить в настройках проекта (указав правильный Compiler compliance level в меню project->propertiies->java compiler):
http://www.cis.upenn.edu/~matuszek/cit594-2004/Pages/eclipse-faq.html#assert


Задание

3_pre на ejudge. Чтобы упростить себе задачу - сделайте все поля и методы статическими (как main).


Неделя 2015-03-16

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

public class Point{

    private double x=0, y=0;            // можно инициализировать поля в конструкторе, можно - здесь

    public Point(double x, double y){...}

    public void print(){}

}

public class Point3d extends Point{

    private double z=0;                // x и y у нас уже есть!

    public Point3d(double x, double y, double z){

        super(x, y);                    // вызов конструктора из суперкласса!

        инициализировать z

    }

    public void print(){...}            // переопределение!

}

..в main():

    Point p1 = new Point(11, 22);
        p1.print();                        // -> (11.0, 22.0)
    Point3d p2 = new Point3d(33, 44, 55);
        p2.print();                        // -> (33.0, 44.0, 55.0)

    // подстановка!
    Point p3 = new Point3d(66, 66, 66);
        p3.print();                        // что будет на экране?

2 Л.р.4


Задание: 4_pre

Неделя 2015-03-23

1 Наследование реализации и композиция

Цели наследования:

  1. Наследование реализации (закрытое) - в Java не бывает! - чтобы 2-ой раз не писать тот же код.
  2. Наследование интерфейса (открытое) - чтобы работал принцип подстановки (наследник на место родителя).
Наследование Композиция + делегирование
public void push(double val){
    super.insert(val, super.getSize());
}
public void push(double val){
    v.insert(val, v.getSize());
}

2 Является ли квадрат прямоугольником

Допустим, квадрат поддерживает все операции из класса прямоугольник.

=> значит можно сделать setWidth(1) и setHeight(2)

=> значит это не квадрат

--

квадрат - это НЕ прямоугольник!

Задание (5_pre):


...
public void setSide(double s){
    r.width=s;
    r.height=s;
}
public double getArea(){
    return r.getArea();            // делегирование!
}
...

Неделя 2015-03-30

Полиморфизм

Полиморфизм - это возможность взаимодействия с объектом без знания его конкретного типа.

Но для этого нам нужна гарантия, что объект поддерживает все нужные нам операции:

public interface Container{

    void put(double val);

    double get();

}

class Stack implements Container{...}

class Queue implements Container{...}

После чего мы можем полиморфно вызывать методы этих классов:

1)

Container c = new Stack();

c.put(); c.put();        // 1,2

c.get(); c.get();        // 2,1

2)

void saveData(Container c){...c.put(...);...}        // 1 Тут мы НЕ ЗНАЕМ, вызываем ли мы метод из Stack или из Queue! (см. 2)

...в main():

Container c;

if(...)                                              // 2 Тут уже знаем. Но это становится известно на этапе ВЫПОЛНЕНИЯ, а НЕ компиляции.

    c = new Stack();

else

    c = new Queue();

saveData(c);

Полиморфный вызов - это вызов метода, при котором информация о том, какой именно метод (из нескольких) будет вызван, недоступна на этапе компиляции.

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

Еще примеры:

http://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html

http://ermak.cs.nstu.ru/cprog/HTML/114.htm (примечание: в Java все функции - всегда виртуальные, но не все вызовы полиморфные)

Задание: 6_pre

Неделя 2015-04-20

1 Классы Java Collections Framework построены с использованием "дженериков" ("шаблонов"):

List<String> list = new ArrayList<String>();

2 Осторожно! В классе LinkedList есть много методов для доступа к элементу по индексу (get(), set(), add()), метод contains и другие ужасно неэффективные операции - применяя их, нужно четко понимать, что существуют коллекции с гораздо более эффективной их реализацией (ArrayList и Set в данном случае).

3 Как интерфейс List - обобщение понятие списка (ArrayList'а и LinkedList'а), так итератор - обобщение понятия позиции:



Iterator<String> i = list.iterator();

while(i.hasNext())

    // do something with i.next();            // метод next() возвращает правый элемент и преходит к следующему

Задание: Создать объект LinkedList. Заполнить его несколькими элементами. С помощью итератора найти элемент с заданным (можно в коде) значением и удалить его. С помощью итератора распечатать измененный список. Примеры кода.

Неделя 2015-05-05

Вложенные (nested) и внутренние (inner) классы


..main():
Vector.Iterator = new Vector.Iterator();
(или - обычно - new Vector.Iterator(v))
 ..main():
Vector v = new Vector();                    // нужен объект!
Vector.Iterator i = v.new Iterator();      // new "в контексте" объекта v

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

Это класс внутри функции - он виден только внутри этой функции, а объекты его также содержат неявную ссылку на объект "внешнего" класса.

Безымянный:

ActionListener obj = new ActionListener(){

    public void actionPerformed(ActionEvent e) {
         System.out.println("Меня нажали");

    }

}

someButton.addActionListener(obj);

Методы локальныого внутреннего класса имеют доступ к локальным переменным вмещающей этот класс функции (но только final - см. в Хорстманне почему!).

Задание: 9_pre. Подробнее: см. Хорстманн и Java Tutorials.

Comments