2008-09-26 9 views

Respuesta

21

Sí. Java 1.7 introduce la construcción try-with-resources que le permite escribir:

try(InputStream is1 = new FileInputStream("/tmp/foo"); 
    InputStream is2 = new FileInputStream("/tmp/bar")) { 
     /* do stuff with is1 and is2 */ 
} 

... al igual que una declaración using.

Desafortunadamente, antes de Java 1.7, los programadores de Java se vieron obligados a usar try {...} finally {...}. En Java 1.6:

InputStream is1 = new FileInputStream("/tmp/foo"); 
try{ 

    InputStream is2 = new FileInputStream("/tmp/bar"); 
    try{ 
     /* do stuff with is1 and is 2 */ 

    } finally { 
     is2.close(); 
    } 
} finally { 
    is1.close(); 
} 
+0

¿Es posible actualizar esta respuesta con un ejemplo de C# con su uso de bloque, y luego con Java try-finally? Preferiblemente un ejemplo que utiliza 2 recursos separados para que podamos documentar cómo asegurarnos de que todo esté cerrado correctamente. –

+2

Como un chico de Java, la comparación anterior es un poco dolorosa. –

+0

Aunque técnicamente correcto, este patrón try/finally no es el mejor. Uso: X x = nueva X(); intenta {/ * trabajar * /} finalmente {x.disponer(); } – McDowell

2

No es que yo sepa. Puedes simular algo con un intento ... finalmente bloquear, pero todavía no es lo mismo.

-3

No, no hay uso en Java, la funcionalidad más similar es la palabra clave "importar".

+0

El cartel original no se refería a incluye. Ver http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx – McDowell

+3

¡Pobre @shifoz! Ustedes son crueles. La pregunta era totalmente vaga y podría haber querido decir esto http://msdn.microsoft.com/en-us/library/sf0df423 (VS.80) .aspx ... Shifoz, puedes recuperar algunos puntos preguntando algo sobre a los programadores les gusta "¿cuál es tu color de programación favorito en RGB?" –

-2

No, no hay.

Puede

public void func(){ 

    { 
    ArrayList l = new ArrayList(); 
    } 
    System.out.println("Hello"); 

} 

Esto le da el alcance limitado de la cláusula de usar, pero no hay ninguna interfaz IDisposable a llamar al código de finalización. Puedes usar try {} catch() {} Finally {}, pero no tiene el azúcar de usar. Por cierto, el uso de finalizadores en Java generalmente es una mala idea.

1

Creo que puede lograr algo similar al bloque "usar", implementando una clase interna anónima. Como Spring lo hace con las "Plantillas Dao".

2

Lo más cerca que puede obtener en Java es try/finally. Además, Java no proporciona un tipo implícito desechable.

C#: determinación del alcance de la variable fuera de un uso de bloque de

public class X : System.IDisposable { 

    public void Dispose() { 
     System.Console.WriteLine("dispose"); 
    } 

    private static void Demo() { 
     X x = new X(); 
     using(x) { 
      int i = 1; 
      i = i/0; 
     } 
    } 

    public static void Main(System.String[] args) { 
     try { 
      Demo(); 
     } catch (System.DivideByZeroException) {} 
    } 

} 

Java: la determinación del alcance de la variable fuera de un bloque

public class X { 

    public void dispose() { 
     System.out.println("dispose"); 
    } 

    private static void demo() { 
     X x = new X(); 
     try { 
      int i = 1/0; 
     } finally { 
      x.dispose(); 
     }   
    } 

    public static void main(String[] args) { 
     try { 
      demo(); 
     } catch(ArithmeticException e) {} 
    } 

} 

C#: determinación del alcance de la variable dentro de un bloque

public class X : System.IDisposable { 

    public void Dispose() { 
     System.Console.WriteLine("dispose"); 
    } 

    private static void Demo() { 
     using(X x = new X()) { 
      int i = 1; 
      i = i/0; 
     } 
    } 

