static
Назначение:
Позволяет обращаться к полю или методу без создания объекта класса.
Принадлежит самому классу, а не конкретному экземпляру.
Применение:
- Общие константы (
static final) - Вспомогательные методы (
Math.max,Collections.sort) - Счётчики и фабричные методы
Пример:
class Counter {
static int count = 0; // общее для всех объектов
public Counter() { count++; }
}
Counter c1 = new Counter();
Counter c2 = new Counter();
System.out.println(Counter.count); // 2💡 Особенности:
staticпеременные создаются один раз при загрузке класса.- В
staticметоде нельзя обращаться кthisилиsuper. - Часто используется для singleton и utility классов.
final
Назначение:
Фиксирует значение или запрещает изменение поведения.
Применение:
- Переменная → нельзя переопределить значение.
- Метод → нельзя переопределить в наследнике.
- Класс → нельзя наследовать.
Примеры:
final int MAX = 10; // константа
// MAX = 15; // ошибка
final class Utils {} // нельзя наследовать
class Parent {
final void greet() { System.out.println("Hi"); }
}
class Child extends Parent {
// void greet() {} // ошибка — метод final
}💡 Совет:
final часто комбинируют со static → public static final = константа (например, Math.PI).
this
Назначение:
Ссылка на текущий объект — используется внутри методов или конструкторов.
Пример:
class Person {
private String name;
public Person(String name) {
this.name = name; // "this" отличает поле от параметра
}
public void print() {
System.out.println(this.name);
}
}💡 Особенности:
this()можно использовать для вызова другого конструктора в том же классе:
public Person() {
this("Default");
}- Нельзя использовать
thisвstaticметодах (так как нет экземпляра).
super
Назначение:
Используется для обращения к методам и конструкторам родительского класса.
Пример:
class Animal {
void speak() { System.out.println("Animal speaks"); }
}
class Dog extends Animal {
void speak() {
super.speak(); // вызов метода родителя
System.out.println("Dog barks");
}
}💡 Особенности:
super()должен быть первой строкой в конструкторе.- Помогает при override методов и при инициализации наследников.
volatile
Назначение:
Используется для переменных, доступных из нескольких потоков.
Гарантирует, что все потоки читают актуальное значение из памяти, а не из кэша процессора.
Пример:
class FlagExample {
private volatile boolean running = true;
void stop() {
running = false;
}
void run() {
while (running) {
// выполняется, пока running не изменится
}
}
}💡 Без volatile другой поток может не увидеть изменения переменной,
поскольку она может быть закэширована в CPU.
📍 Используй volatile, если переменная не зависит от предыдущего состояния (например, boolean-флаг).
transient
Назначение:
Указывает, что поле не нужно сериализовать.
При сохранении объекта (например, в файл или по сети) это поле будет пропущено.
Пример:
class User implements Serializable {
private String username;
private transient String password; // не будет сериализовано
}💡 Поле transient после десериализации становится null или 0.
📍 Применяется при работе с Serializable и безопасностью (пароли, ключи).
Разница между == и .equals()
| Сравнение | Что делает | Где используется |
|---|---|---|
== | Сравнивает ссылки (адреса в памяти) | Объекты, примитивы |
.equals() | Сравнивает содержимое | Переопределяется в классах (String, Integer, и др.) |
| Пример: |
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false (разные объекты)
System.out.println(a.equals(b)); // true (одинаковое содержимое)💡 Для примитивов == сравнивает значения, для объектов — ссылки
📍 Совет:
- Для строк, коллекций и объектов — всегда используй
.equals(). - Переопределяй
equals()всегда вместе сhashCode().
String, StringBuilder, StringBuffer
String
- Неизменяемый (immutable) объект.
- Каждая операция конкатенации создаёт новый объект в памяти.
String s = "Hello";
s += " World"; // создаётся новый объект📍 Используется, когда строка не меняется часто.
⚠️ Избегай конкатенации String в цикле — создаётся много мусора для GC.
StringBuilder
- Изменяемый (mutable).
- Не синхронизирован → быстрее, но не потокобезопасен.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Hello World📍 Используется в однопоточных операциях.
StringBuffer
- Почти то же, что
StringBuilder, но синхронизирован (потокобезопасен). - Немного медленнее.
StringBuffer sb = new StringBuffer("Hi");
sb.append(" there");
System.out.println(sb);📍 Используется в многопоточной среде, когда строки редактируются одновременно из разных потоков.
🧩 Сравнение
| Класс | Изменяемость | Потокобезопасность | Скорость | Когда использовать |
|---|---|---|---|---|
String | ❌ immutable | ✅ безопасен | 🐢 медленный при частых изменениях | Статичные тексты, ключи |
StringBuilder | ✅ mutable | ❌ нет | ⚡ быстрый | Генерация строк, шаблоны, циклы |
StringBuffer | ✅ mutable | ✅ да | ⚖️ средний | При многопоточности |
⚙️ Best practices
- ✅ Используй
StringBuilderдля конкатенации в циклах. - ✅ Не сравнивай строки через
==, только.equals(). - ✅ Делай константы через
public static final. - ✅ Применяй
volatileтолько при необходимости синхронизации. - ✅ Помни:
transientзащищает данные при сериализации. - ✅ Не злоупотребляй
static— это уменьшает тестируемость.