Por que usar o método dispose() em uma janela?

Existe uma boa razão para usar o método dispose() para fechar uma janela?

Ou é melhor usar setVisible(false) ?

Sei que dispose() libera alguns recursos, mas ainda é possível reabrir a janela.

É bom utilizar setVisible(true),
e com relação ao dispose, uma serventia é para quanto você ter uma janela principal
onde essa janela pode abrir outras janelas, quando for fechas as outra(s) janela(s) você
utiliza dispose(), porque caso você use System.exit(0), você terminará a execução do
programa, e com dispose não. Entendeu?

[quote=WendersonLP]É bom utilizar setVisible(true),
e com relação ao dispose, uma serventia é para quanto você ter uma janela principal
onde essa janela pode abrir outras janelas, quando for fechas as outra(s) janela(s) você
utiliza dispose(), porque caso você use System.exit(0), você terminará a execução do
programa, e com dispose não. Entendeu?[/quote]

Sim, isso eu já sabia.

Pelo que entendi, as vantagens de usar dispose() são:

  1. Liberar a memória que a janela está utilizando;

  2. Se fechar todas as janelas usando dispose(), a máquina virtual será encerrada (na maioria das vezes). Se fechar usando setVisible() o programa continuará executando, apesar de nenhuma janela estar visível.

http://java.sun.com/javase/6/docs/api/java/awt/Window.html#dispose()

1 curtida

Isso mesmo, não utilize setVisible(false), a janela estará aberta, mas não visível, e com dispose não
ela fechará e sairá da memória.

[quote=WendersonLP]Isso mesmo, não utilize setVisible(false), a janela estará aberta, mas não visível, e com dispose não
ela fechará e sairá da memória.[/quote]

O que o dispose faz é liberar os recursos do sistema operacional relacionados a janela. Mas a memória ocupada pela parte java da janela (textfields, botões, etc) permanece lá.
Funciona assim, quando você abre uma janela, o java solicita ao SO um objeto Window, com um Canvas. E desenha lá os objetos java que você colocou. É esse objeto window, com esse canvas que são liberados no dispose. Caso a janela seja criada novamente, um novo objeto window será solicitado, mas como a parte java (descrição de que botões, labels, etc a janela tem) não foi liberada, ele pode redesenhar tudo.

Para realmente liberar a janela da memória, você deve além de chamar o dispose() fazer como toda variável java: remover as referências a janela.

1 curtida

Mas o Garbage Collector não faz isso?

Não.

Pense no Garbage Collector como uma arrumadeira que limpa o chão, mas não pega a toalha molhada que você deixou sobre a cama e a põe no cabide.

É que ela limpa o chão (porque sabe que o que está no chão e ninguém está referenciando é lixo mesmo) mas não tira a toalha molhada porque acha que você ainda a está usando (mesmo que você largue o raio da toalha e não passe no seu quarto por um mês :slight_smile:

Se você não remover as referências à janela, ela não morre sozinha. Você precisa pegar o raio da toalha molhada e:

a) OU a jogar no lixo ou deixá-la no chão, ou
b) Deixá-la no cabide.

entanglement, obrigado pelo esclarecimento mas qual a maneira correta de remover esse objeto? definindo ele como null?

Como se faz com todos os objetos em java, definindo todas as variáveis que apontam para ele como null.
Atenção especial no caso de JInternalFrames, pois eles deverão ser removidos do DesktopPane também.

Em java, a única maneira de um objeto ser coletado é se não houver mais referências para ele.

Como se faz com todos os objetos em java, definindo todas as variáveis que apontam para ele como null.
Atenção especial no caso de JInternalFrames, pois eles deverão ser removidos do DesktopPane também.

Em java, a única maneira de um objeto ser coletado é se não houver mais referências para ele.[/quote]

Aí eu discordo. Não precisa e nem é recomendável ficar definindo todas as variáveis como null explicitamente, pois deixa o código mais difícil de ler. O correto é remover referências quando necessário e deixar as coisas saírem de escopo naturalmente quando não são mais usadas, isto é, usar o mínimo de variáveis globais.

Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes :slight_smile: )

[quote=entanglement]Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes :slight_smile: )

[/quote]

Oi,

Bom… mas não vai fazer tanto efeito assim. Digo isso de forma perceptível, a não ser que a pessoa utilize umas 300 “aberturas e fechamentos” da janela.

Se é que me entende.

Tchauzin!

[quote=entanglement]Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes :slight_smile: )

[/quote]

É aí que entra o método dispose(), que é a razão desse tópico existir.

[quote=lina][quote=entanglement]Sei.
É que normalmente em código de GUI as referências para janelas não estão em variáveis locais (que irão naturalmente sair de escopo uma vez que a rotina for concluída - e nesse caso, e apenas nesse caso, o que o ceklock disse tem sentido) e sim em membros da classe que abriu a tal da janela.
Portanto, nesse caso, se a classe precisar fechar a janela, terá de setar explicitamente essa referência para null (obviamente tem de dar o dispose antes :slight_smile: )

