Меня всегда бесило одно: программа работает сама по себе, как робот. Запустил — она что-то сделала — завершилась. А хочется же, чтобы она с тобой общалась! Чтобы спросила что-нибудь, получила ответ, отреагировала. И вот тут появляется класс Scanner. Представь его как такого официанта в ресторане — ты говоришь ему свой заказ, он аккуратно записывает и несёт на кухню (то есть в твою программу). Без него никак не обойтись, если хочешь, чтобы программа реагировала на действия пользователя.Потоки ввода/вывода и строки в Java - 1Кстати! Scanner живёт в пакете java.util, поэтому его обязательно нужно импортировать. Делается это в самом начале, ещё до объявления класса:
import java.util.Scanner;

Создаём Scanner — наш первый шаг

Чтобы начать работать со Scanner, нужно создать его объект. При создании мы сразу говорим ему: "Слушай, дружок, вот откуда будешь читать данные". Для клавиатуры используется специальная штука — System.in. Это стандартный поток ввода в Java. Помнишь System.out? Это для вывода на экран. А System.in — для ввода. Логично же! Есть ещё System.err для ошибок, но это уже совсем другая история.
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Окей, я готов слушать!");
    }
}
Вот этот sc — это просто имя переменной. Можешь назвать как угодно: scanner, input, хоть keyboard. Главное — чтобы тебе было понятно, что это такое.

Читаем числа (и не падаем в обморок)

Допустим, тебе нужно спросить у пользователя число. Казалось бы — чего проще? Но есть засада: пользователь может ввести вообще всё что угодно. Слово "привет", какой-нибудь смайлик, текст любимой песни... А ты-то ждёшь число! Поэтому перед чтением нужно проверить: "Эй, там точно число? Или опять какая-то фигня?" Для этого есть метод hasNextInt() — он возвращает true, если следующее, что ввёл пользователь, действительно целое число.
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Дай мне число: ");
        
        if (sc.hasNextInt()) {
            int number = sc.nextInt();
            System.out.println("Отлично! Удваиваю: " + number * 2);
        } else {
            System.out.println("Да это же не число совсем! Давай по новой.");
        }
        
        sc.close();
    }
}
При вводе 5:
Дай мне число: 5
Отлично! Удваиваю: 10
При вводе "абракадабра":
Дай мне число: абракадабра
Да это же не число совсем! Давай по новой.
Видишь в конце sc.close()? Это важная штука. Scanner использует системные ресурсы, и их нужно освобождать. Как кран закрыть после того, как помыл посуду — иначе вода будет литься зря. Да, я знаю, что все об этом забывают в начале, но лучше сразу привыкай!

А если забыть проверку? Всё сломается

Вот смотри, что будет, если считывать число напрямую, без проверки:
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Введи число: ");
        int number = sc.nextInt(); // Бабах! Тут всё упадёт, если ввести текст
        System.out.println("Делим на два: " + number / 2);
        
        sc.close();
    }
}
Если пользователь введёт что-то типа "hello", программа рухнет с ошибкой InputMismatchException. Причём компилятор об этом не предупредит — ошибка вылезет только во время выполнения. Неприятненько...

Дробные числа — тот же принцип

Для работы с double (числа с плавающей точкой) всё аналогично: - hasNextDouble() проверяет - nextDouble() считывает
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Введи дробное число: ");
        
        if (sc.hasNextDouble()) {
            double number = sc.nextDouble();
            System.out.println("Делим на 3: " + number / 3);
        } else {
            System.out.println("Эм, это не похоже на число...");
        }
        
        sc.close();
    }
}
При вводе 9.6:
Введи дробное число: 9.6
Делим на 3: 3.2
Всё просто, да?

Строки — когда нужен текст

Иногда нужно получить от пользователя целую фразу или предложение. Тут поможет nextLine() — он читает всю строку до Enter:
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Как тебя зовут? ");
        String name = sc.nextLine();
        
        System.out.print("А фамилия? ");
        String surname = sc.nextLine();
        
        System.out.println("Значит, тебя зовут " + name + " " + surname + ". Запомнил!");
        
        sc.close();
    }
}
Вывод:
Как тебя зовут? Иван
А фамилия? Петров
Значит, тебя зовут Иван Петров. Запомнил!
Кстати, есть ещё метод hasNext() — он проверяет, остались ли вообще какие-то данные в потоке ввода. Пригодится позже, когда будешь обрабатывать большие объёмы информации.

Работаем со строками — класс String

Ладно, научились получать данные от пользователя. Теперь что с ними делать? У класса String в Java куча полезных методов. Давай разберём самые нужные!

Узнаём длину — метод length()

int length() возвращает количество символов.
String text = "JavaRush";
int len = text.length();
System.out.println("В этой строке " + len + " символов");
Вывод:
В этой строке 8 символов
Просто и понятно.

Пустая строка или нет — isEmpty()

boolean isEmpty() проверяет, есть ли в строке хоть один символ.
String empty = "";
String notEmpty = "Привет";
System.out.println(empty.isEmpty());    // true
System.out.println(notEmpty.isEmpty()); // false

Заменяем символы — replace()

String replace(a, b) создаёт новую строку, где все символы a заменены на b.
String text = "Hello";
String fixed = text.replace('l', 'p');
System.out.println(fixed);
Вывод:
Heppo
Важный момент! Метод replace() НЕ изменяет исходную строку. Он возвращает новую. Строки в Java неизменяемые (immutable) — это важное свойство. Поэтому если просто напишешь text.replace('l', 'p'); без присваивания результата, исходная строка останется прежней. Многие тут спотыкаются вначале!

