Why can not I access the elements inside an ArrayList with a for?

1

I'm trying to fill a JTable with elements that are inside an ArrayList, which is inside another object:

private void jButtonConfirmarProdutoActionPerformed(java.awt.event.ActionEvent evt) {                                                        
    modProduto.setQuantidade(Integer.parseInt(jTextFieldQnt.getText()));
    modVenda.itens.add(modProduto);
    jTable1 = ctrl.fillTable(jTable1, modVenda);
}   

These are the classes:

public class ModeloVenda {

    private int idVenda;
    private String data;
    private float valorVenda;
    private int idCliente;
    public final ArrayList<ModeloProduto> itens;
}

public class ModeloProduto {
    private int id_produto;
    private String nome;
    private float preco_compra;
    private float preco_venda;
    private int quantidade;
    private int fornecedor;

public float calculaTotal(int quantidade){
    return preco_venda*quantidade;
}}

This is the function that populates the table:

public JTable fillTable(JTable tabela, ModeloVenda mod){
    ArrayList data = new ArrayList();
    String[] Collums= new String[]{"Nome", "Valor Unitário", "Quantidade", "Valor Total"};
    for(int i = 0; i < mod.itens.size(); i++){
        dados.add(new Object[]{mod.itens.get(i).getNome(), 
            mod.itens.get(i).getPreco_venda(), mod.itens.get(i).getQuantidade(), 
            mod.itens.get(i).calculaTotal(mod.itens.get(i).getQuantidade())});
    }
    ModeloTabela modelo = new ModeloTabela(dados, Colunas);
    tabela.setModel(modelo);

    for(int i = 0; i<Colunas.length; i++){
        tabela.getColumnModel().getColumn(i).setPreferredWidth(150);
        tabela.getColumnModel().getColumn(i).setResizable(false);
    }
    tabela.getTableHeader().setReorderingAllowed(false);
    tabela.setAutoResizeMode(tabela.AUTO_RESIZE_OFF);
    tabela.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    return tabela;
}

But when I add another element in the array and update the table all elements are replaced by the new one:

    
asked by anonymous 01.12.2016 / 19:18

1 answer

2

Let's suppose you have an item class:

public class Item {

  String descricao;

  public String getDescricao() {
    return descricao;
  }

  public void setDescricao(String descricao) {
    this.descricao = descricao;
  }

  @Override
  public String toString() {
    return this.descricao;
  }
}

And have the following method:

List<Item> itens = new ArrayList<>();
Item item = new Item();

item.setDescricao("Descrição A");
itens.add(item);
item.setDescricao("Descrição B");
itens.add(item);
item.setDescricao("Descrição C");
itens.add(item);

System.out.println(itens);

The output would be:

  

[Description C, Description C, Description C]

Why?

Because you just instantiated each item, so by changing some property you just changed the original item and replicated references to the same item in your list.

And how to solve?

The correct one would be to create an instance for each item as follows:

List<Item> itens = new ArrayList<>();

Item itemA = new Item();
itemA.setDescricao("Descrição A");
itens.add(itemA);
Item itemB = new Item();

itemB.setDescricao("Descrição B");
itens.add(itemB);

Item itemC = new Item();
itemC.setDescricao("Descrição C");
itens.add(itemC);

System.out.println(itens);

Where the output would be:

  

[Description A, Description B, Description C]

And where does this fit into the problem?

In the jButtonConfirmarProdutoActionPerformed method, you have to create a new modProduto for each time you add to the list otherwise it will be, just like in the example, just replicating the reference to a single object.

    
02.12.2016 / 01:09