Чи є деструктор для Java?


594

Чи є деструктор для Java? Я не можу знайти жодної документації на це. Якщо цього немає, як я можу досягти такого ж ефекту?

Щоб зробити моє запитання більш конкретним, я пишу заявку, яка займається даними, і специфікація каже, що повинна бути кнопка "скидання", яка повертає програму у початковий стан, щойно запущений. Однак усі дані мають бути "живими", якщо програма не закрита або не натиснуто кнопку скидання.

Будучи звичайно програмістом на C / C ++, я думав, що це було б банально. (А значить, я планував його впровадити останнім часом.) Структурував свою програму таким чином, що всі об’єкти, які можуть бути скинуті, будуть у тому ж класі, що я можу просто знищити всі "живі" об'єкти при натисканні кнопки скидання.

Я думав, якщо все, що я робив, - це просто знецінити дані та дочекатися збирання сміття, чи не відбудеться витік пам'яті, якби мій користувач неодноразово вводив дані та натискав кнопку скидання? Я також думав, оскільки Java досить зріла як мова, повинен бути спосіб запобігти цьому чи витончено вирішити це.


7
Існує витік пам'яті, лише якщо ви зберігаєте посилання на об'єкти, які вам не потрібні. тобто є помилка у вашій програмі. GC працюватиме як потрібно (іноді швидше)
Пітер Лоурі

17
Віртуальна машина не запустить GC досить швидко, якщо ви швидко обробляєте дані через об'єкти. Ідея, що GC завжди може бути в курсі, або приймати правильні рішення, є помилкою.
Kieveli

1
@Kieveli Не став би JVM запускати GC до помилки?
WVrock

4
Так, було б добре, якби на Java був деструктор, який знищив би її раз і назавжди.
Томаш Зато - Відновіть Моніку

Відповіді:


526

Оскільки Java - це зібрана сміття мова, ви не можете передбачити, коли (або навіть якщо) об'єкт буде знищений. Отже, немає прямого еквівалента деструктора.

Існує успадкований метод, який називається finalize, але це називається цілком на розсуд сміттєзбірника. Отже, для класів, які потрібно чітко налагодити, умовою є визначення методу закриття та використання остаточного лише для перевірки правильності (тобто якщо закриття ще не було викликано, зробіть це зараз і введіть помилку).

Виникло питання, яке нещодавно породило глибоке обговорення остаточного завершення , щоб воно могло забезпечити більшу глибину, якщо потрібно ...


5
Чи в цьому контексті "close ()" посилається на метод у java.lang.Autocloseable?
Шрідхар Сарнобат

21
Ні, в системі Java 7 було введено функцію автоматичного зачинення, але умова "close ()" існувала набагато довше.
Джон Онстотт

чому ви не можете передбачити, коли (або навіть якщо) об'єкт буде знищений. який приблизний інший спосіб передбачити це?
dctremblay

Знищення об'єкта @dctremblay здійснюється сміттєзбірником, і сміттєзбірник ніколи не може працювати за весь час застосування.
Піро каже: Відновити Моніку

4
Зверніть увагу , що finalizeметод є застарілим в Java 9.
Lii

124

Погляньте на заяву про використання ресурсів . Наприклад:

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  System.out.println(br.readLine());
} catch (Exception e) {
  ...
} finally {
  ...
}

Тут ресурс, який більше не потрібен, звільняється в BufferedReader.close()методі. Ви можете створити власний клас, який реалізує AutoCloseableта використовує його аналогічно.

Це твердження є більш обмеженим, ніж finalizeв частині структуризації коду, але в той же час він робить код простішим для розуміння та підтримки. Також немає гарантії того, що finalizeметод взагалі викликається під час роботи програми.


12
Я здивований, що так мало голосів. Це фактична відповідь.
Нуреттін

20
Я не згоден, що це фактична відповідь. Якщо в примірнику є ресурс, який він обробляє протягом більшого періоду часу, за допомогою декількох викликів методів, тестування ресурсів не допоможе. Якщо тільки не нормально закривати та повторно відкривати згаданий ресурс швидкістю, за допомогою якої називаються методи - не загальний факт.
Ерік

14
Дійсно, це не справжня відповідь. Неможливо використовувати цю структуру для управління знищенням об'єкта, якщо конструкція та використання об'єкта повністю не інкапсульована tryі finallyне використовується для примусового виклику obj.finalize(). І навіть ця настройка не вирішує проблему, яку постає ОП: знищення об'єкта середньої програми, викликане кнопкою "скидання".
7yl4r

