---
gitea: none
include_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! 🚀**
