How do I solve the problem of this instantiation?

Asked

Viewed 49 times

-1

program class

package application;
 
import java.util.Locale;
import java.util.Scanner;
 
import model.entities.Account;
import model.exceptions.DomainException;
 
public class Program {
 
    public static void main(String[] args) {
        Locale.setDefault(Locale.US);
        Scanner sc = new Scanner(System.in);
 
        try {
            System.out.println("Enter account data");
            System.out.print("Number: ");
            int number = sc.nextInt();
            System.out.print("Holder: ");
            sc.nextLine();
            String holder = sc.nextLine();
            System.out.print("Initial balance: ");
            double initialBalance = sc.nextDouble();
            System.out.print("Witdraw Limit: ");
            double withdrawLimit = sc.nextDouble();
 
            Account account = new Account(number, holder, initialBalance, withdrawLimit);
 
            System.out.println();
            System.out.print("Enter amount for withdraw: ");
            double amount = sc.nextDouble();
            account.withdraw(amount);
 
            System.out.println("New balance: " + String.format("%.2f", account.getBalance()));
            
        } catch (DomainException e) {
            System.out.println("Witdraw Error: " + e.getMessage());
        } 
 
        sc.close();
    }
 
}

account class

package model.entities;
 
import model.exceptions.DomainException;
 
public class Account {
 
    private Integer number;
    private String holder;
    private Double balance;
    private Double withdrawLimit;
    
    public Account() {
    }
 
    public Account(Integer number, String holder, Double initialBalance, Double withdrawLimit) {
        this.number = number;
        this.holder = holder;
        this.withdrawLimit = withdrawLimit;
        deposit(initialBalance);
    }
 
    public Integer getNumber() {
        return number;
    }
 
    public void setNumber(Integer number) {
        this.number = number;
    }
 
    public String getHolder() {
        return holder;
    }
 
    public void setHolder(String holder) {
        this.holder = holder;
    }
 
    public Double getWithdrawLimit() {
        return withdrawLimit;
    }
 
    public void setWithdrawLimit(Double withdrawLimit) {
        this.withdrawLimit = withdrawLimit;
    }
 
    public Double getBalance() {
        return balance;
    }
    
    public void deposit(Double amount) {
        balance += amount;
    }
    
    public void withdraw(Double amount) throws DomainException{
        if (amount > balance) {
            throw new DomainException("Not enough balance");
        } else if (amount > withdrawLimit) {
            throw new DomainException("The amount exceeds withdraw limit");
        }
        balance -= amount;
    }
}

Domainexception class

package model.exceptions;
 
public class DomainException extends Exception {
    private static final long serialVersionUID = 1L;
 
    public DomainException(String msg) {
        super(msg);
    }
}

Error message:

Exception in thread "main" java.lang.NullPointerException
    at model.entities.Account.deposit(Account.java:51)
    at model.entities.Account.<init>(Account.java:19)
    at application.Program.main(Program.java:27)

I don’t know why you’re making a mistake, since the mistake is about the method deposit(). The method deposit() where it is used to deposit the balance initial instead of "set" this balance direct. If I take the variable type of the balance, deposit() class Double for the guy double works.

And why if I did the direct instantiation:

    this.number = number;
            this.holder = holder;
            this.balance = balance;
            this.withdrawLimit = withdrawLimit;
        }

Instead of:

public Account(Integer number, String holder, Double initialBalance, Double withdrawLimit) {
            this.number = number;
            this.holder = holder;
            this.withdrawLimit = withdrawLimit;
            deposit(initialBalance);
        }

It would work?

  • Hello @Rq, welcome to Sopt, you wanted to say instantiation? But from what I saw in your code your problem is more with the call than with instance.

2 answers

2


This is because Double is a class and double is a primitive type (in Java there is this differentiation, in other languages, not necessarily). And each type has a value default which is used when it is not initialized.

See here that there is a table (in the section Default Values) that says fields of the type double are initialized with zero while objects (such as Double) are initialized with null.

That’s why it works when you use it double, but not with Double, for this will be null and it will not be possible to perform any operation with it (that is why the NullPointerException).

So the solution is to initialize the values, not only to "satisfy the language bureaucracy," but also to make it clear in the code that it starts at zero:

public Account(Integer number, String holder, Double initialBalance, Double withdrawLimit) {
    this.number = number;
    this.holder = holder;
    this.withdrawLimit = withdrawLimit;
    this.balance = 0.0; // setar para zero
    deposit(initialBalance);
}

Although in this case it makes no sense to start with zero just to add another value right away, then it could also be:

public Account(Integer number, String holder, Double initialBalance, Double withdrawLimit) {
    this.number = number;
    this.holder = holder;
    this.withdrawLimit = withdrawLimit;
    this.balance = initialBalance;
}

Unless, of course, the method deposit has some additional logic, and that is necessary to initialize the instance. But as in this case it only adds up to the current balance (which in turn starts with zero), I don’t know if I would need to call it in the builder.


Another point is to check if you really need to use the Wrappers, because the fields could just be:

private int number;
private double balance;
private double withdrawLimit;

When performing operations (such as summation and subtraction) in types such as Double, is made the autoboxing and autounboxing, that despite being "transparent" for the programmer, have their cost (in addition to hiding "traps" like this, the NullPointerException). There are also other differences, which are explained in more detail here.

What about the use of double to represent money, read here and here.

1

In the Account class you started the following variables, as follows:

private Integer number;
private String holder;
private Double balance;
private Double withdrawLimit;

All these variables have by default a value equal to null, so if you try to add something to null, it will result in a Nullpointerexception.

It can be verified by writing the following line of code before the variables are initialized in the Constructor of the class Accounts:

System.out.print(this.number + " : " + this.holder + " : " + this.balance + " : " + this.withdrawLimit);

To resolve:

1 - Or set a value for the variable early on:

private Double balance = 0.0;

2 - Or change the type of the variable to "double", because the type double has a default value of 0.0, whereas the type "Double" has the default value of null:

private double balance;

The same applies for example for the type "Integer" that has the default value of null, but if it is of type "int" has the default value of 0.

3 - Or start it in the Constructor:

public Account(Integer number, String holder, Double initialBalance, Double withdrawLimit) {
        this.number = number;
        this.holder = holder;
        this.balance = 0.0;
        this.withdrawLimit = withdrawLimit;
        deposit(initialBalance);
    }

4 - Or start the variable with the initial value:

public Account(Integer number, String holder, Double initialBalance, Double withdrawLimit) {
        this.number = number;
        this.holder = holder;
        this.balance = initialBalance;
        this.withdrawLimit = withdrawLimit;
    }

Finally, why the this.balance = initialBalance; work, it is because you are starting that variable with a value and not doing an operation with its value (you cannot do operations with a null value).

I hope you answered the question and also helped him, any questions just ask :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.