1
Інші користувачі показали, що це робиться у точці входу вашої програми. Визначте свою змінну глобально. Ініціалізуйте його у функції введення, спробуйте. Дезініціалізуйтесь остаточно (коли ваша заявка закриється). Це цілком можливо.
TamusJRoyce

1
@nurettin Java 7 існував лише 3 місяці, коли було задано питання, якщо це допоможе зрозуміти її більше.
corsiKa

110

Ні, тут деструкторів немає. Причина в тому, що всі об’єкти Java виділяються купою і збираються сміття. Без явного делокації (тобто оператора видалення C ++) немає розумного способу впровадження реальних деструкторів.

Java підтримує фіналізатори, але вони покликані використовуватись лише як захист для об'єктів, що тримають ручку до власних ресурсів, таких як сокети, ручки файлів, віконні ручки тощо. Коли збирач сміття збирає об'єкт без фіналізатора, він просто відзначає пам'ять регіон як вільний, і все. Коли об’єкт має фіналізатор, він спочатку копіюється у тимчасове місце (пам’ятайте, ми тут збираємо сміття), потім він вкладається в чергу очікування, яка буде завершена, а потім нитка Finalizer опитує чергу з дуже низьким пріоритетом і запускає фіналізатор.

Коли програма закривається, JVM зупиняється, не чекаючи, коли очікувані об'єкти будуть доопрацьовані, тому практично немає гарантій того, що ваші фіналізатори ніколи не працюватимуть.


4
Дякую, що згадали про місцеві ресурси - це одна сфера, в якій корисний метод, що нагадує деструктор.
Натан Осман

так, я зараз стикаюся з тією самою проблемою, коли вивільнення ресурсів / ручок, що виділяються за допомогою власних дзвінків на C ++.
nikk

@ddimitrov, теоретично міг би Java реалізувати явну угоду? Або це логічне протиріччя?
міл

1
@mils, що наївно реалізує явну транслокацію, може або порушити припущення Java про те, що будь-які орієнтири вказують на живий об'єкт. Ви можете повторити всі вказівники та скасувати псевдоніми, але це дорожче, ніж GC. Або ви можете спробувати скористатися якоюсь лінійною системою типу (див. "Власність" у Rust), але це суттєва зміна мови. Існують і інші варіанти (див. Пам'ять, на якій розміщено JavaRT тощо), але в цілому явна транслокація не дуже відповідає мові Java.
ddimitrov

31

Використання фіналізації () методу слід уникати. Вони не є надійним механізмом очищення ресурсів, і можливо викликати проблеми у сміттєзбірнику, зловживаючи ними.

Якщо вам потрібен виклик транслокації у вашому об’єкті, скажімо, щоб звільнити ресурси, використовуйте явний виклик методу. Цю умову можна побачити в існуючих API (наприклад, Closeable , Graphics.dispose () , Widget.dispose () ) і зазвичай викликається через try / last .

Resource r = new Resource();
try {
    //work
} finally {
    r.dispose();
}

Спроби використовувати розміщений об'єкт повинні викидати виняток із виконання (див. IllegalStateException ).


Редагувати:

Я думав, якби все, що я робив, було лише зняти дані та дочекатися, коли збирач сміття збирає їх, чи не відбудеться витік пам'яті, якби мій користувач неодноразово вводив дані та натискав кнопку скидання?

Взагалі, все, що вам потрібно зробити, - це знеструмлення об'єктів - принаймні, це так, як він повинен працювати. Якщо ви турбуєтесь про збирання сміття, перегляньте настройку Java-6 HotSpot [tm] Налаштування сміття для віртуальної машини (або еквівалентний документ для вашої версії JVM).


1
Це не те, що означає дереференція. Це не "встановлення останньої посилання об'єкта на нуль", а скоріше отримання (зчитування) значення з посилання, щоб ви могли використовувати його для наступних операцій.

