Jestem całkiem stara Byłem tam, widziałem to i wiele razy waliłem w nie głową.
Byłem na konferencji w Hursley Park, gdzie chłopcy IBM opowiadali nam, jak cudowny jest ten nowy język Java, tylko ktoś zapytał ... dlaczego nie ma destruktora dla tych obiektów. Nie miał na myśli tego, co znamy jako destruktor w C ++, ale nie było też finalizatora (lub miał finalizatory, ale w zasadzie nie działały). To jest bardzo dawno temu i doszliśmy do wniosku, że Java była trochę zabawkowym językiem.
teraz dodali Finalizatory do specyfikacji języka, a Java zyskała trochę akceptacji.
Oczywiście później wszystkim powiedziano, aby nie nakładali finalizatorów na swoje obiekty, ponieważ to znacznie spowolniło GC. (ponieważ musiał nie tylko zablokować stertę, ale także przenieść obiekty, które mają zostać sfinalizowane, do obszaru tymczasowego, ponieważ metody te nie mogły zostać wywołane, ponieważ GC wstrzymała działanie aplikacji. Zamiast tego zostałyby wywołane bezpośrednio przed następnym Cykl GC) (i co gorsza, czasami finalizator nigdy nie zostanie wywołany, gdy aplikacja zostanie zamknięta. Wyobraź sobie, że nie masz zamkniętego uchwytu pliku)
Potem mieliśmy C # i pamiętam forum dyskusyjne na MSDN, gdzie powiedziano nam, jak wspaniały był ten nowy język C #. Ktoś zapytał, dlaczego nie było deterministycznej finalizacji, a chłopcy ze stwardnienia rozsianego powiedzieli nam, że nie potrzebujemy takich rzeczy, a następnie powiedzieli nam, że musimy zmienić nasz sposób projektowania aplikacji, a następnie powiedzieli nam, jak niesamowity był GC i jak wszystkie nasze stare aplikacje były śmieci i nigdy nie działały z powodu wszystkich okólników. Potem poddali się presji i powiedzieli nam, że dodali ten wzór IDispose do specyfikacji, której moglibyśmy użyć. Myślałem, że w tym momencie wróciłem do ręcznego zarządzania pamięcią w aplikacjach C #.
Oczywiście, chłopcy ze stwardnienia rozsianego później odkryli, że wszystko, co nam powiedzieli, to ... cóż, uczynili IDispose nieco więcej niż zwykłym interfejsem, a później dodali instrukcję using. W00t! Zrozumieli, że mimo wszystko w języku brakowało deterministycznej finalizacji. Oczywiście nadal musisz pamiętać o umieszczeniu go wszędzie, więc jest trochę ręczny, ale jest lepszy.
Dlaczego więc zrobili to, skoro od samego początku mogli automatycznie umieszczać semantykę w stylu przy użyciu każdego bloku zakresu? Prawdopodobnie wydajność, ale lubię myśleć, że po prostu nie zdawali sobie sprawy. Tak jak w końcu zdali sobie sprawę, że nadal potrzebujesz inteligentnych wskaźników w .NET (Google SafeHandle), pomyśleli, że GC naprawdę rozwiąże wszystkie problemy. Zapomnieli, że obiekt to coś więcej niż pamięć i że GC jest przede wszystkim zaprojektowany do zarządzania pamięcią. złapali się na pomysł, że GC sobie z tym poradzi i zapomnieli, że umieściłeś tam inne rzeczy, obiekt nie jest tylko kroplą pamięci, która nie ma znaczenia, jeśli nie usuniesz go przez jakiś czas.
Ale myślę też, że brak metody finalizacji w oryginalnej Javie miał coś więcej - że stworzone obiekty dotyczyły pamięci i jeśli chcesz usunąć coś innego (np. Uchwyt DB, gniazdo lub cokolwiek innego ), oczekiwano, że zrobisz to ręcznie .
Pamiętaj, że Java została zaprojektowana dla środowisk osadzonych, w których ludzie byli przyzwyczajeni do pisania kodu C z dużą ilością ręcznych alokacji, więc brak automatycznego bezpłatnego nie stanowił większego problemu - nigdy wcześniej tego nie robili, więc po co miałbyś go używać w Javie? Problem nie miał nic wspólnego z wątkami lub stosem / stertą, prawdopodobnie był po to, aby ułatwić przydzielanie pamięci (a tym samym cofanie alokacji). Podsumowując, instrukcja try / wreszcie jest prawdopodobnie lepszym miejscem do obsługi zasobów innych niż pamięć.
Więc IMHO, sposób, w jaki .NET po prostu skopiował największą wadę Javy, jest jej największą słabością. .NET powinien być lepszym C ++, a nie lepszą Javą.