--- gitea: none allow-toc: true --- # Конспект лекции 2: Массивы и ссылки **Преподаватель:** Георгий Корнеев **Курс:** Введение в программирование (Java) --- ## Содержание 1. [Одномерные массивы](#1-одномерные-массивы) 2. [Многомерные массивы](#2-многомерные-массивы) 3. [Ссылки на массивы](#3-ссылки-на-массивы) 4. [Полные имена классов](#4-полные-имена-классов) 5. [Класс Scanner](#5-класс-scanner) 6. [Домашнее задание](#6-домашнее-задание) --- ## 1. Одномерные массивы ### 1.1. Типы данных в Java (повторение) **Классификация типов:** ``` Типы данных ├── Примитивные (primitive) │ ├── int, long │ ├── char │ ├── boolean │ └── double, float └── Ссылочные (reference) ├── String ├── Массивы └── Объекты классов ``` ⚠️ **Важно:** Массивы — это ссылочные типы! --- ### 1.2. Объявление массивов #### Синтаксис объявления ```java int[] ints; // Массив целых чисел double[] doubles; // Массив вещественных чисел boolean[] booleans; // Массив булевых значений String[] strings; // Массив строк char[] chars; // Массив символов long[] longs; // Массив длинных целых ``` **Важные особенности:** - Квадратные скобки `[]` указывают на тип "массив" - Можно создавать массивы любых типов (примитивных и ссылочных) --- ### 1.3. Создание массивов #### Способ 1: Указание размера ```java 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: Инициализация значениями ```java ints = new int[]{1, 2, 3}; doubles = new double[]{1.5}; booleans = new boolean[]{true, false}; strings = new String[]{"a", "b", "c"}; ``` #### Способ 3: Сокращённая инициализация (при объявлении) ```java int[] ints = {1, 2, 3}; String[] strings = {"hello", "world", "array"}; ``` ⚠️ **Нельзя комбинировать:** `new int[5]{1, 2, 3, 4, 5}` — **НЕ компилируется!** --- ### 1.4. Длина массива ```java 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` | ```java 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. Доступ к элементам массива ```java 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. Ошибки при работе с массивами #### Отрицательная длина ```java int[] array = new int[-5]; // Исключение: NegativeArraySizeException ``` #### Выход за границы ```java int[] array = new int[3]; System.out.println(array[5]); // Исключение: ArrayIndexOutOfBoundsException ``` #### Обращение к null ```java int[] array = null; System.out.println(array.length); // Исключение: NullPointerException ``` --- ### 1.8. Итерация по массивам #### Цикл for (с индексом) ```java int[] ints = {1, 2, 3, 4, 5}; // i — это индекс for (int i = 0; i < ints.length; i++) { System.out.println(ints[i]); } ``` **Когда использовать:** - Нужен индекс элемента - Нужен доступ на запись - Нужна итерация с шагом (не по порядку) #### Цикл for-each (без индекса) ```java int[] ints = {1, 2, 3, 4, 5}; // i — это значение элемента for (int i : ints) { System.out.println(i); } ``` **Когда использовать:** - Нужно только читать значения - Итерация всегда последовательная - Индекс не нужен **Преимущества for-each:** - Более читаемый код - Меньше ошибок (нет индексов) - Работает с любыми коллекциями --- ### 1.9. Максимальная длина массива ```java // Максимальное значение int int maxSize = Integer.MAX_VALUE; // 2,147,483,647 // НО! Массив такой длины создать НЕЛЬЗЯ int[] huge = new int[Integer.MAX_VALUE]; // Исключение: OutOfMemoryError ``` **Ограничения:** - Длина массива имеет тип `int` - Физически ограничено доступной памятью - JVM имеет лимиты на размер heap (куча) **Пример работы с памятью:** ```java // Настройка 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. Динамический размер массива Размер может определяться во время выполнения: ```java public static void main(String[] args) { // Первый аргумент командной строки int size = Integer.parseInt(args[0]); // Создаём массив динамического размера int[] array = new int[size]; System.out.println("Создан массив длины: " + array.length); } ``` ```bash # Запуск программы java MyProgram 123 # Вывод: Создан массив длины: 123 ``` --- ## 2. Многомерные массивы ### 2.1. Концепция многомерных массивов **Важная идея:** В Java многомерные массивы — это **массивы массивов**! ``` Двумерный массив: int[][] matrix - это массив, каждый элемент которого — массив int[] Трёхмерный массив: int[][][] cube - это массив, каждый элемент которого — массив int[][] ``` --- ### 2.2. Объявление многомерных массивов ```java int[][] ints2d; // Двумерный массив int[][][] ints3d; // Трёхмерный массив String[][] strings2d; // Двумерный массив строк ``` --- ### 2.3. Создание многомерных массивов #### Полное создание (прямоугольный массив) ```java // Матрица 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[][]) ``` #### Частичное создание ```java // Создаём только первое измерение int[][] matrix = new int[10][]; int[][][] cube = new int[10][][]; System.out.println(matrix[0]); // null (элементы не созданы!) System.out.println(cube[0]); // null ``` **Использование:** ```java int[][] matrix = new int[10][]; // Заполняем вручную for (int i = 0; i < matrix.length; i++) { matrix[i] = new int[i]; // Каждая строка своей длины! } ``` --- ### 2.4. Непрямоугольные массивы Java позволяет создавать **"рваные" массивы** (jagged arrays) — массивы, где строки имеют разную длину: ```java // Создание непрямоугольного массива 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 } ``` #### Инициализация непрямоугольного массива ```java 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. Работа с двумерными массивами #### Итерация по всем элементам ```java 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. Значения по умолчанию в многомерных массивах ```java 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. Массивы как ссылочный тип **Ключевая концепция:** Переменная массива хранит не сам массив, а **ссылку** на него в памяти. ```java int[] a = new int[10]; // a содержит ссылку на массив ``` ``` Память: ┌─────────┐ ┌───────────────┐ │ a │───────>│ [0,0,0,...,0] │ └─────────┘ └───────────────┘ переменная массив в heap ``` --- ### 3.2. Копирование ссылок ```java 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. Переприсваивание ссылок ```java 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. Передача массивов в функции #### Изменение элементов массива ```java 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] ``` ✅ **Изменения видны снаружи** — мы меняем элементы по ссылке! --- #### Переприсваивание параметра (НЕ работает!) ```java 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. Возврат массива из функции ```java 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 автоматически освобождает память от неиспользуемых объектов: ```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"); // Программа работает! Сборщик мусора освобождает память ``` **Как это работает:** 1. Когда на объект не осталось ссылок, он становится "мусором" 2. Сборщик мусора периодически удаляет такие объекты 3. Память освобождается автоматически --- ### 3.7. Копирование массивов #### Проблема с присваиванием ```java int[] a = {1, 2, 3}; int[] b = a; // Это НЕ копирование, это копирование ссылки! a[0] = 100; System.out.println(b[0]); // 100 (изменили оба массива!) ``` #### Правильное копирование: System.arraycopy() ```java 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() #### Корректная работа с перекрывающимися областями ```java 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. Полные имена классов **Полное имя** = путь через пакеты + имя класса ```java // Полное имя класса System java.lang.System // Полное имя класса Arrays java.util.Arrays // Полное имя класса Scanner java.util.Scanner ``` #### Использование полных имён ```java // Можно использовать полное имя везде java.util.Arrays.toString(array); java.lang.System.out.println("Hello"); java.lang.Integer.parseInt("123"); ``` --- ### 4.3. Оператор import Чтобы не писать полные имена постоянно, используется `import`: ```java import java.util.Arrays; import java.util.Scanner; import java.lang.Integer; // Теперь можно использовать короткие имена Arrays.toString(array); Scanner scanner = new Scanner(System.in); Integer.parseInt("123"); ``` #### Импорт всех классов из пакета ```java import java.util.*; // Импортирует все классы из java.util Arrays.toString(array); // Работает Scanner scanner = ...; // Работает ``` --- ### 4.4. Неявный импорт java.lang **Важно:** Пакет `java.lang` **импортируется автоматически**! ```java // Эта строка присутствует неявно в каждой программе: import java.lang.*; // Поэтому эти классы доступны без import: String s = "hello"; System.out.println(s); Integer.parseInt("123"); Math.sqrt(25); ``` --- ### 4.5. Класс Arrays Класс `java.util.Arrays` содержит полезные методы для работы с массивами: ```java 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. Вывод массивов ```java 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** — класс для удобного чтения данных из различных источников: - Стандартный ввод (консоль) - Файлы - Строки - Потоки данных ```java import java.util.Scanner; ``` --- ### 5.2. Создание Scanner для стандартного ввода ```java Scanner scanner = new Scanner(System.in); ``` **Параметры:** - `System.in` — стандартный поток ввода (stdin) - Можно также использовать `File`, `String`, `InputStream` и др. --- ### 5.3. Основные методы Scanner #### Чтение различных типов данных ```java 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. Проверка наличия данных ```java 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. Пример: сумма чисел ```java 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 ```java 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 **автоматически пропускает** пробельные символы (пробелы, табуляции, переводы строк): ```java Scanner scanner = new Scanner(System.in); // Ввод: " hello world " String s1 = scanner.next(); // "hello" String s2 = scanner.next(); // "world" ``` **Для чтения целых строк:** ```java String line = scanner.nextLine(); // Читает ВСЁ до конца строки ``` --- ### 5.8. Важные замечания 1. **Scanner читает из потока последовательно** — прочитанные данные нельзя "вернуть обратно" 2. **Разделители по умолчанию** — пробелы, табуляции, переводы строк 3. **Можно настроить разделители** через метод `useDelimiter()` 4. **Нет прямого способа прочитать char** — используйте `scanner.next().charAt(0)` --- ## 6. Домашнее задание ### 6.1. Задание: Класс Reverse **Описание:** Разработать класс `Reverse`, который читает числа из стандартного ввода и выводит их в обратном порядке. **Требования:** 1. Числа могут быть на нескольких строках 2. В каждой строке может быть несколько чисел 3. Нужно развернуть **порядок строк** 4. Нужно развернуть **порядок чисел в каждой строке** 5. Числа разделены пробелами 6. Все числа помещаются в тип `int` 7. Использовать класс `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. Алгоритм решения (подсказки) **Этапы:** 1. **Чтение данных** - Читать строку за строкой - Для каждой строки читать все числа - Сохранять в структуру данных (двумерный массив?) 2. **Разворот** - Развернуть порядок строк - В каждой строке развернуть порядок чисел 3. **Вывод** - Вывести каждую строку - Числа через один пробел **Вопросы для размышления:** - Как хранить строки разной длины? (Непрямоугольный массив!) - Как отличить пустую строку от конца ввода? - Как эффективно развернуть массивы? --- ## Резюме лекции ### Ключевые концепции 1. **Массивы — ссылочный тип** - Хранят ссылку, а не данные напрямую - Передача в функции = передача ссылки - Присваивание = копирование ссылки 2. **Многомерные массивы = массивы массивов** - Могут быть непрямоугольными - Каждое измерение — отдельный массив 3. **Значения по умолчанию** - Примитивы: `0`, `false`, `'\0'` - Ссылочные типы: `null` 4. **Пакеты и импорты** - `java.lang.*` импортируется автоматически - Остальные пакеты требуют `import` - Полное имя = `пакет.класс` 5. **Полезные классы** - `Arrays` — работа с массивами - `Scanner` — чтение данных - `System` — системные операции --- ### Важные методы и техники ```java // Работа с массивами 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 - Следующая тема: классы и объекты --- **Полезные ссылки:** - [Java Arrays Tutorial](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html) - [Java Arrays Documentation](https://docs.oracle.com/javase/specs/jls/se21/html/jls-10.html) - [java.util.Arrays API](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Arrays.html) - [java.util.Scanner API](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Scanner.html) --- **Удачи в выполнении домашнего задания! 🚀** # Конспект лекции 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 #### Простота и безопасность - Достаточно простой язык - Сложно создать код, который: - Убьёт компьютер - Приведёт к непредсказуемому поведению - Не воспроизводится на других машинах #### Содержательность - Простой, но весьма содержательный язык - Широкий спектр возможностей #### Области применения 1. **Серверные приложения** 2. **Desktop-приложения** 3. **Android-разработка** 4. **JVM-языки** (Kotlin, Scala и др.) --- ## 7. Основы Java ### 7.1. Концепция Java #### Виртуальная машина (JVM) - Java компилируется не в машинный код, а в **байт-код** - Байт-код исполняется на **виртуальной машине Java (JVM)** - **Преимущество:** кроссплатформенность (Write Once, Run Anywhere) #### Процесс выполнения программы 1. Написание кода на Java (.java файлы) 2. Компиляция в байт-код (.class файлы) 3. Выполнение на JVM ### 7.2. Установка и настройка #### Java Development Kit (JDK) - **Что включает:** - Компилятор Java - JVM - Стандартная библиотека - Инструменты разработки #### Проверка установки ```bash java -version # Проверка установленной версии JVM javac -version # Проверка версии компилятора ``` ### 7.3. Первая программа: Hello World #### Структура программы ```java 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()` - вывод в консоль #### Компиляция и запуск ```bash 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/false - `char` - 16 бит (символ Unicode) #### Ссылочные типы - Строки: `String` - Массивы - Объекты классов ### 8.2. Переменные #### Объявление и инициализация ```java int x; // Объявление x = 10; // Инициализация int y = 20; // Объявление с инициализацией ``` #### Константы ```java final int MAX_VALUE = 100; // Константа (нельзя изменить) ``` ### 8.3. Операторы #### Арифметические операторы - `+` - сложение - `-` - вычитание - `*` - умножение - `/` - деление - `%` - остаток от деления #### Операторы сравнения - `==` - равно - `!=` - не равно - `>`, `<` - больше, меньше - `>=`, `<=` - больше или равно, меньше или равно #### Логические операторы - `&&` - логическое И (AND) - `||` - логическое ИЛИ (OR) - `!` - логическое НЕ (NOT) #### Операторы присваивания - `=` - присваивание - `+=`, `-=`, `*=`, `/=` - составное присваивание ### 8.4. Управляющие конструкции #### Условный оператор if ```java if (условие) { // код } else if (другое_условие) { // код } else { // код } ``` #### Оператор switch ```java switch (переменная) { case значение1: // код break; case значение2: // код break; default: // код по умолчанию } ``` #### Цикл while ```java while (условие) { // код } ``` #### Цикл do-while ```java do { // код } while (условие); ``` #### Цикл for ```java for (инициализация; условие; инкремент) { // код } // Пример: for (int i = 0; i < 10; i++) { System.out.println(i); } ``` #### Цикл for-each ```java for (тип элемент : коллекция) { // код } ``` --- ## 9. Ввод и вывод ### 9.1. Вывод в консоль ```java System.out.println("текст"); // Вывод с переводом строки System.out.print("текст"); // Вывод без перевода строки ``` ### 9.2. Ввод из консоли ```java import java.util.Scanner; Scanner scanner = new Scanner(System.in); int number = scanner.nextInt(); // Чтение целого числа String line = scanner.nextLine(); // Чтение строки double d = scanner.nextDouble(); // Чтение вещественного числа ``` ### 9.3. Работа с аргументами командной строки ```java public static void main(String[] args) { // args[0] - первый аргумент // args[1] - второй аргумент // args.length - количество аргументов } ``` --- ## 10. Массивы ### 10.1. Одномерные массивы #### Объявление и создание ```java int[] array; // Объявление array = new int[10]; // Создание массива на 10 элементов int[] array2 = new int[5]; // Объявление с созданием // Инициализация значениями int[] array3 = {1, 2, 3, 4, 5}; ``` #### Обращение к элементам ```java array[0] = 10; // Присваивание int x = array[0]; // Чтение ``` #### Длина массива ```java int length = array.length; // Поле length (НЕ метод!) ``` ### 10.2. Многомерные массивы ```java int[][] matrix = new int[3][4]; // 3 строки, 4 столбца int[][] matrix2 = {{1,2}, {3,4}, {5,6}}; ``` --- ## 11. Строки (String) ### 11.1. Создание строк ```java String s1 = "Hello"; String s2 = new String("World"); ``` ### 11.2. Основные методы ```java 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. Конкатенация ```java String result = s1 + s2; String result2 = s1.concat(s2); ``` ### 11.4. Особенности строк - Строки в Java **неизменяемые** (immutable) - Все операции создают новые строки - Сравнение строк: использовать `equals()`, НЕ `==` ```java if (s1.equals(s2)) { // ПРАВИЛЬНО // строки равны } if (s1 == s2) { // НЕПРАВИЛЬНО (сравнивает ссылки) // это не то, что вы думаете } ``` --- ## 12. Работа с тестами ### 12.1. Репозиторий с тестами - Тесты выкладываются в отдельный репозиторий - Доступны исходный код и скомпилированная версия (.jar файлы) ### 12.2. Запуск тестов #### Шаги для запуска 1. Скачать .jar файл с тестами 2. Скомпилировать свою программу 3. Проверить наличие .class файла 4. Запустить тесты командой #### Пример команды запуска ```bash 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. Стратегия успешной сдачи 1. ✅ Начинать делать ДЗ сразу после выдачи 2. ✅ Стремиться сдать в первую неделю (delay = 0) 3. ✅ Тщательно проверять код перед демонстрацией 4. ✅ Использовать тесты для самопроверки 5. ✅ Создать скрипты для автоматизации ### 15.2. Работа с кодом - Можно использовать линтеры для Java - Следить за качеством кода - Исправлять замечания преподавателя - Помнить о накоплении минусов ### 15.3. Что НЕ стоит делать - ❌ Откладывать ДЗ на последнюю неделю - ❌ Закапываться в Run.me вместо основного ДЗ - ❌ Игнорировать замечания преподавателя - ❌ Сравнивать свои баллы с другими группами --- ## 16. Обратная связь ### 16.1. Если недоволен результатом - Использовать кнопку 👎 (thumbs down) под ответами - Написать в чат курса - Отправить email преподавателю ### 16.2. Если что-то непонятно - Задавать вопросы в чате - Подходить к преподавателю после лекции - Писать на email для сложных вопросов --- ## Резюме первой лекции ### Ключевые выводы 1. **Организация:** Лекции → ДЗ → Практика (сдача модификаций) 2. **Оценивание:** Очки → конвертация в БАРС → итоговая оценка 3. **Java:** Популярный, простой, безопасный, кроссплатформенный язык 4. **Стратегия:** Сдавать быстро, качественно, регулярно ### Что делать дальше 1. Настроить среду разработки (JDK установлен) 2. Начать второе домашнее задание 3. Скачать и настроить тесты 4. Стремиться сдать в первую неделю ### Важные даты - Сдача ДЗ: каждый вторник (3 попытки) - Досрочный зачёт: конец декабря - Стандартный зачёт: сессия --- ## Полезные ссылки - Чат курса (основные вопросы) - Email преподавателя (сложные вопросы) - Репозиторий с тестами - Материалы курса - Раздел "Ошибки и опечатки" в чате --- **Успехов в изучении Java! 🚀**