RU | EN | DE

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 часто комбинируют со staticpublic 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 — это уменьшает тестируемость.