Soy bastante viejo. He estado allí y lo he visto y me golpeé la cabeza muchas veces.
Estuve en una conferencia en Hursley Park donde los chicos de IBM nos contaron lo maravilloso que era este nuevo lenguaje Java, solo alguien preguntó ... ¿por qué no hay un destructor para estos objetos? No quiso decir lo que conocemos como destructor en C ++, pero tampoco había finalista (o tenía finalizadores pero básicamente no funcionaron). Esto fue hace mucho, y decidimos que Java era un poco como un lenguaje de juguete en ese momento.
ahora agregaron Finalizadores a la especificación de lenguaje y Java vio cierta adopción.
Por supuesto, luego se les dijo a todos que no pusieran finalizadores en sus objetos porque esto ralentizó tremendamente el GC. (ya que no solo tenía que bloquear el montón, sino también mover los objetos que se iban a finalizar a un área temporal, ya que estos métodos no podían llamarse, ya que el GC había detenido la ejecución de la aplicación. En cambio, serían llamados inmediatamente antes del siguiente Ciclo GC) (y, lo que es peor, a veces el finalizador nunca se llamaría cuando la aplicación se estaba cerrando. Imagínate que nunca se haya cerrado el identificador de archivo)
Luego tuvimos C #, y recuerdo el foro de discusión en MSDN donde se nos dijo lo maravilloso que era este nuevo lenguaje de C #. Alguien preguntó por qué no hubo una finalización determinista y los chicos de MS nos dijeron que no necesitábamos tales cosas, luego nos dijeron que necesitábamos cambiar nuestra forma de diseñar aplicaciones, luego nos contaron lo increíble que era GC y cómo eran todas nuestras aplicaciones antiguas. Basura y nunca funcionó por todas las referencias circulares. Luego cedieron a la presión y nos dijeron que habían agregado este patrón de propósito de uso a la especificación que podríamos usar. Pensé que en ese momento ya habíamos vuelto a la gestión manual de la memoria en las aplicaciones de C #.
Por supuesto, los chicos de MS más tarde descubrieron que todo lo que nos habían dicho era ... bueno, hicieron que el Propósito fuera un poco más que una simple interfaz estándar, y luego agregaron la declaración de uso. W00t! Se dieron cuenta de que la finalización determinista era algo que faltaba en el lenguaje, después de todo. Por supuesto, aún debes recordar ponerlo en todas partes, por lo que es un poco manual, pero es mejor.
Entonces, ¿por qué lo hicieron cuando pudieron haber colocado semánticas de estilo de uso automáticamente en cada bloque de alcance desde el principio? Probablemente eficiencia, pero me gusta pensar que simplemente no se dieron cuenta. Al igual que al final se dieron cuenta de que todavía necesita punteros inteligentes en .NET (google SafeHandle) pensaron que el GC realmente resolvería todos los problemas. Olvidaron que un objeto es más que solo memoria y que GC está diseñado principalmente para manejar la administración de memoria. quedaron atrapados en la idea de que el GC manejaría esto, y olvidaron que pusiste otras cosas allí, un objeto no es solo un bulto de memoria que no importa si no lo eliminas por un tiempo.
Pero también creo que la falta de un método de finalización en el Java original tenía algo más que eso: que los objetos que creaste se referían a la memoria, y si querías eliminar otra cosa (como un controlador de base de datos o un socket o lo que sea), entonces se esperaba que lo hiciera manualmente .
Recuerde que Java se diseñó para entornos integrados donde las personas estaban acostumbradas a escribir código C con muchas asignaciones manuales, por lo que no tener libre automático no era un gran problema, nunca lo hizo antes, ¿por qué lo necesitaría? ¿Java? El problema no tenía nada que ver con subprocesos, o pila / montón, probablemente solo estaba allí para hacer que la asignación de memoria (y por lo tanto la desasignación) fuera un poco más fácil. En general, la declaración try / finally es probablemente un mejor lugar para manejar recursos sin memoria.
Así que, en mi humilde opinión, la forma en que .NET simplemente copió el mayor defecto de Java es su mayor debilidad. .NET debería haber sido un mejor C ++, no un mejor Java.