RU | EN | DE

static

Purpose: Allows access to a field or method without creating an object of the class. Belongs to the class itself, not to a specific instance.

Usage:

  • Static constants (static final)
  • Utility methods (Math.max, Collections.sort)
  • Counters and factory methods

Example:

class Counter {
  static int count = 0; // shared for all objects
  public Counter() { count++; }
}
Counter c1 = new Counter();
Counter c2 = new Counter();
System.out.println(Counter.count); // 2

💡 Features:

  • static variables are created once when the class is loaded.
  • You cannot access this or super in a static method.
  • Often used for singleton and utility classes.

final

Purpose: Fixes a value or prevents modification.

Usage:

  • Variable → cannot be redefined.
  • Method → cannot be overridden in subclasses.
  • Class → cannot be inherited.

Examples:

final int MAX = 10; // constant
// MAX = 15; // error
final class Utils {} // cannot be inherited
class Parent {
  final void greet() { System.out.println("Hi"); }
}
class Child extends Parent {
  // void greet() {} // error — final method
}

💡 Tip: final is often combined with staticpublic static final = constant (e.g., Math.PI).

this

Purpose: Reference to the current object — used within methods or constructors.

Example:

class Person {
  private String name;
  public Person(String name) {
  this.name = name; // "this" distinguishes the field from the parameter
  }
  public void print() {
  System.out.println(this.name);
  }
}

💡 Features:

  • this() can be used to call another constructor in the same class:
public Person() {
  this("Default");
}
  • You cannot use this in static methods (because there is no instance).

super

Purpose: Used to refer to methods and constructors of the parent class.

Example:

class Animal {
  void speak() { System.out.println("Animal speaks"); }
}
class Dog extends Animal {
  void speak() {
  super.speak(); // calls the parent's method
  System.out.println("Dog barks");
  }
}

💡 Features:

  • super() must be the first line in a constructor.
  • Helps with overriding methods and initializing subclasses.

volatile

Purpose: Used for variables accessible from multiple threads. Ensures that all threads read the current value from memory, not from the CPU cache.

Example:

class FlagExample {
  private volatile boolean running = true;
  void stop() {
  running = false;
  }
  void run() {
  while (running) {
  // executes while running is not changed
  }
  }
}

💡 Without volatile, another thread may not see the changes to the variable, because it may be cached in the CPU. 📍 Use volatile if the variable does not depend on the previous state (e.g., a boolean flag).

transient

Purpose: Indicates that a field does not need to be serialized. When saving an object (e.g., to a file or network), this field will be skipped.

Example:

class User implements Serializable {
  private String username;
  private transient String password; // will not be serialized
}

💡 The transient field becomes null or 0 after deserialization. 📍 Used when working with Serializable and security (passwords, keys).

Difference between == and .equals()

ComparisonWhat it doesWhere it is used
==Compares references (memory addresses)Objects, primitives
.equals()Compares contentOverridden in classes (String, Integer, etc.)
Example:
String a = new String("hello");
String b = new String("hello");
 
System.out.println(a == b);  // false (different objects)
System.out.println(a.equals(b)); // true  (same content)

💡 For primitives, == compares values, for objects — references. 📍 Tip:

  • For strings, collections, and objects — always use .equals().
  • Always override equals() together with hashCode().

String, StringBuilder, StringBuffer

String

  • Immutable object.
  • Each concatenation creates a new object in memory.
String s = "Hello";
s += " World"; // a new object is created

📍 Used when the string does not change frequently. ⚠️ Avoid concatenating String in a loop — it creates a lot of garbage for GC.

StringBuilder

  • Mutable.
  • Not synchronized → faster, but not thread-safe.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Hello World

📍 Used in single-threaded operations.

StringBuffer

  • Almost the same as StringBuilder, but synchronized (thread-safe).
  • Slightly slower.
StringBuffer sb = new StringBuffer("Hi");
sb.append(" there");
System.out.println(sb);

📍 Used in multi-threaded environments when strings are edited concurrently from different threads.

🧩 Comparison

ClassMutabilityThread-safetySpeedWhen to use
String❌ immutable✅ safe🐢 slow with frequent changesStatic texts, keys
StringBuilder✅ mutable❌ no⚡ fastString generation, templates, loops
StringBuffer✅ mutable✅ yes⚖️ mediumIn multi-threaded environments

⚙️ Best practices

  • ✅ Use StringBuilder for concatenation in loops.
  • ✅ Never compare strings using ==, only .equals().
  • ✅ Make constants using public static final.
  • ✅ Apply volatile only when necessary for synchronization.
  • ✅ Remember: transient protects data during serialization.
  • ✅ Do not overuse static — it reduces testability.