[/quote]

Oi,

Bom… mas não vai fazer tanto efeito assim. Digo isso de forma perceptível, a não ser que a pessoa utilize umas 300 “aberturas e fechamentos” da janela.

Se é que me entende.

Tchauzin![/quote]

Exato.

Oi,

A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).

O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)

Tchauzin!

[quote=lina]Oi,

A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).

O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)

Tchauzin![/quote]

dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória se a janela não for mais usada em nenhum outro lugar. Se não tiver mais referências à janela o Garbage Collector vai simplesmente se livrar da janela.

[quote=ceklock][quote=lina]Oi,

A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).

O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)

Tchauzin![/quote]

dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória.
[/quote]

Oi,

Eu entendi ao contrário…

Exemplo:

Fechando:

Janela teste = new Janela().setVisible(true); teste.dispose();

Liberando da memoria:

Janela teste = new Janela().setVisible(true); teste.dispose(); teste = null;

Tchauzin!

De qualquer forma, é necessário lembrar que toda vez que se usa um sistema operacional como o Windows ou o Linux, você tem o conceito de objetos (“recursos”) que são solicitados ao sistema operacional e cujo ciclo de vida é controlado por ele. Entre esses objetos, estão: janelas, arquivos em disco, sockets, semáforos, memória compartilhada etc. Quando se usa bancos de dados, além disso temos as conexões.
Tais recursos são finitos e devem ser devolvidos depois de usados.
A devolução pode representar um simples fechamento (no caso de arquivos, onde o fechamento indica apenas que você não quer mais lidar com esse arquivo - talvez você também queira efetivar suas ultimas alterações) ou então a prõpria destruição do recurso (como costuma ser o caso das janelas).
No caso do AWT e do Swing, a palavra-chave usada para dispor (devolver) o recurso finito que é a janela é “dispose”.
No caso do java.io, a palavra-chave usada para devolver o recurso (arquivo) é “close”.
O “garbage collector” lida com apenas um tipo de recurso finito, que é a memória usada por seu programa. Não é atribuição dele sair limpando outros tipos de recursos.
Como certo “abuso”, pode-se entretanto abusar do “garbage collector” para que ele, de vez em quando, também limpe outros tipos de recursos (nesse caso, se o recurso estiver em uma classe que implementa o método finalize - http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#finalize() .
E é por isso que certos professores ingênuos (daqueles que largam uma toalha molhada em cima da cama e esperam que alguém vá recolhê-la automaticamente) ensinam que arquivos não precisam ser fechados, porque o “garbage collector” irá fazer isso. Isso é um abuso e nunca deve ser feito, na verdade.
Atenção: isso é realmente um “abuso” porque uma classe que implementa esse método indica ao garbage collector que objetos dessa classe que não são mais referenciados são postos em uma lista de objetos a serem “finalizados”, mas essa finalização fica a critério do garbage collector e não é determinística (ou seja, pode ser que um objeto marcado para ser finalizado nunca o seja dentro do tempo de execução de seu programa).

[quote=lina][quote=ceklock][quote=lina]Oi,

A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).

O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)

Tchauzin![/quote]

dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória.
[/quote]

Oi,

Eu entendi ao contrário…

Exemplo:

Fechando:

Janela teste = new Janela().setVisible(true); teste.dispose();

Liberando da memoria:

Janela teste = new Janela().setVisible(true); teste.dispose(); teste = null;

Tchauzin![/quote]

Eu sempre fiz assim e vou continuar fazendo:

JFrame f = new JFrame(); ... f.setVisible(true); ... f.dispose();

Não precisa de f = null;

[quote=ceklock][quote=lina][quote=ceklock][quote=lina]Oi,

A principio, isso me parece um ponto negativo da linguagem (eu não esperava ter que dizer isso um dia).

O Java ou a linguagem deveria interpretar que determinado comando, como o dispose(), deveria remover toda a referência do objeto. A não ser que exista uma razão muito complexa para que isso não aconteça. (?!)

Tchauzin![/quote]

dispose() não faz isso? Pelo que pude entender até agora toda a janela e os componentes associados a ela são liberados da memória.
[/quote]

Oi,

Eu entendi ao contrário…

Exemplo:

Fechando:

Janela teste = new Janela().setVisible(true); teste.dispose();

Liberando da memoria:

Janela teste = new Janela().setVisible(true); teste.dispose(); teste = null;

Tchauzin![/quote]

Eu sempre fiz assim e vou continuar fazendo:

JFrame f = new JFrame(); ... f.setVisible(true); ... f.dispose();

Não precisa de f = null;
[/quote]

Oi,

Eu também sempre fiz dessa forma. Mas depois disso:

Como se faz com todos os objetos em java, definindo todas as variáveis que apontam para ele como null.
Atenção especial no caso de JInternalFrames, pois eles deverão ser removidos do DesktopPane também.

Em java, a única maneira de um objeto ser coletado é se não houver mais referências para ele.[/quote]

Começarei a colocar null. Né?

Tchauzin!