Java 7: Try-with-resources ou Automatic Resource Management

48 respostas
T

Com o build 105 do Java 7, está disponível a sintaxe para fechar automaticamente arquivos ou outros recursos que precisem de tratamento especial para serem fechados.
Baixem o build em : http://download.java.net/jdk7/
Vejam o blog do Joseph Darcy, http://blogs.sun.com/darcy/
A spec está em: http://blogs.sun.com/darcy/entry/project_coin_updated_arm_spec
O Thingol postou um exemplo simples desse recurso.
http://thingol-guj.blogspot.com/2010/08/java-7-automatic-resource-management.html

Dá para fazer um exemplo mais elaborado.
Em resumo: o equivalente do seguinte recurso em C#, que chama automaticamente o “Dispose” (equivalente do método Java “close”):

using (StreamWriter sw = new StreamWriter ("teste.txt")) {
    sw.WriteLine ("teste");
}

é, em Java 7,

try (PrintWriter pw = new PrintWriter ("teste.txt")) {
    pw.println ("teste");
}

Para economizar palavras-chave, foi reusada a palavra-chave “try”. Uma coisa que é um pouco diferente no Java em relação ao C# é que esse try continua a ter o “catch” e o “finally”, então você pode ao mesmo tempo fechar o arquivo e tratar as exceções, tudo dentrodo mesmo try/catch/finally.
Uma coisa meio chata é que a classe deve implementar AutoCloseable, mas as classes do JDBC não implementam AutoCloseable apesar de o Darcy ter insistido bastante com o time do JDBC. Parece que a spec do JDBC para o Java 7 está fechada há tempos…

48 Respostas

A

Aposto que vai confundir muita gente esse try com catch e finally opcionais!

Só não vi muita vantagem nisso… Não consegui entender o porque de eu não querer tratar a exception na hora de fechar o arquivo (ou coisa do tipo).

J

show de bola.

E

Vou copiar o exemplo do Thingol, e então postar o exemplo equivalente em Java 6.

// Java 7
        // Exemplo um pouco mais complexo, que
        // envolve 2 arquivos
        try (BufferedOutputStream bos = new BufferedOutputStream (
                new FileOutputStream ("copy.of.file"));
             BufferedInputStream bis = new BufferedInputStream (
                new FileInputStream ("original.file"))) {
            byte[] buffer = new byte[10240];
            for (int nBytes = bis.read (buffer); nBytes > 0;
                    nBytes = bis.read (buffer)) {
                bos.write (buffer, 0, nBytes); 
            }
        } catch (final FileNotFoundException | IOException ex) {
            ex.printStackTrace();
        }
// Java 6
		// Exemplo um pouco mais complexo, que
		// envolve 2 arquivos
		BufferedOutputStream bos = null;
		BufferedInputStream bis = null;
		try {
			BufferedOutputStream bos = new BufferedOutputStream (
				new FileOutputStream ("copy.of.file"));
			BufferedInputStream bis = new BufferedInputStream (
				new FileInputStream ("original.file"));
			byte[] buffer = new byte[10240];
			for (int nBytes = bis.read (buffer); nBytes > 0;
					nBytes = bis.read (buffer)) {
				bos.write (buffer, 0, nBytes); 
			}
		} catch (FileNotFoundException ex) {
			ex.printStackTrace();
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			if (bis != null) try { bis.close(); } catch (IOException ex) {}
			if (bos != null) try { bos.close(); } catch (IOException ex) {}
		}
J

Andre Brito:
Aposto que vai confundir muita gente esse try com catch e finally opcionais!

Só não vi muita vantagem nisso… Não consegui entender o porque de eu não querer tratar a exception na hora de fechar o arquivo (ou coisa do tipo).

A idéia é que o io só existe dentro do scopo, ou seja dentro do try. Isso evita erros gerados quando não se desalocam recursos, como memory leaks.
Idéia muito boa essa interface AutoCloseable.

J

entanglement:
Vou copiar o exemplo do Thingol, e então postar o exemplo equivalente em Java 6.