1
Постарайтеся .. остаточно дієвий і рекомендований підхід? Припустимо, я раніше викликав нативний метод у finalize (), чи можу я перенести виклик до остаточного пункту? class Resource { finalize() { destroy(); } protected native void destroy(); } class Alt_Resource { try (Resource r = new Resource()) { // use r } finalize { r.destroy(); }
аашима

r не потрапив би до остаточного блоку. Тому ви не можете викликати знищення в цей момент. Тепер, якщо ви виправите область для створення об'єкта до блоку спробу, ви закінчитеся некрасивим випадком "перед пробними ресурсами".
користувачAsh

21

З випущеною Java 1.7, тепер у вас є додаткова можливість використання try-with-resourcesблоку. Наприклад,

public class Closeable implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("closing..."); 
    }
    public static void main(String[] args) {
        try (Closeable c = new Closeable()) {
            System.out.println("trying..."); 
            throw new Exception("throwing..."); 
        }
        catch (Exception e) {
            System.out.println("catching..."); 
        }
        finally {
            System.out.println("finalizing..."); 
        } 
    }
}

Якщо ви виконуєте цей клас, c.close()він буде виконуватися, коли tryблок залишиться, і перед тим, як catchі finallyблоки будуть виконані. На відміну від finalize()методу, close()він гарантовано виконаний. Однак немає необхідності виконувати це чітко в finallyпункті.


що робити, якщо ми не використовували блок "пробні ресурси"? Я думаю, що ми можемо зателефонувати закрити в finalize () лише для того, щоб переконатися, що закриття було викликано.
shintoZ

3
@shintoZ, як я читав у відповідях вище, немає гарантії finalize()виконання
Асиф Муштак,

14

Я повністю погоджуюся з іншими відповідями, кажучи не покладатися на виконання завершення.

На додаток до блоків спробу-catch-нарешті, ви можете використовувати Runtime # addShutdownHook (представлений у Java 1.3) для виконання остаточних очищень у вашій програмі.

Це не те саме, що є деструктори , але можна реалізувати гак відключення, маючи зареєстровані слухацькі об’єкти, на яких можуть бути використані методи очищення (закрити стійкі підключення до бази даних, видалити блокування файлів тощо) - речі, які зазвичай роблять у деструктори . Знову ж таки - це не заміна деструкторів, але в деяких випадках ви можете підійти до потрібного функціоналу.

Перевагою цього є те, що поведінка деконструкції слабко поєднується з рештою програми.


addShutdownHook, очевидно, був представлений в Java 1.3. У всякому разі, він доступний мені в 1.5. :) Дивіться це: stackoverflow.com/questions/727151 / ...
skiphoppy

1
FYI, на мій досвід, гачки вимкнення не будуть викликатися, якщо ви використовуєте червону кнопку "завершити" в Eclipse - весь JVM знищується негайно, гачки вимкнення витончено не викликаються. Це означає, що ви можете побачити різну поведінку під час розвитку та виробництва, якщо розвинетесь із використанням затемнення
Хамі

11

Ні, java.lang.Object#finalizeце найближче ви можете дістати.

Однак, коли (і якщо вона) називається, це не гарантується.
Подивитися:java.lang.Runtime#runFinalizersOnExit(boolean)


5
Метод, який можна або не може викликати, в моїй книзі фактично марний. Краще було б не забруднювати мову марним спеціальним методом, який у кращому випадку дає помилкове відчуття безпеки. Я ніколи не зрозумію, чому розробники язикової мови на думці завершилися гарною ідеєю.
antred

@antred Розробники мови Java згодні . Я думаю, тоді для деяких з них це було вперше розроблено мову програмування та середовище виконання під час збирання сміття. Що менш зрозуміло - це те, що інша керована мова скопіювала це поняття в той час, коли вже було зрозуміло, що це поняття є поганою ідеєю.
Холгер

7

По-перше, зауважте, що оскільки Java збирає сміття, рідко потрібно щось робити щодо знищення об'єктів. По-перше, тому що у вас зазвичай немає жодних керованих ресурсів, щоб звільнити, а по-друге, тому, що ви не можете передбачити, коли або якщо це станеться, тому це недоцільно для речей, які вам повинні відбуватися ", як тільки ніхто більше не використовує мій об'єкт ".

