LEARN X · ЗА 18 МИН
Java
Весь Java на одной странице: типы, строки, циклы, массивы, коллекции, ООП, наследование, интерфейсы, исключения, дженерики и Stream API в комментариях кода.
Java — строго типизированный объектно-ориентированный язык со статической компиляцией в байт-код JVM. Здесь весь язык на одной странице: почти без прозы, всё объяснение живёт в комментариях кода. Читай сверху вниз — каждый блок компилируется, а результат указан в комментариях.
1. Структура программы
Точка входа — метод main внутри класса. Имя файла должно совпадать с именем публичного класса (Main.java).
// Однострочный комментарий
/* Многострочный
комментарий */
/** Javadoc-комментарий для документации */
public class Main {
// public static void main(String[] args) — обязательная сигнатура точки входа
public static void main(String[] args) {
System.out.println("Привет, Java!"); // вывод с переводом строки -> Привет, Java!
System.out.print("без переноса"); // вывод без \n
System.out.printf("%s = %d%n", "x", 42); // форматный вывод -> x = 42
}
}
2. Переменные и типы
Восемь примитивных типов хранят значение напрямую; объекты хранятся по ссылке.
// --- Примитивы (значение хранится напрямую) ---
int i = 42; // целое 32 бита
long big = 9_000_000_000L; // 64 бита, суффикс L; _ — разделитель разрядов
short s = 100; // 16 бит
byte b = 127; // 8 бит
double d = 3.14; // дробное 64 бита (по умолчанию для дробных)
float f = 3.14f; // 32 бита, суффикс f
boolean flag = true; // true / false
char c = 'A'; // одиночный символ в одинарных кавычках (Unicode)
// --- var: вывод типа компилятором (с Java 10) ---
var name = "Аня"; // компилятор выводит String
var count = 10; // компилятор выводит int
// --- Примитивы vs объекты ---
int prim = 5; // примитив
Integer obj = 5; // объект-обёртка (autoboxing); может быть null
long max = Long.MAX_VALUE; // 9223372036854775807
String text = Integer.toString(prim); // "5"
int parsed = Integer.parseInt("123"); // 123
final double PI = 3.14159; // final — константа, переприсвоить нельзя
3. Строки
Строки неизменяемы (immutable). Для частой конкатенации используют StringBuilder.
String str = "Hello, Java";
str.length(); // 11 — длина
str.charAt(0); // 'H' — символ по индексу
str.substring(7); // "Java" — подстрока с индекса
str.substring(0, 5); // "Hello" — [0;5)
str.indexOf("Java"); // 7 — позиция подстроки
str.toUpperCase(); // "HELLO, JAVA"
str.replace("Java", "Kt"); // "Hello, Kt"
str.contains("Java"); // true
str.split(", "); // ["Hello", "Java"]
" отступ ".trim(); // "отступ" — обрезка пробелов
"a".equals("a"); // true — сравнение содержимого (== сравнивает ссылки!)
// Конкатенация
String full = "abc" + 1 + true; // "abc1true"
// StringBuilder — изменяемая строка (быстро для циклов)
StringBuilder sb = new StringBuilder();
sb.append("раз").append("-").append(2);
sb.toString(); // "раз-2"
// Форматирование
String.format("%s: %d (%.2f)", "sum", 10, 3.5); // "sum: 10 (3.50)"
// Текстовый блок (с Java 15) — многострочная строка
String json = """
{"name": "Аня"}
""";
4. Операторы и условия
// Арифметика: + - * / % (целочисленное деление отбрасывает дробь)
7 / 2; // 3
7 % 2; // 1 (остаток)
7.0 / 2; // 3.5
// Сравнение: == != < > <= >=
// Логика: && (и), || (или), ! (не)
int age = 18;
if (age >= 18) {
System.out.println("взрослый");
} else if (age >= 14) {
System.out.println("подросток");
} else {
System.out.println("ребёнок");
}
// Тернарный оператор: условие ? если_да : если_нет
String status = age >= 18 ? "можно" : "нельзя"; // "можно"
// switch (классический)
int day = 3;
switch (day) {
case 1: System.out.println("Пн"); break; // break обязателен, иначе провал
case 3: System.out.println("Ср"); break;
default: System.out.println("?");
}
// switch-выражение со стрелкой (с Java 14) — возвращает значение, без break
String name = switch (day) {
case 1 -> "Понедельник";
case 3 -> "Среда";
default -> "Другой";
}; // "Среда"
5. Циклы
// for: инициализация; условие; шаг
for (int i = 0; i < 3; i++) {
System.out.print(i); // 012
}
// for-each: перебор элементов коллекции/массива
int[] nums = {10, 20, 30};
for (int n : nums) {
System.out.print(n + " "); // 10 20 30
}
// while: пока условие истинно
int k = 0;
while (k < 3) {
k++;
} // k == 3
// do-while: тело выполняется хотя бы раз
int m = 0;
do {
m++;
} while (m < 0); // m == 1 (вошли один раз)
// break — выход, continue — к следующей итерации
for (int i = 0; i < 10; i++) {
if (i == 2) continue; // пропустить 2
if (i == 5) break; // остановиться на 5
System.out.print(i); // 0134
}
6. Массивы
Массивы фиксированной длины, индексация с нуля.
// Объявление и создание
int[] a = new int[3]; // [0, 0, 0] — заполнен нулями
a[0] = 5; // присваивание по индексу
a.length; // 3 — длина (поле, не метод!)
// Инициализация литералом
int[] b = {1, 2, 3, 4};
String[] names = {"Аня", "Боб"};
// Перебор
for (int i = 0; i < b.length; i++) {
System.out.print(b[i]); // 1234
}
// Многомерный массив (матрица)
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
grid[1][2]; // 6 — строка 1, столбец 2
// Утилиты Arrays
import java.util.Arrays;
int[] c = {3, 1, 2};
Arrays.sort(c); // [1, 2, 3] — сортировка на месте
Arrays.toString(c); // "[1, 2, 3]" — для печати
int[] d = Arrays.copyOf(c, 5); // [1, 2, 3, 0, 0]
7. Коллекции
Из пакета java.util. В угловых скобках — дженерик-тип элементов.
import java.util.*;
// --- ArrayList: динамический список ---
List<String> list = new ArrayList<>();
list.add("a"); // [a]
list.add("b"); // [a, b]
list.get(0); // "a"
list.set(0, "z"); // [z, b]
list.remove("b"); // [z]
list.size(); // 1
list.contains("z"); // true
// --- HashMap: ключ -> значение ---
Map<String, Integer> ages = new HashMap<>();
ages.put("Аня", 25); // добавить пару
ages.put("Боб", 30);
ages.get("Аня"); // 25
ages.getOrDefault("Ева", 0); // 0 — значение по умолчанию
ages.containsKey("Боб"); // true
for (Map.Entry<String, Integer> e : ages.entrySet()) {
System.out.println(e.getKey() + "=" + e.getValue());
}
// --- HashSet: множество уникальных значений ---
Set<Integer> set = new HashSet<>();
set.add(1);
set.add(1); // дубликат игнорируется
set.add(2);
set.size(); // 2
8. Методы
// Объявление: модификатор тип_возврата имя(параметры)
static int sum(int x, int y) {
return x + y; // возврат значения
}
static void greet(String name) { // void — ничего не возвращает
System.out.println("Привет, " + name);
}
// Перегрузка: одно имя, разные параметры
static int multiply(int a, int b) { return a * b; }
static double multiply(double a, double b) { return a * b; }
// multiply(2, 3) -> 6 ; multiply(2.0, 3.0) -> 6.0
// varargs: переменное число аргументов (внутри — массив)
static int total(int... nums) {
int s = 0;
for (int n : nums) s += n;
return s;
}
// total(1, 2, 3) -> 6 ; total() -> 0
9. Классы и ООП
public class Person {
// Поля (private — инкапсуляция: доступ только через методы)
private String name;
private int age;
// Конструктор — инициализирует объект
public Person(String name, int age) {
this.name = name; // this — ссылка на текущий объект
this.age = age;
}
// Геттеры / сеттеры — контролируемый доступ к полям
public String getName() { return name; }
public void setAge(int age) {
if (age >= 0) this.age = age; // валидация
}
public String greet() {
return "Я " + name + ", мне " + age;
}
}
// Использование
Person p = new Person("Аня", 25); // new вызывает конструктор
p.getName(); // "Аня"
p.setAge(26);
p.greet(); // "Я Аня, мне 26"
10. Наследование и полиморфизм
// abstract — нельзя создать напрямую, только наследовать
abstract class Animal {
protected String name; // protected — виден потомкам
Animal(String name) { this.name = name; }
abstract String sound(); // абстрактный метод — без тела, потомок обязан реализовать
String describe() { return name + " говорит " + sound(); }
}
class Dog extends Animal { // extends — наследование
Dog(String name) { super(name); } // super — вызов конструктора родителя
@Override // аннотация: переопределяем метод родителя
String sound() { return "Гав"; }
}
class Cat extends Animal {
Cat(String name) { super(name); }
@Override String sound() { return "Мяу"; }
}
// Полиморфизм: один тип-ссылка — разное поведение
Animal a = new Dog("Рекс");
a.describe(); // "Рекс говорит Гав"
a = new Cat("Барсик");
a.describe(); // "Барсик говорит Мяу"
11. Интерфейсы
Контракт без состояния. Класс может реализовать несколько интерфейсов.
interface Drawable {
void draw(); // абстрактный метод (по умолчанию public abstract)
// default-метод — реализация по умолчанию (с Java 8)
default void clear() {
System.out.println("очищено");
}
}
interface Resizable {
void resize(double factor);
}
// implements — реализация интерфейса(ов), можно несколько через запятую
class Circle implements Drawable, Resizable {
double r = 1.0;
@Override public void draw() { System.out.println("○ r=" + r); }
@Override public void resize(double f) { r *= f; }
}
Drawable shape = new Circle();
shape.draw(); // ○ r=1.0
shape.clear(); // очищено (default-метод)
12. Исключения
Checked-исключения нужно объявлять/обрабатывать; unchecked (RuntimeException) — нет.
try {
int x = 10 / 0; // выбросит ArithmeticException (unchecked)
} catch (ArithmeticException e) {
System.out.println("Ошибка: " + e.getMessage()); // Ошибка: / by zero
} finally {
System.out.println("finally — выполнится всегда");
}
// Несколько catch + общий тип
try {
String s = null;
s.length(); // NullPointerException
} catch (NullPointerException | IllegalArgumentException e) {
System.out.println("поймано: " + e.getClass().getSimpleName());
}
// throw — выброс вручную; throws — объявление checked-исключения
static void check(int age) {
if (age < 0) throw new IllegalArgumentException("возраст < 0");
}
// checked-исключение нужно объявить через throws
static void read() throws java.io.IOException {
throw new java.io.IOException("нет файла");
}
// try-with-resources — авто-закрытие ресурса (AutoCloseable)
// try (var reader = new BufferedReader(...)) { ... } // close() вызовется сам
13. Дженерики и Stream API
import java.util.*;
import java.util.stream.*;
// --- Дженерики: параметризация типом <T> ---
class Box<T> { // T — параметр-тип
private T value;
void set(T v) { value = v; }
T get() { return value; }
}
Box<String> box = new Box<>();
box.set("привет");
box.get(); // "привет" — без приведения типов
// Дженерик-метод
static <T> T first(List<T> list) { return list.get(0); }
// --- Stream API: декларативная обработка коллекций ---
List<Integer> nums = List.of(1, 2, 3, 4, 5, 6);
// filter -> map -> collect
List<Integer> result = nums.stream()
.filter(n -> n % 2 == 0) // оставить чётные: 2,4,6
.map(n -> n * n) // возвести в квадрат: 4,16,36
.collect(Collectors.toList()); // [4, 16, 36]
// Свёртка к одному значению
int sum = nums.stream()
.mapToInt(Integer::intValue) // ссылка на метод
.sum(); // 21
// Прочие операции
nums.stream().count(); // 6
nums.stream().anyMatch(n -> n > 5); // true
nums.stream().sorted().findFirst().get(); // 1
String joined = nums.stream()
.map(String::valueOf)
.collect(Collectors.joining(", ")); // "1, 2, 3, 4, 5, 6"