Я довольно старый. Я был там и видел это, и много раз ударил головой об этом.
Я был на конференции в Херсли-Парке, где ребята из IBM рассказывали нам, как прекрасен этот совершенно новый язык Java, только кто-то спросил ... почему нет деструктора для этих объектов. Он не имел в виду то, что мы знаем как деструктор в C ++, но финализатора тоже не было (или у него были финализаторы, но они в основном не работали). Это путь назад, и мы решили, что в тот момент Java была немного игрушечным языком.
теперь они добавили Finalisers в спецификацию языка, и Java получила некоторое распространение.
Конечно, позже всем сказали не ставить финализаторы на свои объекты, потому что это сильно замедлило GC. (поскольку он должен был не только заблокировать кучу, но и переместить объекты, подлежащие финализации, во временную область, поскольку эти методы нельзя было вызвать, так как сборщик мусора приостановил работу приложения. Вместо этого они будут вызваны непосредственно перед следующей Цикл GC) (и что еще хуже, иногда финализатор никогда не вызывался бы вообще, когда приложение закрывалось. Представьте, что у вас никогда не было закрытого дескриптора файла)
Потом у нас был C #, и я помню дискуссионный форум на MSDN, где нам рассказывали, как прекрасен этот новый язык C #. Кто-то спросил, почему не было детерминированной финализации, и ребята из MS рассказали нам, как нам не нужны такие вещи, затем сказали, что нам нужно изменить наш способ разработки приложений, а затем сказали, как прекрасен GC и как все наши старые приложения были мусор и никогда не работал из-за всех циркулярных ссылок. Затем они уступили давлению и сказали нам, что они добавили этот шаблон IDispose к спецификации, которую мы могли бы использовать. Я думал, что это было в значительной степени назад к ручному управлению памятью для нас в приложениях C # на тот момент.
Конечно, ребята из MS позже обнаружили, что все, что они сказали нам, это ... ну, они сделали IDispose немного больше, чем просто стандартный интерфейс, а позже добавили оператор using. W00t! Они поняли, что детерминистская финализация чего-то не хватает в языке в конце концов. Конечно, вы все равно должны помнить, чтобы вставить его везде, так что это все еще немного ручной, но это лучше.
Так почему же они сделали это, когда могли с самого начала автоматически размещать семантику в стиле использования в каждом блоке области видимости? Вероятно, эффективность, но мне нравится думать, что они просто не осознали. Также как в конце концов они поняли, что вам все еще нужны умные указатели в .NET (Google SafeHandle), они подумали, что GC действительно решит все проблемы. Они забыли, что объект - это больше, чем просто память, и что GC в первую очередь предназначен для управления памятью. они увлеклись идеей, что GC справится с этим, и забыли, что вы помещаете туда другие вещи, объект не просто капля памяти, которая не имеет значения, если вы не удалите ее на некоторое время.
Но я также думаю, что отсутствие метода finalize в исходной Java имело немного больше - что все объекты, которые вы создавали, были связаны с памятью, и если вы хотите удалить что-то еще (например, дескриптор БД, сокет или что-то еще) ) тогда вы должны были сделать это вручную .
Помните, что Java была разработана для встраиваемых сред, где люди привыкли писать код на C с большим количеством ручных распределений, поэтому отсутствие автоматического освобождения не было большой проблемой - они никогда не делали этого раньше, так зачем вам это нужно в Java? Проблема заключалась не в том, что связано с потоками или стеком / кучей, а просто с тем, чтобы сделать выделение памяти (и, следовательно, удаление) немного проще. В общем, оператор try / finally, вероятно, является лучшим местом для обработки ресурсов, не связанных с памятью.
ИМХО, то, как .NET просто скопировал самый большой недостаток Java - это его самая большая слабость. .NET должен был быть лучше C ++, а не лучше Java.