Ви можете отримувати сповіщення після того, як об’єкт був знищений за допомогою java.lang.ref.PhantomReference (насправді, кажучи, що він був знищений, може бути злегка неточним, але якщо фантомне посилання на нього в черзі, воно більше не підлягає відновленню, що зазвичай становить Те ж саме). Поширене використання:

  • Відокремте ресурси (-и) вашого класу, які потрібно знищити в інший помічний об’єкт (зауважте, що якщо все, що ви робите, це закриття з'єднання, що є звичайним випадком, вам не потрібно писати новий клас: з'єднання, яке має бути закритим, було б "об’єктом-помічником" у цьому випадку).
  • Створюючи свій основний об'єкт, створіть також PhantomReference до нього. Або зверніться до цього нового об’єкта-помічника, або встановіть карту з об'єктів PhantomReference до відповідних їм помічників.
  • Після того, як основний об’єкт буде зібраний, PhantomReference ставиться в чергу (вірніше, він може бути в черзі - як і у фіналізаторів, немає жодної гарантії, що він коли-небудь буде, наприклад, якщо VM вийде, то він не чекатиме). Переконайтесь, що ви обробляєте її чергу (або спеціальною темою, або час від часу). Через жорстке посилання на хелперний об’єкт, хелперний об’єкт ще не зібраний. Тому виконайте будь-яке очищення на помічнику об'єкта, тоді відмовтеся від PhantomReference і помічник з часом теж буде зібраний.

Існує також finalize (), який виглядає як деструктор, але не веде себе як один. Зазвичай це не гарний варіант.


Чому PhantomReference замість WeakReference?
uckelman

2
@uckelman: якщо все, що ви хочете, це повідомлення, то PhantomReference виконує цю роботу, це майже все, для чого він призначений. Тут не потрібна додаткова семантика WeakReference, і в точці, де повідомляється про вашу ReferenceQueue, ви більше не можете відновити об'єкт через WeakReference, тому єдиною причиною його використання є збереження необхідності пам'ятати, що PhantomReference існує. Будь-яка додаткова робота, яку робить WeakReference, мабуть, незначна, але чому це турбуватися?
Стів Джессоп

Дякую за натяк на PhantomReference. Це не ідеально, але все-таки краще, ніж нічого.
foo

@SteveJessop, яка «додаткова робота», на вашу думку, має слабке посилання порівняно з посиланням на фантом?
Холгер

6

finalize()Функція деструктор.

Однак його не слід використовувати звичайно, оскільки він викликається після GC, і ви не можете сказати, коли це станеться (якщо це буде).

Більше того, для розміщення об'єктів, які є, потрібно більше ніж один GC finalize().

Вам слід спробувати прибрати в логічних місцях вашого коду, використовуючи try{...} finally{...}оператори!


5

Я згоден з більшістю відповідей.

Ви не повинні залежати повністю від яких finalizeабоShutdownHook

доопрацювати

  1. JVM не гарантує, коли finalize()буде застосовано цей метод.

  2. finalize()називається лише один раз GC потоком. Якщо об'єкт відроджується від методу доопрацювання, він finalizeбільше не буде викликаний.

  3. У вашій заявці у вас можуть бути живі об’єкти, на які ніколи не викликається сміття.

  4. ExceptionПотік GC ігнорується будь- яким викинутим методом завершення

  5. System.runFinalization(true)і Runtime.getRuntime().runFinalization(true)методи збільшують ймовірність виклику finalize()методу, але тепер ці два методи застаріли. Ці способи є дуже небезпечними через відсутність безпеки потоку та можливе створення тупикового каналу.

shutdownHooks

public void addShutdownHook(Thread hook)

Реєструє новий гак відключення віртуальної машини.

Віртуальна машина Java вимикається у відповідь на два види подій:

  1. Програма завершується нормально, коли виходить останній недемонний потік або коли System.exitвикликається метод (еквівалентно ), або
  2. Віртуальна машина припиняється у відповідь на перерву користувача, наприклад, набравши ^ C, або на загальносистемну подію, наприклад, вихід із системи користувача або вимкнення системи.
  3. Гак відключення - це просто ініціалізована, але не запущена нитка. Коли віртуальна машина розпочне свою послідовність відключення, вона запустить усі зареєстровані гачки відключення в певному невстановленому порядку і дозволить їм працювати одночасно. Коли всі гачки закінчені, він запускатиме всі незвані фіналізатори, якщо фіналізація при виході була включена.
  4. Нарешті віртуальна машина зупиниться. Зауважте, що потоки демона продовжуватимуться працювати під час послідовності відключення, як і недемонові потоки, якщо завершення роботи було ініційовано методом виходу.
  5. Гачки відключення також повинні швидко закінчити свою роботу. Коли програма викликає вихід, очікується, що віртуальна машина негайно вимкнеться та вийде.

    Але навіть документація Oracle цитувала це

У рідкісних випадках віртуальна машина може перерватись, тобто перестати працювати без чистого вимикання

