About method chaining. Why is giving nullPointerException?

2

I have the class Request:

package teste;

import java.util.ArrayList;
import java.util.List;

   public class Pedido {
     List<Item> lista = new ArrayList<Item>();;
     Cliente cliente;

     public Pedido adicionarPedido(int quantidade, String nome){

       lista.add(new Item(nome, quantidade));
       return this;
     }

     public Pedido paraOCliente(String nome){
        Cliente cliente = new Cliente(nome);
        return this;
     }

       public void fechar(){
           System.out.println("Nome " + this.cliente.getNome() + " " +  lista.get(0));
       }
}

The Client class:

package teste;

   public class Cliente {

     private String nome;

     public String getNome() {
        return nome;
     }

     public void setNome(String nome) {
       this.nome = nome;
     }

     public Cliente(String nome){
       this.nome = nome;
     }
}

The class Item:     package test;

   public class Item {

      private String nomeProduto;
      private int quantidade;

      public Item(String nome, int quantidade){
        this.nomeProduto = nome;
        this.quantidade = quantidade;
      }
  }

And the Main class:

package teste;

    public class Teste {

      public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Pedido().adicionarPedido(1, "tênis schutz")
                 .adicionarPedido(2, "iphone 7")
                 .paraOCliente("Aline Gonzaga")
                 .fechar(); 
    }
}

You're giving this problem:

Exception in thread "main" java.lang.NullPointerException
at teste.Pedido.fechar(Pedido.java:21)
at teste.Teste.main(Teste.java:10)

Can anyone tell me what the problem is, I can not see where it is ...

    
asked by anonymous 14.11.2016 / 19:45

2 answers

5

This is because the cliente variable was not initialized. The palliative solution should look something like this:

Cliente cliente = new Cliente();

Ideally, the Cliente class should be done differently, but that's another problem. The Pedido class also allows this kind of thing to happen. Ideally, the object is never in an invalid state. To do this the builder exists.

This method, in addition to not doing what you want, is not suitable because the object only works if it is called:

 public Pedido paraOCliente(String nome){
    Cliente cliente = new Cliente(nome);
    return this;
 }

This works, but still creates a design problem of the class:

 public Pedido paraOCliente(String nome){
    cliente = new Cliente(nome);
    return this;
 }

You are trying to use a pattern that is not suitable for this case. That's what I always say, following rules without knowing why. Use the constructor to have a correct object. Letting the members be initialized into parts is asking to have several problems. If you do not fix this the error may continue to happen. And as it probably will not be tested under faulty conditions (almost no programmer does this, people just want to see it working) the error will only be detected too late, since it will not appear up front.

    
14.11.2016 / 19:48
4
public Pedido paraOCliente(String nome){
    Cliente cliente = new Cliente(nome);
    return this;
 }

should be

  public Pedido paraOCliente(String nome){
        this.cliente = new Cliente(nome);

    return this;
 }
    
14.11.2016 / 19:48