Como desarrollador de Java ingresando a .NET, me gustaría entender la interfaz IDisposable. ¿Podría alguien tratar de explicar esto y cómo difiere de lo que sucede en Java? Gracias.Metáfora identificable en Java?
Respuesta
Escribí un detailed series of articles on IDisposable.
La idea básica aquí es que a veces se necesita DETERMINADO DISPOSICIÓN DE LOS RECURSOS. IDisposable proporciona ese mecanismo.
Por ejemplo, supongamos que tiene un control en una ventana. Cuando se crea esto, crea un identificador de Windows (HWND) internamente. Cuando quita el control de la ventana y ya no se usa, el control pasa a ser elegible para la recolección de basura, pero no se recoge de inmediato. De hecho, no hay garantías de cuánto tiempo pasará antes de que se recopile.
Hasta que el GC se ejecute y procese el control huérfano, seguirá utilizando recursos, ya que aún contiene el HWND.
IDisposable proporciona un medio para que los objetos que contienen código que necesita limpieza separada del GC se limpien explícitamente por el usuario del objeto. En el caso del control, podemos llamar al myControl.Dispose(),
, que limpiará de forma inmediata y sincrónica los recursos "nativos" (HWND) utilizados por el control.
No hay equivalente.
Se utiliza cuando utiliza recursos no administrados (en Java todos los recursos gestionados son).
In. La memoria de red asignada por los recursos administrados es recopilada automáticamente por el GC (como en Java).
También tiene la oportunidad de utilizar recursos no administrados, donde será responsable de la asignación de memoria y su lanzamiento.
Llama a este método cuando ya no necesita los recursos.
Hay situaciones en las que necesita una eliminación confiable de los recursos que pertenecen a su clase. Por ejemplo, la conexión abierta debe cerrarse en el momento adecuado, no cuando GC decide recopilar memoria. En .NET método Dispose
es utilizado por la convención para esto. Se le puede llamar en try ... finally
bloque, por ejemplo:
IConnection conn = OpenConnection();
try{
...
}finally{
conn.Dispose();
}
Debido a este patrón es tan ampliamente utilizado, hay un azúcar sintáctico para esto:
using(IConnection conn = OpenConnection()){
} // Dispose is called at the end.
Como esta sintaxis es muy concisa, a veces es útil para implemente IDisposable
en objetos que no poseen recursos, pero necesitan ejecutar alguna operación al final de su uso. P.ej. tener en cuenta la clase
class TimeMeasure: IDisposable{
public void Measure(string operation) { ... } // recourds operation time
public void Dispose(){
... // print timings for all operations
}
}
Uso:
using(TimeMeasure m = new TimeMeasure())
{
DoFoo();
m.Measure("Foo");
DoBar();
m.Measure("Bar");
} // timings for 'Foo' and 'Bar' are printed here
En Java interfaz más o menos equivalente es Closeable
. Pero no hay una sintaxis simple para garantizar sus llamadas.
¿Cómo se debe implementar IDisposable
?Esto es un poco complicado:
- si posee los recursos, es necesario asegurarse de que pueden ser liberados por explícita
Dispose
llamada o por GC, pero no por ambos. Entonces, necesitas una bandera que indique el hecho de la eliminación. Para una menor duplicación de código, el código de eliminación se mueve a un método diferente.
Ejemplo:
bool disposed;
public void Dispose(){
Dispose(true);
GC.SuppressFinalize(this); // tell GC not to call Finalizer() for this object
}
~MyObject(){
Dispose(false);
}
void Dispose(bool manualDisposing){
if(!disposed){
disposed = true;
if(manualDisposing)
... // call Dispose on all IDisposable fields
... // dispose all native resources
}
}
- si no está sujetando los recursos, como en el caso de
TimeMeasure
clase, sin necesidad de finalizador, que acaba de hacer la lógica necesaria enDispose
.
Básicamente IDisposable en un nivel alto, combinado con la palabra clave using
le está dando soporte sintáctico de lo que se ve como un lenguaje de Java común como esto:
Connection c = null;
try {
c = getConnection();
....
} finally {
if (c != null) {
c.close();
}
}
Si Java tenía un uso de la palabra clave y una interfaz IDisposable con un método close()
, que podría tener este aspecto:
//psudo-Java
using(Connection c = getConnection()) {
.....
}
con el método de cierre se llama implícitamente al final de ese bloque. No hay necesidad de probar/finalmente.
Dicho esto, IDisposible tiene un contrato bastante complejo, y se trata principalmente de liberar la memoria no administrada. Tienes que trabajar duro con Java para tener memoria no administrada (básicamente con componentes JNI y Swing, tienes el concepto), pero es mucho más común en .NET, por lo que hay soporte de lenguaje para el concepto.
Con java 1.7 aparece la nueva instrucción try-with-resource.
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
Los objetos utilizados aquí deben implementar la interfaz AutoCloseable. No es exactamente lo mismo que IDisposable, pero el close()
se llama automáticamente en el final. Esto le da la oportunidad de implementar un comportamiento similar.
El código anterior es la misma que
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
Leer más sobre esto en java tutorial. El código de ejemplo proviene de allí.
La interfaz IDisposable se utiliza para liberar manualmente los recursos no administrados.
- 1. advertencia: carácter no identificable para codificar ASCII
- 2. ¿Qué es una metáfora en el contexto de XP?
- 3. error: carácter no identificable para la codificación UTF-8
- 4. ¿Las extensiones paralelas R rompen la metáfora `aplicar`?
- 5. ¿Cuál es una buena metáfora de la inyección de dependencia?
- 6. ejecutar código Java en Java
- 7. Principiantes básicos en Java: ¿qué significa 'argumentos' en Java
- 8. Java: ¿cómo inicializar una matriz en Java en una línea?
- 9. Java: ¿String.Format existe en Java como en C#?
- 10. Java en GPU: Método completo directamente en GPUin Java simple
- 11. ^operador en java
- 12. ClassValue en Java 7
- 13. BigDecimal Problema en java
- 14. clase DataSet en Java?
- 15. Buscar seno en Java
- 16. ConcurrentHashMap en Java?
- 17. JMenuItems personalizados en Java
- 18. Métodos estáticos en Java
- 19. BigDecimal en Java
- 20. Paquete en Java
- 21. Multidifusión confiable en Java
- 22. Probar/atrapar en Java
- 23. Instancia establecida en Java?
- 24. Escapar html en Java
- 25. alcance local en Java
- 26. ConfigurationException en Java?
- 27. Variables locales en java
- 28. Eliminación gaussiana en Java
- 29. impresión HashMap En Java
- 30. Palabras reservadas en Java
Pregunta rápida: ¿cómo se puede saber si un recurso no está administrado y debe eliminarse explícitamente? – gil
Ver si implementa IDisposable. :) Bastante siempre siempre desecha tus ID, si puedes. –
Si no se administra el recurso, debe saberlo cuando implemente la clase. Si no lo está implementando, solo lo usa, entonces no se requiere cuidado especial. Si necesita decidir sobre la eliminación explícita, intente responder a la pregunta "¿Es más urgente liberar el recurso lo antes posible que continuar la ejecución en este hilo ahora mismo?". Las respuestas pueden ser diferentes, por ejemplo, para una parte del servicio web frente a una parte de la GUI. –