Меняем регистр

String toLowerCase() делает все буквы маленькими. String toUpperCase() делает все буквы большими.
String text = "Java is Cool";
System.out.println(text.toLowerCase());
System.out.println(text.toUpperCase());
Вывод:
java is cool
JAVA IS COOL

Сравниваем строки правильно!

boolean equals(s) — вот этим методом нужно сравнивать строки. Знаешь, сколько новичков попадается на эту ловушку? НЕЛЬЗЯ сравнивать строки через ==! Это частая ошибка. Оператор == сравнивает ссылки на объекты, а не их содержимое. Запомни раз и навсегда: для строк (и вообще объектов) используй equals()!
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");

System.out.println(s1.equals(s2));  // true — содержимое одинаковое
System.out.println(s1.equals(s3));  // true — содержимое одинаковое
System.out.println(s1 == s3);        // false — разные объекты!
Видишь разницу? Используй equals() — всегда!

Ищем символы в строке

int indexOf(ch) возвращает позицию первого вхождения символа. Если не нашёл — вернёт -1. int lastIndexOf(ch) возвращает позицию последнего вхождения. int indexOf(ch, n) ищет символ, начиная с позиции n. Не забывай: нумерация начинается с нуля! Первый символ — это индекс 0, второй — индекс 1, и так далее.
String word = "programming";
System.out.println(word.indexOf('g'));      // 3
System.out.println(word.indexOf('m'));      // 6 (первая 'm')
System.out.println(word.lastIndexOf('m'));  // 7 (последняя 'm')
System.out.println(word.indexOf('x'));      // -1 (нет такой буквы)
System.out.println(word.indexOf('m', 7));   // 7 (ищем с 7-й позиции)

Получаем отдельный символ

char charAt(n) возвращает символ на позиции n. Именно символ типа char, а не его ASCII-код или ещё что-то!
String text = "JavaRush";
char first = text.charAt(0);
char last = text.charAt(7);

System.out.println("Первый: " + first);
System.out.println("Последний: " + last);
Вывод:
Первый: J
Последний: h

Большой пример — собираем всё вместе

Давай теперь посмотрим, как всё это работает в комбинации:
public class Main {
    public static void main(String[] args) {
        String word = "firefox";
        
        System.out.println("Исходное слово: " + word);
        System.out.println("БОЛЬШИМИ БУКВАМИ: " + word.toUpperCase());
        
        String changed = word.replace('o', 'a');
        System.out.println("Заменили 'o' на 'a': " + changed);
        
        System.out.println("Второй символ — это '" + changed.charAt(1) + "'");
        
        System.out.println("Длина: " + word.length() + " символов");
        
        System.out.println("Первая 'f' на позиции: " + word.indexOf('f'));
        System.out.println("Первая 'r' на позиции: " + word.indexOf('r'));
        System.out.println("Последняя 'f' на позиции: " + word.lastIndexOf('f'));
        
        System.out.println("Буква 't' есть? Позиция: " + word.indexOf('t'));
        System.out.println("'r' после 3-й позиции: " + word.indexOf('r', 3));
    }
}
Вывод:
Исходное слово: firefox
БОЛЬШИМИ БУКВАМИ: FIREFOX
Заменили 'o' на 'a': firefax
Второй символ — это 'i'
Длина: 7 символов
Первая 'f' на позиции: 0
Первая 'r' на позиции: 2
Последняя 'f' на позиции: 4
Буква 't' есть? Позиция: -1
'r' после 3-й позиции: -1
Когда символ не найден (как буква 't'), метод возвращает -1. Это стандартный способ сказать "не нашёл".

Практика — находим все пробелы

А теперь задачка посложнее. Программа, которая находит все пробелы в строке:
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        System.out.print("Напиши что-нибудь: ");
        String text = sc.nextLine();
        
        System.out.println("Пробелы стоят на позициях:");
        
        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == ' ') {
                System.out.println("Позиция " + i);
            }
        }
        
        sc.close();
    }
}
При вводе "Java это круто":
Напиши что-нибудь: Java это круто
Пробелы стоят на позициях:
Позиция 4
Позиция 8
Смотри, как круто: используем цикл for для перебора всех символов, метод length() чтобы знать, сколько раз крутить цикл, и charAt() для проверки каждого символа. Красота!

Что нужно запомнить

Про Scanner: После работы обязательно вызывай close(). Серьёзно, это важно! Освобождаются ресурсы системы. Всегда проверяй ввод методами типа hasNextInt() перед чтением. Иначе программа может упасть в самый неподходящий момент. Про строки: Строки в Java неизменяемые. Все методы возвращают НОВУЮ строку, а не меняют старую. Присваивай результат переменной! Для сравнения строк используй equals(), а не ==. Это золотое правило. Одинарные кавычки ('a') для символов char, двойные ("text") для строк String. Не путай!

Что дальше?

Поздравляю! Теперь ты можешь делать программы, которые общаются с пользователем. Это базовый навык, который пригодится в каждом проекте. Впереди ещё много интересного: регулярные выражения для продвинутой работы с текстом, форматирование вывода, работа с файлами... Но пока — практикуйся с тем, что узнал! Пиши маленькие программки, экспериментируй, ломай и чини. Программирование учится только через практику. Можно месяц читать теорию про велосипед, но пока не сядешь и не попробуешь — не научишься ездить. Удачи!