← Назад к вопросам

Приведи пример final класса

1.0 Junior🔥 91 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Примеры final классов в Java

Отличный вопрос про одну из базовых концепций ООП! Final классы предотвращают наследование и важны для безопасности и производительности.

Что такое final класс?

Final класс - это класс, который НЕ может быть наследован. Если попытаешься создать подкласс, получишь ошибку компиляции:

// Пример 1: final класс
public final class ImmutableUser {
    private final String name;
    private final String email;

    public ImmutableUser(String name, String email) {
        this.name = name;
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public String getEmail() {
        return email;
    }
}

// Попытка наследования - ОШИБКА КОМПИЛЯЦИИ
public class PremiumUser extends ImmutableUser {  // ERROR: Cannot extend final class
    // ...
}

Примеры final классов из Java Standard Library

1. String - один из самых известных final классов:

public final class String implements Comparable<String>, ... {
    private final char[] value;
    // ...
}

// Почему final? Потому что String должен быть immutable (неизменяемый)
// Если кто-то создаст подкласс, может нарушить эту гарантию

// Попытка расширить String - ОШИБКА
class MyString extends String {  // ERROR: Cannot extend final class
    @Override
    public String toUpperCase() {
        // Злоумышленник может изменить поведение
    }
}

2. Integer, Long, Double, Boolean - все Wrapper классы final:

public final class Integer extends Number implements Comparable<Integer> {
    private final int value;
    // ...
}

public final class String implements CharSequence {
    // ...
}

public final class StringBuilder implements Appendable, CharSequence {
    // ...
}

Практические примеры для использования

1. Immutable (неизменяемые) классы:

public final class Money {
    private final BigDecimal amount;
    private final Currency currency;

    public Money(BigDecimal amount, Currency currency) {
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Amount must be positive");
        }
        this.amount = amount;
        this.currency = currency;
    }

    public Money add(Money other) {
        // Возвращает новый объект Money, не изменяет этот
        return new Money(amount.add(other.amount), currency);
    }

    public BigDecimal getAmount() {
        return amount;
    }
}

// Защита: никто не может создать подкласс и нарушить immutability
// Например, создать MutableMoney, который позволяет менять amount

2. Утилиты (Utility classes):

public final class MathUtils {
    private MathUtils() {
        // Запрет на инстанцирование
        throw new AssertionError("Cannot instantiate utility class");
    }

    public static int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }

    public static int lcm(int a, int b) {
        return (a * b) / gcd(a, b);
    }
}

// Final гарантирует, что никто не создаст подкласс типа AdvancedMathUtils

3. Конфигурационные объекты:

public final class DatabaseConfig {
    private final String host;
    private final int port;
    private final String database;
    private final String username;
    // password не хранится в памяти!

    public DatabaseConfig(String host, int port, String database, String username) {
        this.host = host;
        this.port = port;
        this.database = database;
        this.username = username;
    }

    public String getConnectionUrl() {
        return String.format("jdbc:postgresql://%s:%d/%s", host, port, database);
    }

    public String getUsername() {
        return username;
    }
}

// Final защищает конфиг от подделок
final class FakeConfig extends DatabaseConfig {  // ERROR
    @Override
    public String getConnectionUrl() {
        return "jdbc:postgresql://attacker.com/database";
    }
}

Разница: final класс vs final методы vs final поля

// 1. final класс - нельзя наследовать
public final class MyClass {
    // ...
}

// 2. final метод - нельзя переопределять
public class Parent {
    public final void importantMethod() {
        // Это поведение не должно изменяться
    }
}

public class Child extends Parent {
    @Override
    public void importantMethod() {  // ERROR: Cannot override final method
        // ...
    }
}

// 3. final поле - нельзя менять значение
public class Config {
    public final String DATABASE_URL = "jdbc:postgresql://localhost:5432/db";
}

Config config = new Config();
config.DATABASE_URL = "other-url"; // ERROR: Cannot assign to final field

Когда использовать final класс?

ДА - используй final для:

  • Immutable классов (String, BigDecimal, Money, Date, UUID)
  • Value Objects (классы, которые просто хранят значения)
  • Безопасности (защита от подделок в security-critical коде)
  • Производительности (JVM может оптимизировать final классы)
public final class UUID {
    private final long mostSigBits;
    private final long leastSigBits;
    // ...
}

public final class Date {
    private final long fastTime;
    // ...
}

НЕТ - избегай final для:

  • Абстрактных классов (они создаются для наследования)
  • Framework классов (Spring, Hibernate, JUnit)
  • Base классов, которые рассчитаны на расширение
// Плохо - ограничиваешь возможности разработчиков
public final class BaseEntity {
    private Long id;
    // ...
}

// Хорошо - allow для расширения
public class BaseEntity {
    private Long id;
    // ...
}

Производительность

JVM оптимизирует final классы:

// Final класс - JVM знает, что больше никто не переопределит методы
public final class OptimizedClass {
    public void doWork() {
        // JVM может inline это напрямую без проверки виртуальной таблицы
    }
}

Без final JVM должна проверить таблицу методов, есть ли подклассы с переопределением.

Вывод

Final класс - это инструмент для:

  • Защиты инвариантов (особенно в immutable классах)
  • Безопасности (предотвращение нежелательных подклассов)
  • Производительности (JVM может лучше оптимизировать)
  • Ясности намерений (показывает, что класс не рассчитан на наследование)

Примеры из JDK: String, Integer, Long, Double, BigDecimal, UUID, LocalDate, Collections - все используют final для защиты immutability.

Приведи пример final класса | PrepBro