Ответ
Поверхностное копирование (Shallow Copy) создает новый объект, но копирует в него ссылки на те же вложенные объекты, что и оригинал. Глубокое копирование (Deep Copy) создает полностью независимую копию, рекурсивно копируя все вложенные объекты.
Различия:
| Аспект | Поверхностное копирование | Глубокое копирование |
|---|---|---|
| Вложенные объекты | Копируются ссылки | Создаются новые объекты |
| Зависимость | Изменения вложенных объектов видны в обеих копиях | Копии полностью независимы |
| Сложность/стоимость | Быстрое, мало памяти | Медленное, больше памяти |
Пример:
class Engine { int power; }
class Car {
String model;
Engine engine; // Вложенный объект
}
Car original = new Car("Sedan", new Engine(150));
// Поверхностная копия (например, через Object.clone())
Car shallowCopy = original.clone();
shallowCopy.engine.power = 200; // Меняет двигатель и у original!
// Глубокая копия (требует ручной реализации)
Car deepCopy = new Car(original.model, new Engine(original.engine.power));
deepCopy.engine.power = 250; // Не влияет на original
Как создать:
- Shallow copy: метод
Object.clone()(если класс реализуетCloneable). - Deep copy: ручное копирование конструкторами, сериализацией или библиотеками (Apache Commons,
ObjectMapper).
Ответ 18+ 🔞
Да ты посмотри, какая красота, блядь! Придумали же, сука, в Java 8, чтобы старые интерфейсы не ломать, как гнилую избу, когда новую пристройку делаешь. Вот эти default-методы — это ж гениально, ёпта!
Раньше-то, если в интерфейс новый метод сунешь, так все, кто его реализовывал, — пиздец, нахуй, компилятор на каждом углу орет, как резаный. А теперь взяли, и говорят: «А давайте сделаем метод с готовой реализацией прямо в интерфейсе!». И назвали это default. И жить стало проще, блядь.
А static-методы в интерфейсах — это вообще отдельная песня. Раньше для утилиток отдельный класс-помойку заводили, а теперь можно прямо в интерфейсе их приткнуть, красиво, удобно. Не надо плодить сущностей, как блох на бродячей собаке.
Вот смотри, табличка, чтобы в голове не еблось:
| Признак | default метод |
static метод |
|---|---|---|
| Кому принадлежит | Каждой конкретной тачке (объекту) | Самому интерфейсу, как начальнику цеха |
| Наследуется ли | Да, и его можно переписать, если не нравится | Ни хуя, он сам по себе, как кот, который гуляет |
| Как вызвать | Через объект: myCar.honk() |
Через имя интерфейса: Vehicle.isValidSpeed(50) |
| Зачем придуман | Чтобы старый код не взрывался, когда интерфейс растет | Чтобы удобные функции рядом лежали, а не по всему проекту разбросаны |
А вот живой пример, чтобы вообще всё встало на свои места, блядь:
interface Vehicle {
// Ну это обычный метод, который все обязаны реализовать
void start();
// А это — default-метод. Хочешь — используй как есть, хочешь — перепиши под себя.
default void honk() {
System.out.println("Beep beep!");
}
// А это static-метод. Общая проверка для всех, кто про скорость спросит.
static boolean isValidSpeed(int speed) {
return speed >= 0;
// Отрицательную скорость, блядь, не предлагать!
}
}
class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car started");
}
// Метод honk() можем оставить дефолтным, а можем и свой гудок придумать.
}
// Использование на практике:
Car myCar = new Car();
myCar.start(); // Выведет: Car started
myCar.honk(); // Выведет: Beep beep! (работает дефолтная реализация)
boolean valid = Vehicle.isValidSpeed(50); // true (вызов статического метода)
boolean invalid = Vehicle.isValidSpeed(-10); // false (пиздец, куда ты гонишь?)
Вот и вся магия, блядь. default — чтобы не ломать старое, static — чтобы не плодить лишних классов. Красота, в рот меня чих-пых! Главное — не путать, а то получится мартышлюшка, а не код.