// Java 7
        // Exemplo um pouco mais complexo, que
        // envolve 2 arquivos
        try (BufferedOutputStream bos = new BufferedOutputStream (
                new FileOutputStream ("copy.of.file"));
             BufferedInputStream bis = new BufferedInputStream (
                new FileInputStream ("original.file"))) {
            byte[] buffer = new byte[10240];
            for (int nBytes = bis.read (buffer); nBytes > 0;
                    nBytes = bis.read (buffer)) {
                bos.write (buffer, 0, nBytes); 
            }
        } catch (final FileNotFoundException | IOException ex) {
            ex.printStackTrace();
        }

// Java 6 // Exemplo um pouco mais complexo, que // envolve 2 arquivos BufferedOutputStream bos = null; BufferedInputStream bis = null; try { BufferedOutputStream bos = new BufferedOutputStream ( new FileOutputStream ("copy.of.file")); BufferedInputStream bis = new BufferedInputStream ( new FileInputStream ("original.file")); byte[] buffer = new byte[10240]; for (int nBytes = bis.read (buffer); nBytes > 0; nBytes = bis.read (buffer)) { bos.write (buffer, 0, nBytes); } } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } finally { if (bis != null) try { bis.close(); } catch (IOException ex) {} if (bos != null) try { bos.close(); } catch (IOException ex) {} }

Estou baixando a nova release.

E

Note várias coisas.

a) O try-with-resources sempre fecha direitinho os arquivos (não preciso usar esse truque de inicializar a variável com null, usar um finally, e então sufocar a eventual exceção gerada pelo close com esses try/catchs dentro do finally.
b) Diferentemente do C# (onde só posso fazer uma declaração dentro do using), posso pôr várias declarações dentro do try(). Elas indicarão também a ordem de encerramento ( se você abrir os arquivos em uma determinada ordem, eles serão fechados em ordem inversa).
c) Você pode tratar várias exceções em um mesmo catch, se elas forem compatíveis entre si. Basta usar “final” e “|” para separar os nomes das classes.

E

Como foi apontado pelo Thingol, infelizmente as classes e interfaces de java.sql.* não implementam AutoCloseable*, portanto não posso usar o mesmo truque com um ResultSet ou uma Connection. Provavelmente alguém irá criar um “wrapper” para essas interfaces que implemente AutoCloseable, só para poder usar o “try-with-resources”.

  • Provavelmente porque, devido ao fato de o JDBC envolver cooperação dos fornecedores de drivers, ficaria um pouco inviável, já que a spec foi fechada há tempos, reabrir a spec e forçar os fornecedores a atualizarem suas implementações. Isso é diferente, por exemplo, do java.io.*, cujo único fornecedor é a Sun/Oracle nesse caso.
M

Boa, mas a interface podia se chamar simplesmente Closable.

Isso tudo são syntax-sugars ou realmente ouve alguma mudança na estrutura dos programas em Java?

D

Achei muito legal, só não gostei da sintaxe.

[]´s

D

Não concordo. Pq o fechamento é automático e a interface tem que denotar exatamente, ao meu ver, o comportamento de quem a implementa.
Closable fica muito genérico. Afinal, as classes já são Closable.

[]´s

T

Marky.Vasconcelos:
Boa, mas a interface podia se chamar simplesmente Closable.

Isso tudo são syntax-sugars ou realmente houve alguma mudança na estrutura dos programas em Java?

Já existe uma interface Closeable:

http://download-llnw.oracle.com/javase/6/docs/api/java/io/Closeable.html

A Closeable, no Java 7, irá estender Autocloseable.