Це відбувається, коли віртуальну машину припиняють зовні, наприклад, SIGKILLсигнал на Unix або TerminateProcessвиклик в Microsoft Windows. Віртуальна машина може також перервати, якщо нативний метод скажеться, наприклад, пошкодивши внутрішні структури даних або намагаючись отримати доступ до неіснуючої пам'яті. Якщо віртуальна машина скасовує, то гарантії щодо того, чи будуть запускатися гачки відключення, не можна давати.

Висновок : використовуйте try{} catch{} finally{}блоки належним чином і вивільнюйте критичні ресурси в finally(}блоці. Під час вивільнення ресурсів у finally{}блоці, вилову Exceptionта Throwable.


4

Якщо ви переживаєте лише про пам'ять, не варто. Просто довіряйте GC, вона робить гідну роботу. Я насправді бачив, що щось настільки ефективно, що для продуктивності може бути краще створити купу крихітних об'єктів, ніж використовувати великі масиви в деяких випадках.


3

Можливо, ви можете скористатися спробу ... нарешті заблокувати для остаточного завершення роботи об'єкта в потоці управління, в якому ви використовуєте об'єкт. Звичайно, це не відбувається автоматично, але знищення в C ++ також не відбувається. Ви часто бачите закриття ресурсів в остаточному блоці.


1
Це правильна відповідь, коли у відповідного ресурсу є один власник і ніколи не має посилань на нього "викраденого" іншим кодом.
Стів Джессоп

3

У Ломбоку є анотація @Cleanup, яка здебільшого нагадує деструктори C ++:

@Cleanup
ResourceClass resource = new ResourceClass();

Обробляючи його (під час компіляції), Lombok вставляє відповідний try-finallyблок так, що resource.close()викликається, коли виконання залишає область змінної. Ви також можете чітко вказати інший метод звільнення ресурсу, наприклад resource.dispose():

@Cleanup("dispose")
ResourceClass resource = new ResourceClass();

2
Перевага, яку я бачу, полягає в тому, що буде менше гніздування (Що може бути значним, якщо у вас багато об’єктів, які потребують "знищення").
Олексій

Блок спробу використання ресурсів може мати декілька ресурсів за один кадр
Олександр - Відновити Моніку

1
Але між ними не може бути вказівок.
Олексій

Справедливий. Я припускаю, що тоді рекомендується віддати перевагу пробному ресурсу, навіть для кількох ресурсів, якщо тільки між ними не буде інструкції, яка змусила вас робити нові блоки з використанням ресурсів (збільшуючи вкладення), а потім використовувати@Cleanup
Олександр - Відновіть Моніка

2

Найближчим еквівалентом деструктора на Java є метод finalize () . Велика відмінність традиційного деструктора полягає в тому, що ви не можете бути впевнені, коли він буде викликаний, оскільки це відповідальність за збирач сміття. Настійно рекомендую уважно ознайомитися з цим, перш ніж використовувати його, оскільки ваші типові шаблони RAIA для файлових ручок тощо не будуть надійно працювати з finalize ().


2

Тут багато чудових відповідей, але є додаткова інформація про те, чому вам слід уникати використання finalize () .

Якщо JVM виходить через System.exit()або Runtime.getRuntime().exit(), фіналізатори не працюватимуть за замовчуванням. Від Javadoc для Runtime.exit () :

Послідовність відключення віртуальної машини складається з двох фаз. На першій фазі всі зареєстровані гачки відключення, якщо такі є, запускаються у визначеному порядку і дозволяють одночасно працювати до їх закінчення. На другій фазі всі незакликані фіналізатори запускаються, якщо фіналізація при виході була включена. Як тільки це буде зроблено, віртуальна машина зупиняється.

Ви можете зателефонувати, System.runFinalization()але це лише докладає «максимум зусиль для завершення всіх непогашених доопрацювань» - не гарантія.

Існує System.runFinalizersOnExit()метод, але не використовуйте його - він небезпечний, давно застарілий.


1

Якщо ви пишете аплет Java, ви можете змінити метод "знищити ()" аплет. Це є...

 * Called by the browser or applet viewer to inform
 * this applet that it is being reclaimed and that it should destroy
 * any resources that it has allocated. The stop() method
 * will always be called before destroy().

Очевидно, не те, що ти хочеш, але може бути те, що шукають інші люди.


1

