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

Какие методы переходят от Object по наследованию?

1.3 Junior🔥 231 комментариев
#ООП

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

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

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

Методы класса Object в Java

Все классы в Java наследуют методы из класса java.lang.Object. Это фундаментальный класс, от которого наследуются все остальные классы по умолчанию. Давайте рассмотрим все методы, которые переходят по наследованию.

1. equals(Object obj) — сравнение объектов

public class Person {
    private String name;
    private int age;
    
    // По умолчанию Object.equals() сравнивает по ссылке (==)
    // Нужно переопределить для сравнения по значению
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;  // Проверка по ссылке
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Person person = (Person) obj;
        return age == person.age && 
               Objects.equals(name, person.name);
    }
}

public class Example {
    public static void main(String[] args) {
        Person p1 = new Person("John", 30);
        Person p2 = new Person("John", 30);
        
        System.out.println(p1 == p2);          // false (разные объекты в памяти)
        System.out.println(p1.equals(p2));     // true (одинаковые значения)
    }
}

Важно: При переопределении equals() ВСЕГДА переопределяй и hashCode()!

2. hashCode() — получить хеш-код объекта

public class Person {
    private String name;
    private int age;
    
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
    
    @Override
    public boolean equals(Object obj) {
        // ...
    }
}

public class Example {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        System.out.println(person.hashCode());
        
        // Использование в HashMap
        Map<Person, String> map = new HashMap<>();
        map.put(person, "Developer");
    }
}

Контракт: Если a.equals(b) возвращает true, то a.hashCode() == b.hashCode().

3. toString() — строковое представление объекта

public class Person {
    private String name;
    private int age;
    
    @Override
    public String toString() {
        return String.format("Person(name='%s', age=%d)", name, age);
    }
}

public class Example {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        System.out.println(person);  // Person(name='John', age=30)
        System.out.println(person.toString());  // То же самое
    }
}

По умолчанию возвращает что-то вроде Person@1f96302c (класс + хеш).

4. getClass() — получить класс объекта (FINAL метод)

public class Example {
    public static void main(String[] args) {
        Person person = new Person("John", 30);
        
        Class<?> personClass = person.getClass();
        System.out.println(personClass.getName());       // Person
        System.out.println(personClass.getSimpleName()); // Person
        
        // Проверка типа
        if (person.getClass() == Person.class) {
            System.out.println("Это экземпляр Person");
        }
        
        // Рефлексия
        Method[] methods = personClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
    }
}

Этот метод нельзя переопределить (final).

5. clone() — создать копию объекта

public class Person implements Cloneable {
    private String name;
    private List<String> hobbies;
    
    @Override
    public Object clone() throws CloneNotSupportedException {
        // Поверхностное копирование
        Person cloned = (Person) super.clone();
        
        // Для изменяемых полей нужно глубокое копирование
        cloned.hobbies = new ArrayList<>(this.hobbies);
        
        return cloned;
    }
}

public class Example {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person original = new Person("John", Arrays.asList("Reading", "Coding"));
        Person cloned = (Person) original.clone();
        
        System.out.println(original == cloned);  // false (разные объекты)
        System.out.println(original.equals(cloned));  // true (если переопределено)
    }
}

Важно: Класс ДОЛЖЕН реализовать интерфейс Cloneable, иначе выбросится CloneNotSupportedException.

6. finalize() — подготовка к удалению (DEPRECATED)

public class Resource implements AutoCloseable {
    private FileInputStream fileInputStream;
    
    // DEPRECATED! Не используй в новом коде
    @Override
    @Deprecated(since = "9", forRemoval = true)
    protected void finalize() throws Throwable {
        try {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        } finally {
            super.finalize();
        }
    }
    
    // Предпочитай AutoCloseable
    @Override
    public void close() throws Exception {
        if (fileInputStream != null) {
            fileInputStream.close();
        }
    }
}

public class Example {
    public static void main(String[] args) {
        // Используй try-with-resources вместо finalize()
        try (Resource resource = new Resource()) {
            // Работа с ресурсом
        }  // Автоматически вызовется close()
    }
}

Рекомендация: Используй AutoCloseable и try-with-resources вместо finalize().

7. wait(), notify(), notifyAll() — синхронизация потоков

public class Message {
    private String content;
    private boolean isReady = false;
    
    public synchronized void produce(String msg) throws InterruptedException {
        while (isReady) {
            wait();  // Ждём, пока consumer заберёт сообщение
        }
        this.content = msg;
        this.isReady = true;
        notifyAll();  // Пробуждаем ждущие потоки
    }
    
    public synchronized String consume() throws InterruptedException {
        while (!isReady) {
            wait();  // Ждём, пока producer создаст сообщение
        }
        String msg = content;
        isReady = false;
        notifyAll();  // Пробуждаем ждущие потоки
        return msg;
    }
}

public class Example {
    public static void main(String[] args) throws InterruptedException {
        Message message = new Message();
        
        Thread producer = new Thread(() -> {
            try {
                message.produce("Hello from producer!");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        Thread consumer = new Thread(() -> {
            try {
                String msg = message.consume();
                System.out.println(msg);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        producer.start();
        consumer.start();
        producer.join();
        consumer.join();
    }
}

Современный подход — используй java.util.concurrent:

public class ModernExample {
    public static void main(String[] args) throws InterruptedException {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>();
        
        Thread producer = new Thread(() -> {
            try {
                queue.put("Message");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        Thread consumer = new Thread(() -> {
            try {
                String msg = queue.take();
                System.out.println(msg);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        producer.start();
        consumer.start();
    }
}

Полный список методов Object

public final class Object {
    public native int hashCode();                     // Хеш-код
    public boolean equals(Object obj);                // Сравнение
    protected native Object clone() throws CloneNotSupportedException;  // Копирование
    public String toString();                         // Строковое представление
    public final Class<?> getClass();                 // Получить класс
    
    protected void finalize() throws Throwable;       // (DEPRECATED) Финализация
    public final void notify();                       // Разбудить один поток
    public final void notifyAll();                    // Разбудить все потоки
    public final void wait() throws InterruptedException;           // Ждать
    public final void wait(long timeout) throws InterruptedException;
    public final void wait(long timeout, int nanos) throws InterruptedException;
}

Практические рекомендации

  1. Всегда переопределяй equals() и hashCode() вместе

    • Используй IDE для автогенерации
    • Или используй @Data в Lombok
  2. Переопределяй toString() для отладки

    // IDE может автогенерировать
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    
  3. Избегай clone() если возможно

    • Используй конструктор копирования
    • Или copy factory method
    • Или builder pattern
  4. Используй java.util.concurrent вместо wait()/notify()

    • BlockingQueue, ReentrantLock, Semaphore и т.д.
  5. Никогда не переопределяй getClass()

    • Это final метод, нельзя переопределить