    public static void Main(System.String[] args) { 
     try { 
      Demo(); 
     } catch (System.DivideByZeroException) {} 
    } 

} 

Java: la determinación del alcance de la variable dentro de un bloque

public class X { 

    public void dispose() { 
     System.out.println("dispose"); 
    } 

    private static void demo() { 
     { 
      X x = new X(); 
      try { 
       int i = 1/0; 
      } finally { 
       x.dispose(); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     try { 
      demo(); 
     } catch(ArithmeticException e) {} 
    } 

} 
0

Bueno, era el uso de azúcar sintáctico todos modos por lo compañeros de Java, no se preocupe.

5

El equivalente más cercano en el idioma es usar try-finally.

using (InputStream in as FileInputStream("myfile")) { 
    ... use in ... 
} 

convierte

final InputStream in = FileInputStream("myfile"); 
try { 
    ... use in ... 
} finally { 
    in.close(); 
} 

Nota la forma general es siempre:

acquire; 
try { 
    use; 
} finally { 
    release; 
} 

Si la adquisición se encuentra dentro del bloque try, se dará a conocer en el caso de que falle la adquisición. En algunos casos, es posible que puedas hackear código innecesario (por lo general, pruebas de null en el ejemplo anterior), pero en el caso de, por ejemplo, ReentrantLock, sucederán cosas malas.

Si está haciendo lo mismo a menudo, puede utilizar el modismo "ejecutar alrededor". Lamentablemente, la sintaxis de Java es prolija, por lo que hay una gran cantidad de placa más bolier.

fileInput("myfile", new FileInput<Void>() { 
    public Void read(InputStream in) throws IOException { 
     ... use in ... 
     return null; 
    } 
}); 

donde

public static <T> T fileInput(FileInput<T> handler) throws IOException { 
    final InputStream in = FileInputStream("myfile"); 
    try { 
     handler.read(in); 
    } finally { 
     in.close(); 
    } 
} 

ejemplo más complicado de mi, por ejemplo, envolver excepciones.

0

Si obtenemos cierres BGGA en Java, esto también se abriría para estructuras similares en Java. Gafter ha utilizado este ejemplo en sus diapositivas, por ejemplo:

withLock(lock) { //closure } 
0

La expresión real utilizado por la mayoría de los programadores para el primer ejemplo es la siguiente:

InputStream is1 = null; 
InputStream is2 = null; 
try{ 
    is1 = new FileInputStream("/tmp/bar"); 
    is2 = new FileInputStream("/tmp/foo"); 

    /* do stuff with is1 and is 2 */ 

} finally { 
    if (is1 != null) { 
     is1.close(); 
    } 
    if (is2 != null) { 
     is2.close(); 
    } 
} 

hay menos sangría utilizando este idioma, que se convierte aún más importante cuando tienes más de 2 recursos para la limpieza.

Además, puede agregar una cláusula catch a la estructura que tratará con el nuevo FileStream() lanzando una excepción si lo necesita. En el primer ejemplo, tendrías que tener otro bloque adjunto try/catch si quieres hacer esto.

+0

Este código no cierra is2 si la llamada a is1.close() arroja una excepción. El código anidado dado en la pregunta es preferible. – cunkel

9

Sí, ya que Java 7 puede volver a escribir:

InputStream is1 = new FileInputStream("/tmp/foo"); 
try{ 

    InputStream is2 = new FileInputStream("/tmp/bar"); 
    try{ 
     /* do stuff with is1 and is2 */ 

    } finally { 
     is2.close(); 
    } 
} finally { 
    is1.close(); 
} 

Como

try(InputStream is1 = new FileInputStream("/tmp/foo"); 
    InputStream is2 = new FileInputStream("/tmp/bar")) { 
     /* do stuff with is1 and is2 */ 
} 

Los objetos pasados ​​como parámetros a la sentencia try debe aplicar java.lang.AutoCloseable .have un vistazo a la official docs.

Para versiones anteriores de la comprobación de Java this answer y this answer.

Cuestiones relacionadas