Duvida simples, mas interessante

11 respostas
H

Eu tava lendo um topico do forum sobre construcao de model em JTable e me deparei com 1 codigo q me deixou em duvida:

public class SimpleTableModel extends AbstractTableModel{

    private ArrayList linhas = null;
    private String [] colunas = null;
    public SimpleTableModel(ArrayList dados, String[] colunas){
    setLinhas(dados);
    setColunas(colunas);}
    public String[] getColunas() {return colunas;}
    public ArrayList getLinhas() {return linhas;}
    public void setColunas(String[] strings) {colunas = strings;}
    public void setLinhas(ArrayList list) {linhas = list;}

}


public JTable createJTable() {

    ArrayList dados = new ArrayList();
    String[] colunas = new String[] { "Estado", "Cidade" };

    // Alimenta as linhas de dados
    dados.add(new String[] { "SP", "São Paulo" });
    dados.add(new String[] { "RJ", "Rio de Janeiro" });
    dados.add(new String[] { "RN", "Rio Grande do Norte" });
    dados.add(new String[] { "ES", "Espirito Santo" });

    SimpleTableModel modelo = new SimpleTableModel(dados, colunas); //ATENTAR AQUI!!!
    JTable jtable = new JTable(modelo);
    jtable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    return jtable;

}

Qnd eu uso o metodo “SimpleTableModel modelo = new SimpleTableModel(dados, colunas);” a variavel dados eh local e desaparece qnd o metodo finaliza, correto? na parte “setLinhas(dados)” do construtor ele ta chamando “public void setLinhas(ArrayList list) {linhas = list;}” e ai q eu pergunto: na parte “linhas = list”, linhas ta apontando p msm area da variavel list (ou seja ambos estao apontados p msm area de memoria)? ou eh feita 1 copia igual a de list p/a variavel linhas e ambas ficam c msm conteudo porem em areas distintas(caso muda 1 n ira alterar o outro)?

Me ajudem ai, eu pensei q acontecia ambos apontar p msm area, mas pela logica n eh assim, ocorrera copia igual, porem em areas distintas. Fiquei confuso e queria saber o q ocorre realmente.

11 Respostas

louds

Já pensou em testar para ver o que acontece?

H

pow eu sabia q iam dizer isso, eh pq como eu tava lendo a parada d JTable ai n kis para, mas se n conseguir nd por aki, vo testar dps sim, vlws

Mantu

Olha, até onde eu sei, tanto dados, quanto linhas, quanto list, todos apontam para o mesmo local da memória… São diferentes referências apontando para um mesmo conteúdo. Se vc alterar os dados através da variável dados, acho que vai interferir na tabela sim, a menos que o construtor que foi implementado pelo criador da SiompleTableModel previna tal situação, clonando o ArrayList e passando tal clone para o atributo linhas

H

eu n sei se me expressei direito, mas em resumo eu queria saber se qnd eu passo uma arraylist por parametro e atribuo ela a outra arraylist, ai uma copia eh criada ou apenas e referencia eh copiada. Tipo assim:

setDados(dados) {

list = dados; // list aponta p msm canto de dados ou eh criada uma copia d dados p list?

}

pelo q saiba eu pensava q ambos iriam apontar p msm canto, mas pela logica do metodo createJTable, creio eu q n daria certo, pois dps q o metodo createJTable termina ai o ArrayList dados eh destruido e daria pau no ArrayList linhas (q estaria apontando p msm area q foi apagada c a finalizacao do createJTable), mas se uma copiada indepedente eh criada e atribuida ao ArrayList linhas, ai isso n ocorre (penso assim).

ps: isso reforca a ideia q n existe passagem por referencia em Java (se n me engano eu li isso)

Mantu

Ah, saquei sua dúvida!
Assim: Existe um ArrayList na memória, certo? Vamos chamar esse ArrayList alocado na memória apenas de objAL, ok? Só pra facilitar. dados e list serão chamadas de referências, blz?
Lá naquele seu primeiro exemplo, nós temos, em um tal método createJTable, a seguinte linha de código

ArrayList dados = new ArrayList()

O que acontece aqui? São criadas duas “coisas”, basicamente, nesse momento: uma referência chamada dados e uma instancia de um objeto ArrayList, que no caso é o nosso objAL. Perceba que a referência dados e o objAL estão associados. É através da referência dados que conseguimos manipular o objAL(Como pode ser visto através da invocação do método add, por exemplo). Quando passamos a referência dados para o construtor da SimpleTableModel, o objAL passa a estar associado com duas referências: com a dados que foi declarada no método createJTable, e também com a dados, diferente da primeira, declarada na assinatura do construtor da classe SimpleTableModel.
O construtor, por sua vez, invoca o método setLinhas(ArrayList), e passa a referência dados por parâmetro. Isso agora faz com que objAL esteja associado com 3 referências: dados de createJTable(…), dados de SimpleTableModel(…) e list de setLinhas(…). O método setLinhas(…) faz esse número aumentar pra 4 quando ele, atravez da instrução …

linhas = list;