O que o Darcy não conseguiu é que as classes e interfaces do JDBC que tèm um método close() implementassem Autocloseable. (A propósito, elas também não implementam java.io.Closeable, principalmente porque a interface java.io.Closeable tem um método close que lança a exceção IOException, e o close do JDBC lança SQLException.

O close do Autocloseable irã lançar simplesmente Exception, o que é permitido pelo Java (você, ao estender uma interface, pode redefinir o método lançando uma exceção mais específica - por exemplo, se Autocloseable lança Exception, java.io.Closeable pode lançar IOException, e java.sql.Closeable (uma interface que não existe, aliás) poderia lançar SQLException, sem problemas.

Voltando à vaca fria: é claro que é um syntax sugar. Mas que economiza um bocado de esforço e ajuda a tornar seus programas mais corretos, ajuda.

M

PS: Thingol, seu blog é muito preto e cinza, é dificil ver as coisas. Foi pra economizar energia?

M

entanglement:
Vou copiar o exemplo do Thingol, e então postar o exemplo equivalente em Java 6.

// Java 7
        // Exemplo um pouco mais complexo, que
        // envolve 2 arquivos
        try (BufferedOutputStream bos = new BufferedOutputStream (
                new FileOutputStream ("copy.of.file"));
             BufferedInputStream bis = new BufferedInputStream (
                new FileInputStream ("original.file"))) {
            byte[] buffer = new byte[10240];
            for (int nBytes = bis.read (buffer); nBytes > 0;
                    nBytes = bis.read (buffer)) {
                bos.write (buffer, 0, nBytes); 
            }
        } catch (final FileNotFoundException | IOException ex) {
            ex.printStackTrace();
        }

// Java 6 // Exemplo um pouco mais complexo, que // envolve 2 arquivos BufferedOutputStream bos = null; BufferedInputStream bis = null; try { BufferedOutputStream bos = new BufferedOutputStream ( new FileOutputStream ("copy.of.file")); BufferedInputStream bis = new BufferedInputStream ( new FileInputStream ("original.file")); byte[] buffer = new byte[10240]; for (int nBytes = bis.read (buffer); nBytes > 0; nBytes = bis.read (buffer)) { bos.write (buffer, 0, nBytes); } } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } finally { if (bis != null) try { bis.close(); } catch (IOException ex) {} if (bos != null) try { bos.close(); } catch (IOException ex) {} }

O equivalente em Clojure:

(spit "copy.of.file" (slurp "original.file"))
P

A espera foi grande, mas parece que teremos uma boa gama de features novas, sem contar as closures.

M

Marky.Vasconcelos:
Boa, mas a interface podia se chamar simplesmente Closable.

Isso tudo são syntax-sugars ou realmente ouve alguma mudança na estrutura dos programas em Java?

Sim, apenas syntax-sugars…

L

[quote=mochuara]

entanglement:
Vou copiar o exemplo do Thingol, e então postar o exemplo equivalente em Java 6.

// Java 7
        // Exemplo um pouco mais complexo, que
        // envolve 2 arquivos
        try (BufferedOutputStream bos = new BufferedOutputStream (
                new FileOutputStream ("copy.of.file"));
             BufferedInputStream bis = new BufferedInputStream (
                new FileInputStream ("original.file"))) {
            byte[] buffer = new byte[10240];
            for (int nBytes = bis.read (buffer); nBytes > 0;
                    nBytes = bis.read (buffer)) {
                bos.write (buffer, 0, nBytes); 
            }
        } catch (final FileNotFoundException | IOException ex) {
            ex.printStackTrace();
        }

// Java 6 // Exemplo um pouco mais complexo, que // envolve 2 arquivos BufferedOutputStream bos = null; BufferedInputStream bis = null; try { BufferedOutputStream bos = new BufferedOutputStream ( new FileOutputStream ("copy.of.file")); BufferedInputStream bis = new BufferedInputStream ( new FileInputStream ("original.file")); byte[] buffer = new byte[10240]; for (int nBytes = bis.read (buffer); nBytes > 0; nBytes = bis.read (buffer)) { bos.write (buffer, 0, nBytes); } } catch (FileNotFoundException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } finally { if (bis != null) try { bis.close(); } catch (IOException ex) {} if (bos != null) try { bos.close(); } catch (IOException ex) {} }

O equivalente em Clojure:

(spit "copy.of.file" (slurp "copy.of.file"))

O equivalente em Python

shutil.copyfile(copy.of.file, copy.of.file);

Vale lembrar que o commons-io tem muitas funções prontas pra esses tipos de operações que envolvem o filesystem. Mas são poucas pessoas que usam, de fato, as bibliotecas do commons =(

A

juliocbq:
Andre Brito:
Aposto que vai confundir muita gente esse try com catch e finally opcionais!

Só não vi muita vantagem nisso… Não consegui entender o porque de eu não querer tratar a exception na hora de fechar o arquivo (ou coisa do tipo).

A idéia é que o io só existe dentro do scopo, ou seja dentro do try. Isso evita erros gerados quando não se desalocam recursos, como memory leaks.
Idéia muito boa essa interface AutoCloseable.


Hum… É, o escopo fica bem mais ‘restrito’ ou ‘focado’, não sei qual o termo certo. Pensando dessa forma e das outras vantagens colocadas pelo entaglement, é bem interessante a funcionalidade.

Aliás, o blog do Thingol tem várias coisas a respeito do Java 7. Vale a pena dar uma conferida.

B

[quote=mochuara]
O equivalente em Clojure:

(spit "copy.of.file" (slurp "original.file"))

O equivalente em Java, usando um método copyFile:

copyFile("original.file", "copy.of.file");

Mas sério, não vou ficar brincando de a-minha-api-padrão-é-melhor-que-a-sua.

M

Leozin:

O equivalente em Python

shutil.copyfile(copy.of.file, copy.of.file);

Vale lembrar que o commons-io tem muitas funções prontas pra esses tipos de operações que envolvem o filesystem. Mas são poucas pessoas que usam, de fato, as bibliotecas do commons =(

Bem melhor ne? rs

Mas Clojure tem uma vantagem que é não precisar abrir mão do Java.

M

Bruno Laturner:

Mas sério, não vou ficar brincando de a-minha-api-padrão-é-melhor-que-a-sua.

Até porque não existe o equivalente na API padrão do Java.

E

Acho que ele só postou esse exemplo de cópia de arquivos por ser bem simples de entender. Ele já postou, por exemplo, como é que se copia um arquivo com java.nio, por exemplo, que é claramente mais rápido que com Buffered*Stream.

É pena que a especificação do Projeto Lambda não está muito fechada, e você ainda não possa baixar uma versão funcional do site (você precisa baixar os fontes você mesmo e fazer você mesmo a compilação do JDK, o que não é nada muito trivial. ) Não é o “closures” do Neal Gafter (que não envolvia mudar a própria JVM).

O Projeto Lambda, que é uma modificação bem tímida da linguagem a meu ver, vai permitir algumas coisas que ainda não são possíveis em Java.

M

entanglement:
Acho que ele só postou esse exemplo de cópia de arquivos por ser bem simples de entender. Ele já postou, por exemplo, como é que se copia um arquivo com java.nio, por exemplo, que é claramente mais rápido que com Buffered*Stream.

É pena que a especificação do Projeto Lambda não está muito fechada, e você ainda não possa baixar uma versão funcional do site (você precisa baixar os fontes você mesmo e fazer você mesmo a compilação do JDK, o que não é nada muito trivial. ) Não é o “closures” do Neal Gafter (que não envolvia mudar a própria JVM).

O Projeto Lambda, que é uma modificação bem tímida da linguagem a meu ver, vai permitir algumas coisas que ainda não são possíveis em Java.

Dependendo do tamanho do arquivo lido a diferença entre NIO e IO é irrelevante, e em operações maiores eu não afirmaria com tanta certeza, pelo menos sem saber qual o modelo de threads utilizado.


D

Bom post Thigol,

na revista JavaMagazine desde mês (ed. 82) foi publicada um artigo do Osvaldo Doederlein) sobre esse mesmo assunto, aos interessados recomendo a leitura.

Esse recurso, pelo que entendi é chamado de “Automatic Resource Management - ARM” e aparentemente tem impacto apenas na “verbosidade” do Java.

Os defensores dessa coisa, reclamam de fazer isso em um bloco finally:

if (bis != null) try { bis.close(); } catch (IOException ex) {} if (bos != null) try { bos.close(); } catch (IOException ex) {}

Como se ninguém tivesse escrito classes utilitárias para evitar os catch vazios esparramados pelo código. Eu uso assim:

FileUtils.close(bis); FileUtils.close(bos);

Com relação aos outros aspectos das novidades, eu ainda estou avaliando (risos).

fw

J

Dieval Guizelini:
Bom post Thigol,

na revista JavaMagazine desde mês (ed. 82) foi publicada um artigo do Osvaldo Doederlein) sobre esse mesmo assunto, aos interessados recomendo a leitura.

Esse recurso, pelo que entendi é chamado de “Automatic Resource Management - ARM” e aparentemente tem impacto apenas na “verbosidade” do Java.

Os defensores dessa coisa, reclamam de fazer isso em um bloco finally:

if (bis != null) try { bis.close(); } catch (IOException ex) {} if (bos != null) try { bos.close(); } catch (IOException ex) {}

Como se ninguém tivesse escrito classes utilitárias para evitar os catch vazios esparramados pelo código. Eu uso assim:

FileUtils.close(bis); FileUtils.close(bos);

Com relação aos outros aspectos das novidades, eu ainda estou avaliando (risos).

fw

Com certeza. Eu não considero como sintaxe sugar, pelo fato de realmente ser muito útil. Como citado eu precisaria de um finally para liberar os recursos, pois a vida deles se estende além do escopo mostrado acima. Dessa maneira o próprio ciclo de vida delas se encarrega de libera-los para mim.

M

Está acontecendo com o Java e C# o mesmo que aconteceu com o Delphi e VB: a MS lança uns recursos que atendem 0,001% de melhoria na produtividade e sai com um marketing de que possui o recurso e o outro não. Daí a outra empresa corre e implementa também, mesmo que na prática pouquíssima gente vai usar e que ajuda muito pouco no produto final.

Chega uma hora que as duas linguagens vão ficar tão cheias de recursos quase inúteis que vão ficar pesadonas, enormes e confusas, gerando códigos idem. Até que surja uma nova onda e comece tudo de novo.

I

Alguém sabe dizer se o MigLayout vai entrar na versão final?

F

marcosalex:
Está acontecendo com o Java e C# o mesmo que aconteceu com o Delphi e VB: a MS lança uns recursos que atendem 0,001% de melhoria na produtividade e sai com um marketing de que possui o recurso e o outro não. Daí a outra empresa corre e implementa também, mesmo que na prática pouquíssima gente vai usar e que ajuda muito pouco no produto final.

Chega uma hora que as duas linguagens vão ficar tão cheias de recursos quase inúteis que vão ficar pesadonas, enormes e confusas, gerando códigos idem. Até que surja uma nova onda e comece tudo de novo.

É o ciclo da vida :slight_smile:

L

Antes de comentarem se gostaram ou não, vamos combinar uma coisa: o Java 7 é uma lenda urbana! Está no mesmo nível de Duke Nukem Forever e Chinese Democracy. De quando e quando, sempre lançam uma espécie de “novas features do Java 7”, mas esquecem que não há JSR, não há apoio (e com razão) da Apache e, possivelmente, do Google, e não há mais a aparente benevolência da Sun.

Talvez um dia saia, mas é de um futuro tão incerto que me faz pensar: pra que se preocupar tanto?

J

marcosalex:
Está acontecendo com o Java e C# o mesmo que aconteceu com o Delphi e VB: a MS lança uns recursos que atendem 0,001% de melhoria na produtividade e sai com um marketing de que possui o recurso e o outro não. Daí a outra empresa corre e implementa também, mesmo que na prática pouquíssima gente vai usar e que ajuda muito pouco no produto final.

Chega uma hora que as duas linguagens vão ficar tão cheias de recursos quase inúteis que vão ficar pesadonas, enormes e confusas, gerando códigos idem. Até que surja uma nova onda e comece tudo de novo.

como uma linguagem fica pesada?

M

Leonardo3001:
Antes de comentarem se gostaram ou não, vamos combinar uma coisa: o Java 7 é uma lenda urbana! Está no mesmo nível de Duke Nukem Forever e Chinese Democracy. De quando e quando, sempre lançam uma espécie de “novas features do Java 7”, mas esquecem que não há JSR, não há apoio (e com razão) da Apache e, possivelmente, do Google, e não há mais a aparente benevolência da Sun.

Talvez um dia saia, mas é de um futuro tão incerto que me faz pensar: pra que se preocupar tanto?

Pelo jeito, você não acompanha o desenvolvimento dele. hehehe
Ele tem o cronograma dos builds, as JSRs e os recursos planejados, está em desenvolvimento e tem data prevista, sim. Quaisquer alterações no cronograma costumam ser lançadas no site, que é de onde as pessoas aqui do forum buscam informações.

Era assim com a Sun, continua sendo com a Oracle, pelo menos até agora.

L

marcosalex:
Pelo jeito, você não acompanha o desenvolvimento dele. hehehe
Ele tem o cronograma dos builds, as JSRs e os recursos planejados, está em desenvolvimento e tem data prevista, sim. Quaisquer alterações no cronograma costumam ser lançadas no site, que é de onde as pessoas aqui do forum buscam informações.

Era assim com a Sun, continua sendo com a Oracle, pelo menos até agora.

Cite pra mim quais são essas JSRs, tem uma listinha aqui.

Ter cronograma não implica que vai ser respeitado (“Era assim com a Sun, continua sendo com a Oracle”).

Ter gente desenvolvendo não implica haver uma aprovação no JCP (“Era assim com a Sun, continua sendo com a Oracle”).

E

A resposta simples é “não”. Isso mesmo ele sendo um dos bugs mais votados,

http://bugs.sun.com/view_bug.do?bug_id=6530906

M

Realmente, você não acompanha o desenvolvimento. :lol: :lol: :lol:

Quando você estiver mais infomado, a gente retoma o diálogo, ok?

M

Dizem que sim, do mesmo modo que dizem que o Joda-Time vai entrar também, mas acredito que apenas o Joda entre.

L

mas agora, parando um pouco com o trollismo

toda linguagem de programação que quer atacar java, principalmente as de script (groovy, ruby, python) usam o mesmo exemplo, o de sempre e provavelmente o pior, que mostra N drawbacks da linguagem numa situação simples.

num código de abrir arquivo, o cara tem que lidar com Streams de baixo nível e muitos try/catches inúteis, checked exceptions etc parecem ser os primordiais pro Java virar alvo de críticas e mostrando como “qualquer linguagem é melhor”

não que isso tenha sido discutido nesse tópico, longe disso, mas é que os exemplos de código (que eu mesmo postei também rs) me fizeram lembrar de outros flamewars em fóruns ou até em livros o.O

M

Acho que é válido notar que vc pode escrever 1 linha de código ao invés de 20 para ler um arquivo. Mas se vc copia e cola no final não faz diferença.

D

Eu posso fazer assim no JAVA 7?

int codCadastro = 345;

try (Connection con = ConnectionFactory.getNewConnection();
      PreparedStatement ps;
      ResultSet rs; ) {

      String sql = "select * from cadastro where id = ?";
      ps = con.prepareStatement(sql);
      ps.setInteger(1, codCadastro);
      rs = ps.executeQuery();

      if (rs.next()) {
          //....
   
      }


} catch (Exception e) {
}

Ou seja, declarar objetos que quero fechar no try, sem inicializá-los dentro do mesmo? (vide os objetos rs e ps).
Gostaria de saber porquê eu acabo setando os demais objetos dentro do try…

E

Um exemplo simples. (Fiz um exemplo boboca, suficiente para ser compilado sem referência a nenhuma classe externa. Obviamente você vai usar seu ConnectionFactory mesmo.) Tratei a exceção só no bloco mais externo, que é o que você faria na verdade.

import java.sql.*;

class TesteTryWithResources {

    public static void main (String[] args) {
	int codCadastro = 345;  
	String sql = "select * from cadastro where id = ?";  
        String url = ".....";
   
	try (Connection con = DriverManager.getConnection (url)) {
            try (PreparedStatement ps = con.prepareStatement(sql)) {
                try (ResultSet rs = ps.executeQuery()) {
                    while (rs.next()) {
                    }
                }
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}
E

Outra forma, que é obviamente mais elegante, é:

import java.sql.*;

class TesteTryWithResources {

    public static void main (String[] args) {
        int codCadastro = 345;  
        String sql = "select * from cadastro where id = ?";  
        String url = ".....";
   
        try (
            Connection con = DriverManager.getConnection (url);
            PreparedStatement ps = con.prepareStatement(sql);
            ResultSet rs = ps.executeQuery()) {

            while (rs.next()) {
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
        }
    }
}
D

Legal…

Acho que no caso de ter muitas instruções intermediárias, seria melhor usar o try…with aninhado.

E

O C# aceitava apenas uma declaração no “using”, portanto é necessário fazer o equivalente do try aninhado (um monte de ‘usings’ aninhados). Isso é um porre (não sei se acertaram isso no c# 4.0)

No Java eles aprenderam a lição e é por isso que é possível declarar tudo que é necessário dentro dos parênteses de um único ‘try’.

L

Felagund:
marcosalex:
Está acontecendo com o Java e C# o mesmo que aconteceu com o Delphi e VB: a MS lança uns recursos que atendem 0,001% de melhoria na produtividade e sai com um marketing de que possui o recurso e o outro não. Daí a outra empresa corre e implementa também, mesmo que na prática pouquíssima gente vai usar e que ajuda muito pouco no produto final.

Chega uma hora que as duas linguagens vão ficar tão cheias de recursos quase inúteis que vão ficar pesadonas, enormes e confusas, gerando códigos idem. Até que surja uma nova onda e comece tudo de novo.

É o ciclo da vida :)

É, Rei Leão é da hora.

V

Acho que só pelo fato de que programadores inexperientes vão começar a fechar recursos corretamente já é um grande avanço.
Esse é um sintax suggar bastante significativo, como foi a inclusão do for each.

Não se trata apenas de um recurso estético, mas de uma forma de fornecer de maneira conveniente o tratamento correto.

Ah, entanglement, o C# já suportava multiplas inicializações no using, separadas por vírgula:
http://msdn.microsoft.com/en-us/library/yh598w02.aspx#Y220

Discordo fortemente de quem se refere isso a um recurso motivado pelo marketing.
Automatic Resource Management é um conceito bastante antigo, já surgido no C++ com o nome de RAII.

A técnica só obteve uma sintaxe mais limpa e elegante em C#, devido as características da linguagem, e agora o recurso vem para o Java.

E

Olhei a mais nova especificação da linguagem C# e ela diz que você pode ter várias inicializações, mas todas as variáveis têm de ser do mesmo tipo - ou seja, não dá para escrever o estrito equivalente do novo recurso do Java sem usar usings aninhados.

using (X x = new X(), y = new X(), z = new X()) 
{
    ...
}

O C# não força que você tenha de fazer uma declaração (como é o caso do Java); aceita expressões também. A expressão cria implicitamente uma variável local com o tipo de retorno da expressão (que pode ser bastante complexo, por sinal - veja o LINQ para ver como é possível criar tipos arbitrariamente complexos em C#); essa variável local “escondida” irá ter uma referência a esse objeto, que poderá ser fechado (“Dispose”) etc.

using (new Y()) 
      {
          ...
      }
L

ViniGodoy:

Discordo fortemente de quem se refere isso a um recurso motivado pelo marketing.
Automatic Resource Management é um conceito bastante antigo, já surgido no C++ com o nome de RAII.

Desnecessário dizer que Lisp tem isso desde antes do C++ existir.

Em Lisp a macro with-open-file já fecha o stream automaticamente, seja de forma normal ou por erro. Além das macros padrões, o desenvolvedor pode criar as suas próprias sintaxes para o que bem entender.

C++, assim como Java ou C#, não inventou nada.

E

http://www.paulgraham.com/icad.html

V

Não disse que o C++ estava inventando qualquer coisa. Disse que no C++, esse conceito surgiu com o nome de RAII, mas o conceito em si, não é invenção do C++, ou mesmo do LISP.
Estava apenas mostrando que no C++ esse conceito era usado, e foi extremamente fortificado, ao ponto de ser considerado um padrão.
E que a inserção dele no Java não se trata apenas de um syntax suggar, mas a fortificação de um detalhe bastante importante para justifica-lo.

O próprio Java já possuia APIs que implementavam o conceito (como as APIs de banco de dados do Spring).
Mas essa é uma sinalização clara, de que isso é importante, ao ponto de incluirem para isso um comando na linguagem, que certamente será cobrado dos desenvolvedores aspirando por uma certificação.

Acho extremamente válido que o Java também tenha colocado em sua linguagem estruturas próprias que demonstram essa preocupação em fechar recursos.
E que o conceito de automatic resource management tenha surgido no vocabulário “javanês” à partir de agora.

W

diego_qmota:
Eu posso fazer assim no JAVA 7?

int codCadastro = 345;

try (Connection con = ConnectionFactory.getNewConnection();
      PreparedStatement ps;
      ResultSet rs; ) {

      String sql = "select * from cadastro where id = ?";
      ps = con.prepareStatement(sql);
      ps.setInteger(1, codCadastro);
      rs = ps.executeQuery();

      if (rs.next()) {
          //....
   
      }


} catch (Exception e) {
}

Ou seja, declarar objetos que quero fechar no try, sem inicializá-los dentro do mesmo? (vide os objetos rs e ps).
Gostaria de saber porquê eu acabo setando os demais objetos dentro do try…


Se não me engano, tem que ficar tudo dentro do try nesse caso.

EDIT:
diego_qmota criou o tópico http://www.guj.com.br/java/250876-bloco-trywith-do-java-7

Criado 24 de agosto de 2010
Ultima resposta 25 de ago. de 2011
Respostas 48
Participantes 19