Поміркувавши над початковим запитанням ... яке, я думаю, ми можемо зробити висновок з усіх інших вивчених відповідей, а також із суттєвої ефективної Java Bloch , пункт 7, "Уникайте фіналізаторів", шукає рішення правомірного питання таким чином, невідповідний мові Java ...:

... не було б досить очевидним рішенням робити те, що ОП насправді хоче, - зберегти всі ваші об'єкти, які потрібно скинути, у своєрідний «манеж», на який усі інші об'єкти, що не перезавантажуються, мають посилання лише через якесь об'єкта аксесуара ...

І тоді, коли вам потрібно «скинути», ви від'єднаєте існуючий манеж і зробите новий: вся павутина об’єктів у манежі відкидається, ніколи не повертаючись, і один день повинен бути зібраний GC.

Якщо будь-який з цих об'єктів є Closeable(або немає, але має closeметод), ви можете помістити їх у Bagмайданчик, коли вони створені (і, можливо, відкриті), і останнім актом аксесуара перед відсіканням манежу було б піти через все їх Closeablesзакриття ...?

Код, мабуть, виглядатиме приблизно так:

accessor.getPlaypen().closeCloseables();
accessor.setPlaypen( new Playpen() );

closeCloseablesмабуть, це буде метод блокування, ймовірно, що включає засувку (наприклад CountdownLatch), для вирішення (і зачекання, якщо це доречно) будь-яких Runnables/ Callablesу будь-яких потоках, специфічних для Playpenзавершення, як годиться, зокрема в потоці JavaFX.


0

Незважаючи на те, що в GC-технології Java було досягнуто значного прогресу, ви все ще повинні пам’ятати про свої посилання. Згадуються численні випадки начебто тривіальних референтних зразків, які насправді є щурячими гніздами під кришкою.

З вашого повідомлення це не здається, що ви намагаєтесь реалізувати метод скидання з метою повторного використання об'єкта (правда?). Чи є у ваших об'єктах будь-який інший тип ресурсів, який потрібно очистити (тобто потоки, які необхідно закрити, об'єднані або позичені об’єкти, які потрібно повернути)? Якщо єдине, про що ви турбуєтесь - це операція з пам’яттю, то я б переглянув свою об’єктну структуру і спробував би переконатися, що мої об’єкти є самодостатньою структурою, яка буде очищена під час GC.


0

Класу деструкторів у Java немає точно, клас знищується автоматично у Java на сміттєзбірнику. але ви можете зробити це, використовуючи нижче одного, але це не зовсім те саме:

завершити ()

Виникло питання, яке породило поглиблене обговорення остаточного завершення , щоб ви могли отримати більше глибини, якщо потрібно ...


0

Жодна Java не має деструкторів. Основна причина цього в Java - смітники, які пасивно працюють у фоновому режимі завжди, і всі об'єкти створюються в купі пам'яті. Це місце, де працює GC. У c ++ там ми доведеться явно викликати функцію видалення, оскільки немає такого сміттєзбірника.


-3

Я в основному мав справу з C ++, і саме це призводить мене до пошуку деструктора. Зараз я дуже багато використовую JAVA. Що я зробив, і це може бути не найкращим випадком для всіх, але я реалізував власний деструктор шляхом повторного скидання всіх значень на 0 або там за замовчуванням через функцію.

Приклад:

public myDestructor() {

variableA = 0; //INT
variableB = 0.0; //DOUBLE & FLOAT
variableC = "NO NAME ENTERED"; //TEXT & STRING
variableD = false; //BOOL

}

В ідеалі це не буде працювати у всіх ситуаціях, але там, де є глобальні змінні, воно буде працювати до тих пір, поки у вас їх немає.

Я знаю, що я не найкращий програміст Java, але, здається, працює для мене.


Постарайтеся більше використовувати незмінні предмети, після того, як ви «отримаєте це», це матиме більше сенсу :)
R. van Twisk,

5
Це не так неправильно, як безглуздо - тобто нічого не досягається. Якщо ваша програма вимагає скидання необроблених типів для коректної роботи, то екземпляри ваших класів неправильно визначені, тобто ви, ймовірно, перепризначаєте властивості існуючого об'єкта властивостям нового об’єкта, не створюючи нового Object ().
simo.3792

1
За винятком того, що для скидання змінних існує велика кількість потреб. Я вибрав ім’я деструктора, оскільки воно відповідає тому, що я роблю. Це щось досягає, просто нічого не розумієш
ChristianGLong
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.