… associa o objAL também a referência linhas, que é um atributo da classe JTableModel.
Agora é o momento em que sua dúvida toma lugar, pois logo após esta intrução, o método setLinhas(…) é encerrado e list “morre”. Perceba que list não é a instância para o ArrayList, é apenas um referência para tal instância, é apenas uma referência para o nosso objAL. Imagine que o objAL é um balão que tem infinitas cordas a ele amarrado, e que cada referência é uma mão que segura uma corda qualquer dessas. Quando o método setLinhas(…) é encerrado, a única coisa que acontece com o objAL é que a sua “corda” que estava sendo segurada pela referência list é “solta”; list “solta” objAL depois de “morrer”. Da mesma forma, dados(do construtor da SimpleTableModel) vai também soltar a corda quando o construtor terminar sua execução e retornar o controle para o método createJTable. Neste exato momento momento, lá no método createJTable, a referência modelo é associada a uma instância de SimpleTableModel(implementação da dita classe lá na memória, da mesma forma que o nosso objAL). Nesse momento, como estão as “cordas” do objAL? Assim: uma está sendo segurada pela referência dados, que pertence ao método createJTable, e uma segunda corda está sendo segurada pela referência linhas, que por sua vez está contido dentro da referência modelo(pois linhas é um atributo da classe cuja determinada instância está associada a modelo).
Quando o método createJTable terminar, a referência dados vai morrer e, assim, largar sua “corda”, desassociar-se do objAL. Daí então podemos ser levados a pensar…

“hlds”:

[…]dps q o metodo createJTable termina ai o ArrayList dados eh destruido e daria pau no ArrayList linhas (q estaria apontando p msm area q foi apagada c a finalizacao do createJTable)[…]

Isso não ocorre! Por quê? Simples: objAL, sendo um “balão”, só se perderá quando ninguém mais o estiver segurando, o que não necessariamente está acontecendo…
Um pouco ante de o createJTable(…) terminar, ele pegou a referência modelo e passou pro construtor da JTable, que por sua vez, internamente, vai “segurar uma corda” da intância de SimpleTableModel referenciada pela referência modelo. Quando o createJTable termina, ele retorna para seja-lá-quem-for-que-o-invocou a referência “jtable”, a qual está associada, está segurando a corda de uma instância da classe JTable.
Vamos supor que o método seja-lá-quem-for-que-invocou-o-createJTable tenha feito a invocação do createJTable(…) com a linha…

JTable myTable = createJTable(...);

Nesse caso, aquela referência jtable(do createJTable(…)) morre, larga a corda, e myTable pega uma corda e segura a instancia de JTable. Segura JTable, que segura SimpleTableModel, que segura ArrayList, e este ArrayList é o nosso objAL.
Conseguiu ver por que aquilo que vc imaginou não acontece? Percebe que o “balão” do ArrayList, o objAL, não foi largado em nenhum momento desde sua criação?
Mas agora vc pode perguntar: “P@$*#! Mas isso não é passagem por referência!!?”
Não é. Pelo menos não como é a dita passagem em C e C++. Como assim? Vamos olhar para o construtor SimpleTableModel(ArrayList dados,…) e para o método setLinhas(ArrayList list). Suponha que o código do setLinhas(…) seja assim:

list = new ArrayList(0);
linhas = list;

Se em Java tivesse passagem por referência, como há no C/C++, o nosso objAL, que tinha vários elementos(“São Paulo”, “Rio de Janeiro”, etc), passaria a ser agora um ArrayList vazio. Mas isso não acontesse em Java. O que aconteceria se o código acima fosse o código do setLinhas(ArrayList list), seria a referência list largar o balão objAL, que lhe foi entrege pela referência dados(do construtor), e pegar a corda de um outro balão(associar-se a uma outra instância de ArrayList, uma que tem 0 posições) e passar esse balão pra referência “linhas”(atributo da classe SimpleTableModel). Quando o controle voltar ao contrutor, a sua referência dados ainda vai estar segurando objAL, mas a referência que representa o atributo linhas vai estar segurando um outro ArrayList, que naum tem nada a ver com o objAL.

Espero que tenha ajudado, ou pelo menos não complicado mais ainda as coisas… :lol:
Qq coisa, poste mais, ok? :thumbup:

louds

Java possui apenas passagem por valor.
Java usa apenas referencias para objetos.
Logo, sempre que você atribuir ou passar como parâmetro um objeto apenas a referência a ele é copiada, ele permanece intacto.

Aproveitando, por favor, evita escrever em “internetes” porque fica meio dificil para os que falam português traduzirem.

H

Mantu, perfeita tua ajuda, ainda bem q 1 me entendeu, eu testei aki isso e aconteceu isso q vc falou. Ou seja, a variavel “dados” vai p espaco mas como a variavel “linhas” fica apontando p o ArrayList, este ArrayList n sera excluido pelo Garbage Collector (q por teoria so recolhe as variaveis sem referencia). Tanto q no programa eu coloquei p imprimir a referencia das 2 variaveis e elas apontavam p msm refrencia ou seja NAO sao criadas 2 copias independetes e SIM, elas dividem msm area da memoria. Fechado o assunto??? :smiley:

H

Agora teoricamente eu sei q Java NAO tem passagem por referencia, mas eh dificil entrar na minha cabeca q essa passagem de objeto n seria uma especie de passagem por referencia, possa ser q nem seja igua a C/C++, mas q na logica, p mim, isso seria passagem por referencia, seria sim , mas ai sao outros 500 :smiley:

louds

Java suporta passagem de referência, mas não passagem por referencia. :lol: :lol:

Passagem por referência implica que alterar o valor do parâmetro vai alterar o valor na origem. Isso significa que você poderia trocar qual objeto é apontado pela variavel passada para o método.

A confusão com C++ é pelo fato da notação do Java ser a mesma para um valor e um ponteiro para um valor (int var X Object var).

H

concordo vc, n pode alterar a referencia da variavel q eh passada por parametro (no caso “dados” do metodo createJTable), mas vc pode acessar o q ela ta referenciando, ou seja c a varriavel “dados” do construtor eu poderia alterar o ArrayList q esta sendo apontado e isso axo q tem caracteristicas da passagem por referencia.

H

Vlw tds pela ajuda, inclusive o Mantus q escreveu 1 texto mto bom.

Criado 12 de junho de 2006
Ultima resposta 17 de jun. de 2006
Respostas 11
Participantes 3