53 KiB
Конспект лекции 2: Массивы и ссылки
Преподаватель: Георгий Корнеев
Курс: Введение в программирование (Java)
Содержание
- Одномерные массивы
- Многомерные массивы
- Ссылки на массивы
- Полные имена классов
- Класс Scanner
- Домашнее задание
1. Одномерные массивы
1.1. Типы данных в Java (повторение)
Классификация типов:
Типы данных
├── Примитивные (primitive)
│ ├── int, long
│ ├── char
│ ├── boolean
│ └── double, float
└── Ссылочные (reference)
├── String
├── Массивы
└── Объекты классов
⚠️ Важно: Массивы — это ссылочные типы!
1.2. Объявление массивов
Синтаксис объявления
int[] ints; // Массив целых чисел
double[] doubles; // Массив вещественных чисел
boolean[] booleans; // Массив булевых значений
String[] strings; // Массив строк
char[] chars; // Массив символов
long[] longs; // Массив длинных целых
Важные особенности:
- Квадратные скобки
[]указывают на тип "массив" - Можно создавать массивы любых типов (примитивных и ссылочных)
1.3. Создание массивов
Способ 1: Указание размера
ints = new int[10]; // Массив из 10 элементов
doubles = new double[20]; // Массив из 20 элементов
booleans = new boolean[30];
strings = new String[40];
chars = new char[5];
longs = new long[3];
Способ 2: Инициализация значениями
ints = new int[]{1, 2, 3};
doubles = new double[]{1.5};
booleans = new boolean[]{true, false};
strings = new String[]{"a", "b", "c"};
Способ 3: Сокращённая инициализация (при объявлении)
int[] ints = {1, 2, 3};
String[] strings = {"hello", "world", "array"};
⚠️ Нельзя комбинировать: new int[5]{1, 2, 3, 4, 5} — НЕ компилируется!
1.4. Длина массива
int[] array = new int[10];
System.out.println(array.length); // 10 (поле, НЕ метод!)
Важно:
length— это поле (property), не метод- Пишется без скобок:
array.length, а неarray.length()
1.5. Значения по умолчанию
При создании массива с указанием только размера элементы инициализируются значениями по умолчанию:
| Тип | Значение по умолчанию |
|---|---|
int, long |
0 |
double, float |
0.0 |
boolean |
false |
char |
'\0' (символ с кодом 0) |
Ссылочные типы (String, массивы) |
null |
int[] ints = new int[10];
System.out.println(ints[0]); // 0
boolean[] booleans = new boolean[10];
System.out.println(booleans[0]); // false
String[] strings = new String[10];
System.out.println(strings[0]); // null
1.6. Доступ к элементам массива
int[] array = {1, 2, 3, 4, 5};
// Чтение
int first = array[0]; // 1 (нумерация с 0!)
int last = array[4]; // 5
// Запись
array[0] = 10;
array[2] = 30;
// Результат: {10, 2, 30, 4, 5}
Важно: Индексация начинается с 0!
1.7. Ошибки при работе с массивами
Отрицательная длина
int[] array = new int[-5];
// Исключение: NegativeArraySizeException
Выход за границы
int[] array = new int[3];
System.out.println(array[5]);
// Исключение: ArrayIndexOutOfBoundsException
Обращение к null
int[] array = null;
System.out.println(array.length);
// Исключение: NullPointerException
1.8. Итерация по массивам
Цикл for (с индексом)
int[] ints = {1, 2, 3, 4, 5};
// i — это индекс
for (int i = 0; i < ints.length; i++) {
System.out.println(ints[i]);
}
Когда использовать:
- Нужен индекс элемента
- Нужен доступ на запись
- Нужна итерация с шагом (не по порядку)
Цикл for-each (без индекса)
int[] ints = {1, 2, 3, 4, 5};
// i — это значение элемента
for (int i : ints) {
System.out.println(i);
}
Когда использовать:
- Нужно только читать значения
- Итерация всегда последовательная
- Индекс не нужен
Преимущества for-each:
- Более читаемый код
- Меньше ошибок (нет индексов)
- Работает с любыми коллекциями
1.9. Максимальная длина массива
// Максимальное значение int
int maxSize = Integer.MAX_VALUE; // 2,147,483,647
// НО! Массив такой длины создать НЕЛЬЗЯ
int[] huge = new int[Integer.MAX_VALUE];
// Исключение: OutOfMemoryError
Ограничения:
- Длина массива имеет тип
int - Физически ограничено доступной памятью
- JVM имеет лимиты на размер heap (куча)
Пример работы с памятью:
// Настройка heap для JVM
// java -Xmx16G MyProgram — выделить 16 GB
// java -Xmx1G MyProgram — выделить 1 GB
// Создание большого массива
int[] array = new int[100_000_000]; // 100 млн элементов
// Занимает: 100,000,000 × 4 bytes = ~400 MB
1.10. Динамический размер массива
Размер может определяться во время выполнения:
public static void main(String[] args) {
// Первый аргумент командной строки
int size = Integer.parseInt(args[0]);
// Создаём массив динамического размера
int[] array = new int[size];
System.out.println("Создан массив длины: " + array.length);
}
# Запуск программы
java MyProgram 123
# Вывод: Создан массив длины: 123
2. Многомерные массивы
2.1. Концепция многомерных массивов
Важная идея: В Java многомерные массивы — это массивы массивов!
Двумерный массив:
int[][] matrix - это массив, каждый элемент которого — массив int[]
Трёхмерный массив:
int[][][] cube - это массив, каждый элемент которого — массив int[][]
2.2. Объявление многомерных массивов
int[][] ints2d; // Двумерный массив
int[][][] ints3d; // Трёхмерный массив
String[][] strings2d; // Двумерный массив строк
2.3. Создание многомерных массивов
Полное создание (прямоугольный массив)
// Матрица 10×20 (10 строк, 20 столбцов)
int[][] matrix = new int[10][20];
// Куб 10×20×30
int[][][] cube = new int[10][20][30];
System.out.println(matrix[0]); // [I@... (ссылка на массив int[])
System.out.println(cube[0]); // [[I@... (ссылка на int[][])
Частичное создание
// Создаём только первое измерение
int[][] matrix = new int[10][];
int[][][] cube = new int[10][][];
System.out.println(matrix[0]); // null (элементы не созданы!)
System.out.println(cube[0]); // null
Использование:
int[][] matrix = new int[10][];
// Заполняем вручную
for (int i = 0; i < matrix.length; i++) {
matrix[i] = new int[i]; // Каждая строка своей длины!
}
2.4. Непрямоугольные массивы
Java позволяет создавать "рваные" массивы (jagged arrays) — массивы, где строки имеют разную длину:
// Создание непрямоугольного массива
int[][] jagged = new int[3][];
jagged[0] = new int[5]; // Первая строка — 5 элементов
jagged[1] = new int[2]; // Вторая строка — 2 элемента
jagged[2] = new int[7]; // Третья строка — 7 элементов
// Проверка длин
for (int[] row : jagged) {
System.out.println(row.length); // 5, 2, 7
}
Инициализация непрямоугольного массива
int[][] jagged = new int[][]{
{1, 2, 3}, // Строка из 3 элементов
{4, 5}, // Строка из 2 элементов
{6, 7, 8, 9}, // Строка из 4 элементов
null // Пустая строка (null)
};
System.out.println(jagged.length); // 4 (количество строк)
System.out.println(jagged[0].length); // 3
System.out.println(jagged[1].length); // 2
System.out.println(jagged[2].length); // 4
System.out.println(jagged[3]); // null
⚠️ Внимание: jagged[3].length вызовет NullPointerException!
2.5. Работа с двумерными массивами
Итерация по всем элементам
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Вложенные циклы for
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
// Вложенные циклы for-each
for (int[] row : matrix) {
for (int element : row) {
System.out.print(element + " ");
}
System.out.println();
}
2.6. Значения по умолчанию в многомерных массивах
int[][] matrix = new int[3][4];
// Все элементы инициализированы нулями
System.out.println(matrix[0][0]); // 0
String[][] strings = new String[3][4];
// Все элементы равны null
System.out.println(strings[0][0]); // null
3. Ссылки на массивы
3.1. Массивы как ссылочный тип
Ключевая концепция: Переменная массива хранит не сам массив, а ссылку на него в памяти.
int[] a = new int[10]; // a содержит ссылку на массив
Память:
┌─────────┐ ┌───────────────┐
│ a │───────>│ [0,0,0,...,0] │
└─────────┘ └───────────────┘
переменная массив в heap
3.2. Копирование ссылок
int[] a = new int[10];
int[] b = a; // b указывает на ТОТ ЖЕ массив!
a[1] = 10;
System.out.println(a[1] + " " + b[1]); // 10 10
System.out.println(a == b); // true (одна и та же ссылка)
Память:
┌─────────┐ ┌───────────────┐
│ a │───────>│ [0,10,0,...,0]│
└─────────┘ ┌──>└───────────────┘
┌─────────┐ │
│ b │────┘
└─────────┘
3.3. Переприсваивание ссылок
int[] a = new int[10];
int[] b = a;
a = new int[10]; // a теперь указывает на НОВЫЙ массив!
a[1] = 20;
System.out.println(a[1] + " " + b[1]); // 20 10
System.out.println(a == b); // false (разные массивы)
До: a и b указывают на один массив
┌─────┐ ┌───────────────┐
│ a │───>│ [0,0,0,...,0] │
└─────┘ ┌─>└───────────────┘
┌─────┐ │
│ b │─┘
└─────┘
После: a указывает на новый массив
┌─────┐ ┌───────────────┐
│ a │───>│ [0,20,0,...,0]│
└─────┘ └───────────────┘
┌─────┐ ┌───────────────┐
│ b │───>│ [0,0,0,...,0] │
└─────┘ └───────────────┘
3.4. Передача массивов в функции
Изменение элементов массива
void fill(int[] ints, int value) {
for (int i = 0; i < ints.length; i++) {
ints[i] = value;
}
}
// Использование
int[] array = new int[3];
fill(array, 100);
System.out.println(Arrays.toString(array)); // [100, 100, 100]
✅ Изменения видны снаружи — мы меняем элементы по ссылке!
Переприсваивание параметра (НЕ работает!)
void referenceAsValue(int[] ints) {
ints = new int[0]; // Локальное изменение параметра
}
// Использование
int[] a = new int[10];
int[] b = a;
referenceAsValue(a);
System.out.println(a == b); // true (массив НЕ изменился!)
❌ Переприсваивание НЕ видно снаружи — параметры передаются по значению!
Почему так происходит:
При вызове функции:
1. Копируется ССЫЛКА (не сам массив)
2. Локальный параметр указывает на тот же массив
3. Переприсваивание меняет только локальную переменную
4. Исходная переменная остаётся без изменений
3.5. Возврат массива из функции
int[] create(int length, int value) {
int[] ints = new int[length];
for (int i = 0; i < ints.length; i++) {
ints[i] = value;
}
return ints; // Возвращаем ссылку на созданный массив
}
// Использование
int[] array = create(3, 123);
System.out.println(Arrays.toString(array)); // [123, 123, 123]
✅ Массив создаётся в heap и продолжает существовать после выхода из функции!
3.6. Сборка мусора (Garbage Collection)
Java автоматически освобождает память от неиспользуемых объектов:
int[] a = new int[1_000_000];
// Создаём 10 миллионов массивов
for (int i = 0; i < 10_000_000; i++) {
a = new int[1_000_000]; // Старый массив становится мусором
}
System.out.println("ok");
// Программа работает! Сборщик мусора освобождает память
Как это работает:
- Когда на объект не осталось ссылок, он становится "мусором"
- Сборщик мусора периодически удаляет такие объекты
- Память освобождается автоматически
3.7. Копирование массивов
Проблема с присваиванием
int[] a = {1, 2, 3};
int[] b = a; // Это НЕ копирование, это копирование ссылки!
a[0] = 100;
System.out.println(b[0]); // 100 (изменили оба массива!)
Правильное копирование: System.arraycopy()
int[] source = {0, 10, 20, 30, 40, 50};
int[] dest = new int[5];
// System.arraycopy(откуда, откуда_индекс, куда, куда_индекс, сколько)
System.arraycopy(source, 2, dest, 1, 3);
System.out.println(Arrays.toString(dest)); // [-1, 20, 30, 40, -1]
Параметры:
source— исходный массив2— начальный индекс в источникеdest— массив назначения1— начальный индекс в назначении3— количество копируемых элементов
Схема:
source: [0, 10, 20, 30, 40, 50]
^ ^ ^
| | |
└───┼───┘
↓
dest: [-1, 20, 30, 40, -1]
^ ^ ^ ^ ^
3.8. Особенности System.arraycopy()
Корректная работа с перекрывающимися областями
int[] array = {1, 2, 3, 4, 5};
// Копирование внутри одного массива (вправо)
System.arraycopy(array, 0, array, 2, 3);
// Результат: [1, 2, 1, 2, 3]
// Копирование внутри одного массива (влево)
int[] array2 = {1, 2, 3, 4, 5};
System.arraycopy(array2, 2, array2, 0, 3);
// Результат: [3, 4, 5, 4, 5]
✅ System.arraycopy() корректно обрабатывает перекрытия (использует временный буфер при необходимости)
4. Полные имена классов
4.1. Пакеты в Java
Java использует иерархическую систему пакетов для организации классов:
java (корневой пакет)
├── lang (фундаментальные классы)
│ ├── String
│ ├── System
│ ├── Integer
│ ├── Object
│ └── Math
├── util (вспомогательные утилиты)
│ ├── Arrays
│ ├── Scanner
│ ├── ArrayList
│ └── zip (подпакет для сжатия)
│ ├── ZipFile
│ └── GZIPInputStream
└── io (ввод-вывод)
├── File
├── InputStream
└── OutputStream
javax (дополнительные пакеты)
└── crypto (криптография)
4.2. Полные имена классов
Полное имя = путь через пакеты + имя класса
// Полное имя класса System
java.lang.System
// Полное имя класса Arrays
java.util.Arrays
// Полное имя класса Scanner
java.util.Scanner
Использование полных имён
// Можно использовать полное имя везде
java.util.Arrays.toString(array);
java.lang.System.out.println("Hello");
java.lang.Integer.parseInt("123");
4.3. Оператор import
Чтобы не писать полные имена постоянно, используется import:
import java.util.Arrays;
import java.util.Scanner;
import java.lang.Integer;
// Теперь можно использовать короткие имена
Arrays.toString(array);
Scanner scanner = new Scanner(System.in);
Integer.parseInt("123");
Импорт всех классов из пакета
import java.util.*; // Импортирует все классы из java.util
Arrays.toString(array); // Работает
Scanner scanner = ...; // Работает
4.4. Неявный импорт java.lang
Важно: Пакет java.lang импортируется автоматически!
// Эта строка присутствует неявно в каждой программе:
import java.lang.*;
// Поэтому эти классы доступны без import:
String s = "hello";
System.out.println(s);
Integer.parseInt("123");
Math.sqrt(25);
4.5. Класс Arrays
Класс java.util.Arrays содержит полезные методы для работы с массивами:
import java.util.Arrays;
int[] array = {3, 1, 4, 1, 5};
// Преобразование в строку
String str = Arrays.toString(array);
System.out.println(str); // [3, 1, 4, 1, 5]
// Заполнение массива
Arrays.fill(array, 7);
System.out.println(Arrays.toString(array)); // [7, 7, 7, 7, 7]
// Сортировка
int[] data = {5, 2, 8, 1, 9};
Arrays.sort(data);
System.out.println(Arrays.toString(data)); // [1, 2, 5, 8, 9]
// Копирование
int[] copy = Arrays.copyOf(data, data.length);
4.6. Вывод массивов
int[] array = {0, 10, 20, 30};
// Прямой вывод (плохо!)
System.out.println(array); // [I@3834d63f (адрес в памяти)
// Правильный вывод
System.out.println(Arrays.toString(array)); // [0, 10, 20, 30]
Почему так происходит:
- Массивы — ссылочный тип
- При прямом выводе печатается представление ссылки
[I@...означает "массив int" + хеш-код
5. Класс Scanner
5.1. Назначение класса Scanner
Scanner — класс для удобного чтения данных из различных источников:
- Стандартный ввод (консоль)
- Файлы
- Строки
- Потоки данных
import java.util.Scanner;
5.2. Создание Scanner для стандартного ввода
Scanner scanner = new Scanner(System.in);
Параметры:
System.in— стандартный поток ввода (stdin)- Можно также использовать
File,String,InputStreamи др.
5.3. Основные методы Scanner
Чтение различных типов данных
Scanner scanner = new Scanner(System.in);
// Чтение целого числа
int number = scanner.nextInt();
// Чтение вещественного числа
double value = scanner.nextDouble();
// Чтение строки (до пробела)
String word = scanner.next();
// Чтение целой строки (до конца строки)
String line = scanner.nextLine();
// Чтение символа (нет прямого метода, используем next())
char ch = scanner.next().charAt(0);
5.4. Проверка наличия данных
Scanner scanner = new Scanner(System.in);
// Проверка наличия следующего токена
while (scanner.hasNext()) {
String word = scanner.next();
System.out.println(word);
}
// Проверка наличия целого числа
while (scanner.hasNextInt()) {
int number = scanner.nextInt();
System.out.println(number + 1);
}
// Проверка наличия строки
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
5.5. Пример: сумма чисел
import java.util.Scanner;
public class SumExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Введите два числа: ");
int a = scanner.nextInt();
int b = scanner.nextInt();
System.out.println("Сумма: " + (a + b));
}
}
Запуск:
Введите два числа: 10 20
Сумма: 30
5.6. Пример: чтение всех чисел и увеличение на 1
Scanner scanner = new Scanner(System.in);
// Читаем и увеличиваем пока есть числа
while (scanner.hasNextInt()) {
int number = scanner.nextInt();
System.out.println(number + 1);
}
Ввод:
1 2 3
4 5
Вывод:
2
3
4
5
6
5.7. Работа с пробелами и переводами строк
Scanner автоматически пропускает пробельные символы (пробелы, табуляции, переводы строк):
Scanner scanner = new Scanner(System.in);
// Ввод: " hello world "
String s1 = scanner.next(); // "hello"
String s2 = scanner.next(); // "world"
Для чтения целых строк:
String line = scanner.nextLine(); // Читает ВСЁ до конца строки
5.8. Важные замечания
- Scanner читает из потока последовательно — прочитанные данные нельзя "вернуть обратно"
- Разделители по умолчанию — пробелы, табуляции, переводы строк
- Можно настроить разделители через метод
useDelimiter() - Нет прямого способа прочитать char — используйте
scanner.next().charAt(0)
6. Домашнее задание
6.1. Задание: Класс Reverse
Описание: Разработать класс Reverse, который читает числа из стандартного ввода и выводит их в обратном порядке.
Требования:
- Числа могут быть на нескольких строках
- В каждой строке может быть несколько чисел
- Нужно развернуть порядок строк
- Нужно развернуть порядок чисел в каждой строке
- Числа разделены пробелами
- Все числа помещаются в тип
int - Использовать класс
Scanner
6.2. Примеры
Пример 1
Ввод:
1 2
3
Вывод:
3
2 1
Пример 2
Ввод:
3
1 2
Вывод:
2 1
3
Пример 3: Отрицательные числа
Ввод:
-1 -2 -3
4 5
Вывод:
5 4
-3 -2 -1
Пример 4: Пустые строки
Ввод:
1 2
3 4
Вывод:
4 3
2 1
Важно: Пустые строки сохраняются!
Пример 5: Множественные пробелы
Ввод:
1 2 3
4 5
Вывод:
5 4
3 2 1
Важно: В выводе между числами ровно один пробел!
Пример 6: Полный пример
Ввод:
1 2
3 4
5 6
Вывод:
6 5
4 3
2 1
6.3. Требования к реализации
Эффективность
- ✅ Программа должна работать эффективно по памяти
- ✅ Программа должна работать эффективно по времени
- ⚠️ Подумайте, как хранить данные оптимально
Что использовать
- ✅ Класс
Scannerдля чтения - ✅ Массивы для хранения данных
- ✅ Любые конструкции из стандартной библиотеки Java
Формат вывода
- Числа в строке разделены одним пробелом
- Каждая строка заканчивается переводом строки
- Пустые строки выводятся как есть
6.4. Алгоритм решения (подсказки)
Этапы:
-
Чтение данных
- Читать строку за строкой
- Для каждой строки читать все числа
- Сохранять в структуру данных (двумерный массив?)
-
Разворот
- Развернуть порядок строк
- В каждой строке развернуть порядок чисел
-
Вывод
- Вывести каждую строку
- Числа через один пробел
Вопросы для размышления:
- Как хранить строки разной длины? (Непрямоугольный массив!)
- Как отличить пустую строку от конца ввода?
- Как эффективно развернуть массивы?
Резюме лекции
Ключевые концепции
-
Массивы — ссылочный тип
- Хранят ссылку, а не данные напрямую
- Передача в функции = передача ссылки
- Присваивание = копирование ссылки
-
Многомерные массивы = массивы массивов
- Могут быть непрямоугольными
- Каждое измерение — отдельный массив
-
Значения по умолчанию
- Примитивы:
0,false,'\0' - Ссылочные типы:
null
- Примитивы:
-
Пакеты и импорты
java.lang.*импортируется автоматически- Остальные пакеты требуют
import - Полное имя =
пакет.класс
-
Полезные классы
Arrays— работа с массивамиScanner— чтение данныхSystem— системные операции
Важные методы и техники
// Работа с массивами
Arrays.toString(array) // Красивый вывод
Arrays.fill(array, value) // Заполнение
System.arraycopy(...) // Копирование
// Чтение данных
Scanner scanner = new Scanner(System.in);
scanner.nextInt() // Прочитать число
scanner.next() // Прочитать слово
scanner.nextLine() // Прочитать строку
scanner.hasNext() // Проверить наличие данных
Типичные ошибки и их решения
| Ошибка | Причина | Решение |
|---|---|---|
NullPointerException |
Обращение к null | Проверять на null |
ArrayIndexOutOfBoundsException |
Выход за границы | Проверять индексы |
NegativeArraySizeException |
Отрицательный размер | Валидировать размер |
Что дальше
- Практика работы с массивами
- Выполнение домашнего задания Reverse
- Следующая тема: классы и объекты
Полезные ссылки:
Удачи в выполнении домашнего задания! 🚀
Конспект лекции 1: Введение в программирование (Java)
Преподаватель: Георгий Корнеев
1. Организационные вопросы
1.1. Контактная информация
- Преподаватель: Георгий Корнеев
- Связь:
- Основные вопросы → чат курса
- Сложные/долгие вопросы → email преподавателя
1.2. Структура курса
Последовательность предметов:
- 1 курс: Введение в программирование (Java)
- 2 курс 1 семестр: Парадигмы программирования
- 2 курс 2 семестр: Технологии Java
2. Организация учебного процесса
2.1. Структура занятий
Лекции
- Теоретический материал
- Live coding
- Демонстрации примеров
Домашние задания
- Выдаются после каждой лекции
- Срок выполнения: около недели (чуть меньше, т.к. практики перед лекциями)
- Все последующие ДЗ (кроме первого) требуют самостоятельно написанного кода на Java
Практические занятия
- Сдача модификации домашнего задания (не самого ДЗ!)
- Модификация тесно связана с домашним заданием
- Пример: ДЗ - скомпилировать Hello World, практика - скомпилировать другую программу
3. Система оценивания
3.1. Версии домашних заданий
- Простая версия → НЕ нужно делать
- Сложная версия → ОБЯЗАТЕЛЬНО делать
3.2. Попытки сдачи
- Количество попыток: 3 (три вторника подряд)
- Если за 3 попытки не сдано → ДЗ не засчитывается
3.3. Система задержек (delay)
Фиксируется момент ПЕРВОЙ демонстрации рабочей программы преподавателю:
- Сдача в первую неделю → delay = 0
- Сдача во вторую неделю → delay = 1
- Сдача в третью неделю → delay = 2
⚠️ Важно: Задержка определяется моментом первой демонстрации работающей программы, а не финальной сдачи!
3.4. Система минусов
Начисление минусов:
- Преподаватель проверяет код
- За найденные проблемы назначаются минусы
- Минусы накапливаются при каждой попытке
Пример расчёта:
- 1 попытка: 3 минуса
- 2 попытка: 2 минуса
- 3 попытка: 0 минусов (успешно)
- Итого: 5 минусов, delay = 0 (т.к. начали с первой недели)
3.5. Бонусные баллы
Бонусы за скорость сдачи
- Условие: Первый студент, сдавший ДЗ преподавателю в первую неделю
- Количество: До 5 человек (по числу преподавателей)
Бонусы за найденные ошибки
- За обнаруженные ошибки и опечатки в материалах курса
- Сообщать в специальный раздел чата
4. Зачёт
4.1. Условия
- Проводится при неудовлетворительных баллах
- Если баллов достаточно → зачёт не обязателен
4.2. Варианты сдачи
- Досрочная сдача: конец декабря
- Стандартная сдача: во время сессии
5. Особенности первого домашнего задания
5.1. Уникальные условия
- Несложное (т.к. не было лекций)
- Срок сдачи: только первая практика
- Больше не принимается
6. Почему Java?
6.1. Популярность
- Индекс TIOBE: Java в топе популярных языков
- В плотной группе с C, C++, Python
- Python вырвался вперёд в последние 2-3 года
6.2. Преимущества Java
Простота и безопасность
- Достаточно простой язык
- Сложно создать код, который:
- Убьёт компьютер
- Приведёт к непредсказуемому поведению
- Не воспроизводится на других машинах
Содержательность
- Простой, но весьма содержательный язык
- Широкий спектр возможностей
Области применения
- Серверные приложения
- Desktop-приложения
- Android-разработка
- JVM-языки (Kotlin, Scala и др.)
7. Основы Java
7.1. Концепция Java
Виртуальная машина (JVM)
- Java компилируется не в машинный код, а в байт-код
- Байт-код исполняется на виртуальной машине Java (JVM)
- Преимущество: кроссплатформенность (Write Once, Run Anywhere)
Процесс выполнения программы
- Написание кода на Java (.java файлы)
- Компиляция в байт-код (.class файлы)
- Выполнение на JVM
7.2. Установка и настройка
Java Development Kit (JDK)
- Что включает:
- Компилятор Java
- JVM
- Стандартная библиотека
- Инструменты разработки
Проверка установки
java -version # Проверка установленной версии JVM
javac -version # Проверка версии компилятора
7.3. Первая программа: Hello World
Структура программы
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Ключевые элементы
public class HelloWorld- объявление публичного класса- Имя класса должно совпадать с именем файла
public static void main(String[] args)- точка входа в программуSystem.out.println()- вывод в консоль
Компиляция и запуск
javac HelloWorld.java # Компиляция → создаёт HelloWorld.class
java HelloWorld # Запуск (БЕЗ расширения .class!)
8. Основы синтаксиса Java
8.1. Типы данных
Примитивные типы
Целочисленные:
byte- 8 бит (-128 до 127)short- 16 бит (-32768 до 32767)int- 32 бита (-2³¹ до 2³¹-1)long- 64 бита (-2⁶³ до 2⁶³-1)
Вещественные:
float- 32 бита (одинарная точность)double- 64 бита (двойная точность)
Другие:
boolean- true/falsechar- 16 бит (символ Unicode)
Ссылочные типы
- Строки:
String - Массивы
- Объекты классов
8.2. Переменные
Объявление и инициализация
int x; // Объявление
x = 10; // Инициализация
int y = 20; // Объявление с инициализацией
Константы
final int MAX_VALUE = 100; // Константа (нельзя изменить)
8.3. Операторы
Арифметические операторы
+- сложение-- вычитание*- умножение/- деление%- остаток от деления
Операторы сравнения
==- равно!=- не равно>,<- больше, меньше>=,<=- больше или равно, меньше или равно
Логические операторы
&&- логическое И (AND)||- логическое ИЛИ (OR)!- логическое НЕ (NOT)
Операторы присваивания
=- присваивание+=,-=,*=,/=- составное присваивание
8.4. Управляющие конструкции
Условный оператор if
if (условие) {
// код
} else if (другое_условие) {
// код
} else {
// код
}
Оператор switch
switch (переменная) {
case значение1:
// код
break;
case значение2:
// код
break;
default:
// код по умолчанию
}
Цикл while
while (условие) {
// код
}
Цикл do-while
do {
// код
} while (условие);
Цикл for
for (инициализация; условие; инкремент) {
// код
}
// Пример:
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
Цикл for-each
for (тип элемент : коллекция) {
// код
}
9. Ввод и вывод
9.1. Вывод в консоль
System.out.println("текст"); // Вывод с переводом строки
System.out.print("текст"); // Вывод без перевода строки
9.2. Ввод из консоли
import java.util.Scanner;
Scanner scanner = new Scanner(System.in);
int number = scanner.nextInt(); // Чтение целого числа
String line = scanner.nextLine(); // Чтение строки
double d = scanner.nextDouble(); // Чтение вещественного числа
9.3. Работа с аргументами командной строки
public static void main(String[] args) {
// args[0] - первый аргумент
// args[1] - второй аргумент
// args.length - количество аргументов
}
10. Массивы
10.1. Одномерные массивы
Объявление и создание
int[] array; // Объявление
array = new int[10]; // Создание массива на 10 элементов
int[] array2 = new int[5]; // Объявление с созданием
// Инициализация значениями
int[] array3 = {1, 2, 3, 4, 5};
Обращение к элементам
array[0] = 10; // Присваивание
int x = array[0]; // Чтение
Длина массива
int length = array.length; // Поле length (НЕ метод!)
10.2. Многомерные массивы
int[][] matrix = new int[3][4]; // 3 строки, 4 столбца
int[][] matrix2 = {{1,2}, {3,4}, {5,6}};
11. Строки (String)
11.1. Создание строк
String s1 = "Hello";
String s2 = new String("World");
11.2. Основные методы
int len = s.length(); // Длина строки
char ch = s.charAt(0); // Символ по индексу
String sub = s.substring(0, 5); // Подстрока
String upper = s.toUpperCase(); // В верхний регистр
String lower = s.toLowerCase(); // В нижний регистр
11.3. Конкатенация
String result = s1 + s2;
String result2 = s1.concat(s2);
11.4. Особенности строк
- Строки в Java неизменяемые (immutable)
- Все операции создают новые строки
- Сравнение строк: использовать
equals(), НЕ==
if (s1.equals(s2)) { // ПРАВИЛЬНО
// строки равны
}
if (s1 == s2) { // НЕПРАВИЛЬНО (сравнивает ссылки)
// это не то, что вы думаете
}
12. Работа с тестами
12.1. Репозиторий с тестами
- Тесты выкладываются в отдельный репозиторий
- Доступны исходный код и скомпилированная версия (.jar файлы)
12.2. Запуск тестов
Шаги для запуска
- Скачать .jar файл с тестами
- Скомпилировать свою программу
- Проверить наличие .class файла
- Запустить тесты командой
Пример команды запуска
java -cp <путь_к_тестируемому_классу>:<путь_к_тест.jar> <название_теста>
Рекомендация: Создать скрипт для автоматизации запуска тестов
12.3. Требования к решениям
- Для второго ДЗ: промежуточные результаты должны помещаться в
int - Использовать можно всё из стандартной поставки Java
- Неправильное использование → минусы при сдаче
13. Дополнительное задание: Run.me
13.1. Описание
- Необязательное задание для тех, кому "нечего делать"
- Содержит как простые, так и откровенно сложные задачи
- Предназначено для дополнительной практики
13.2. Рекомендации
- ✅ Посмотреть полчасика
- ✅ Получить доступные плюсики
- ✅ Перейти к основному ДЗ
- ⚠️ НЕ закапываться в Run.me - это плохая стратегия!
13.3. Оценивание
- Максимум баллов не больше, чем за обычное ДЗ
- Выполнить обычное ДЗ гораздо полезнее
- Сложность оценивается по количеству решивших
- Оценка: коэффициент × количество решённых задач
13.4. Технические детали
- Можно использовать всё что угодно
- Проверяется только правильность URL результата
- Код НЕ проверяется (в отличие от обычных ДЗ)
- Каждая строка = отдельное число (не склеиваются)
- Не надо показывать код преподавателю
14. Система баллов и оценок
14.1. Начисление очков
- Очки начисляются за сдачу домашних заданий
- Видны в специальной таблице (НЕ в БАРСе)
- Несдача ДЗ = 0 очков
14.2. Важные замечания
- ⚠️ Нельзя сравнивать очки за разные ДЗ
- ⚠️ Нельзя сравнивать очки между группами
- ✅ Гарантируется локальная справедливость внутри группы
14.3. Локальная справедливость
Правило:
Если студент A и студент B:
- Решили одинаковые ДЗ
- У A не больше задержки, чем у B
- У A не больше минусов, чем у B
→ То у A точно не меньше баллов, чем у B
14.4. Конвертация в БАРС
- Конвертация происходит в конце курса
- Очки нормируются относительно группы
- Чем больше очков относительно коллег → выше оценка
14.5. Критерии оценок
- Для 5 (отлично): > 90 баллов в БАРСе
- За каждое ДЗ гарантируется минимальный процент баллов
- Сдать ДЗ всегда строго лучше, чем не сдать
- Разница между "сдано" и "не сдано" существенная
14.6. Причины разброса баллов
- Результаты Run.me (различия в решённых задачах)
- Задержки при сдаче
- Количество минусов
- Относительный перформанс в группе
14.7. Интерпретация статуса
- 🟢 Зелёный → всё хорошо
- 🔴 Красный → проблемы, нужно подтянуться
15. Практические рекомендации
15.1. Стратегия успешной сдачи
- ✅ Начинать делать ДЗ сразу после выдачи
- ✅ Стремиться сдать в первую неделю (delay = 0)
- ✅ Тщательно проверять код перед демонстрацией
- ✅ Использовать тесты для самопроверки
- ✅ Создать скрипты для автоматизации
15.2. Работа с кодом
- Можно использовать линтеры для Java
- Следить за качеством кода
- Исправлять замечания преподавателя
- Помнить о накоплении минусов
15.3. Что НЕ стоит делать
- ❌ Откладывать ДЗ на последнюю неделю
- ❌ Закапываться в Run.me вместо основного ДЗ
- ❌ Игнорировать замечания преподавателя
- ❌ Сравнивать свои баллы с другими группами
16. Обратная связь
16.1. Если недоволен результатом
- Использовать кнопку 👎 (thumbs down) под ответами
- Написать в чат курса
- Отправить email преподавателю
16.2. Если что-то непонятно
- Задавать вопросы в чате
- Подходить к преподавателю после лекции
- Писать на email для сложных вопросов
Резюме первой лекции
Ключевые выводы
- Организация: Лекции → ДЗ → Практика (сдача модификаций)
- Оценивание: Очки → конвертация в БАРС → итоговая оценка
- Java: Популярный, простой, безопасный, кроссплатформенный язык
- Стратегия: Сдавать быстро, качественно, регулярно
Что делать дальше
- Настроить среду разработки (JDK установлен)
- Начать второе домашнее задание
- Скачать и настроить тесты
- Стремиться сдать в первую неделю
Важные даты
- Сдача ДЗ: каждый вторник (3 попытки)
- Досрочный зачёт: конец декабря
- Стандартный зачёт: сессия
Полезные ссылки
- Чат курса (основные вопросы)
- Email преподавателя (сложные вопросы)
- Репозиторий с тестами
- Материалы курса
- Раздел "Ошибки и опечатки" в чате
Успехов в изучении Java! 🚀