ledgeJumper
ledgeJumper

Reputation: 3630

How to increment a field member in a java class each time a new one is instantiated

VERY new to Java, so I am feeling like a child right now. The joys of learning a new language I guess.

Here is my Invoice Class:

public class Invoice {
//member inits
private int numberOfInvoices = 0;
private String companyName;
private double amountDue;
private String chargeDate;
private static int invoiceNumber = 0;


//constructor
public Invoice(String _companyName, double _amountDue, String _chargeDate)
{
    numberOfInvoices++;
    companyName = _companyName;
    amountDue = _amountDue;
    chargeDate = _chargeDate;
    invoiceNumber = numberOfInvoices;
}

//getters
public String getCompanyName()
{
    return companyName;
}

public double getAmountDue()
{
    return amountDue;
}

public String getChargeDate()
{
    return chargeDate;
}

public int getInvoiceNumber()
{
    invoiceNumber = numberOfInvoices + 1;
    return invoiceNumber;
}

//setters
public void setCompanyName(String _companyName)
{
    companyName = _companyName;
}

public void setAmountDue(double _amountDue)
{
    amountDue = _amountDue;
}

public void setChargeDate(String _chargeDate)
{
    chargeDate = _chargeDate;
}
//helpers
public int incrementInvoices()
{
    return numberOfInvoices++;
}
}

And here is the main method where I am trying to create three of these invoices, but increment the invoice number each time a new one is created.

public class InvoiceCreator {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    Invoice invoice1 = new Invoice("Amazing Software", 5000.00, "January 18, 2009");
    System.out.println(invoice1);

    Invoice invoice2 = new Invoice("Best Programs", 4000.00, "February 18, 2009");
    System.out.println(invoice2);

    Invoice invoice3 = new Invoice("Champion Code", 3000.00, "March 18, 2009");
    System.out.println(invoice3);
}
}

I'm also new to the IDE (netbeans), but through debugging and looking at each of the classes I created, all the fields are being initialized correctly, but the invoiceNumber = 1 on every one of them.

What am I doing incorrectly here?

Upvotes: 7

Views: 20918

Answers (9)

Moritz Petersen
Moritz Petersen

Reputation: 13057

numberOfInvoices should be static. invoiceNumber should not be static. And you should synchronize the access to this field. See also: What is the best way to increase number of locks?

Upvotes: 1

Aleks G
Aleks G

Reputation: 57316

You declared invoiceNumber as static, but numberOfInvoices is not static. In your constructor you are incrementing the number of invoices - which, being non-static, is initialised to 0 every time you create an instance of it. Then you assign this value to your invoice number.

The simple fix for your case is to declare the numberOfInvoices as static and invoiceNumber as non static:

private static int numberOfInvoices = 0;
private int invoiceNumber;

then you'll get the desired behaviour.

At the same time, it's worth noting that this implementation is ok for the purpose of learning the language, however it will not work for a production system, because the number will still be reset to 0 when the application exits and is restarted. In a production system, you would want to keep this number in a database or external file somewhere. You would then need to ensure that it's incremented in a thread-safe manner. In a production system, your logic would be something like this:

private int invoiceNumber;
private Object sync;

public Invoice(...) {
    synchronised(sync) {
        invoiceNumber = loadLastInvoiceNumberFromStorage();
        invoiceNumber++;
        writeLastInvoiceNumberFromStorage(invoiceNumber);
    }

    ...
}

Upvotes: 1

waldol1
waldol1

Reputation: 1881

You need to use a static field to generate incremental invoice numbers, not store the individual invoice numbers.

Try this:

public class Invoice {
//member inits
private static int nextInvoiceNumber = 0;
private String companyName;
private double amountDue;
private String chargeDate;
private int invoiceNumber = 0;


//constructor
public Invoice(String _companyName, double _amountDue, String _chargeDate)
{
    invoiceNumber = nextInvoiceNumber;
    nextInvoiceNumber++;
    companyName = _companyName;
    amountDue = _amountDue;
    chargeDate = _chargeDate;

}
....

Upvotes: 7

Julien Bodin
Julien Bodin

Reputation: 803

You should declare your numberOfInvoices member as a static member :

private static int numberOfInvoices = 0;

This way all Invoice instance will share this member. If you don't declare it each Invoice instance will have their own value.

Upvotes: 0

stinepike
stinepike

Reputation: 54682

use

private static int numberOfInvoices = 0;

Reason:

Static variables are related to class while nonstatic variables are related to object. As in this case you are storing the count of the object of the class so this is related to class. Thus you have to store it as static variable ( also called class variable)

For more details see here

Upvotes: 0

Adarsh
Adarsh

Reputation: 3641

numberOfInvoices will always be 0 when a new object is created. So, everytime you increment it and assign it to invoiceNumber, invoiceNumber gets the value 1. Instead, why dont you directly increment invoiceNumber .

Upvotes: 0

Mena
Mena

Reputation: 48404

You could use a static field numberOfInvoices in your class, and increment it in the constructor. Then you could have a static getter for the field.

Upvotes: 0

Dave Newton
Dave Newton

Reputation: 160191

numberOfInvoices isn't the static member.

You currently increment an instance property and set it to the static property.

I suspect you want the opposite.

Upvotes: 0

Andy Thomas
Andy Thomas

Reputation: 86411

Declare numberOfInvoices to be static, so that there is a single value for the entire class, rather than a separate value for each instance.

 private static int numberOfInvoices = 0;

Upvotes: 2

Related Questions