Problem overview
A ticket machine gives every new ticket the next number: 1, then 2, and so on. The class Ticket does the same. Each ticket keeps its own name and number, but the counter that hands out the numbers belongs to the class itself, not to any single ticket. In Java that is a static member: one copy, shared by every ticket.
The class has three parts:
Ticket(name)adds 1 to the counter and gives the new ticket that value as its number.- The static method
issued()returns how many tickets were created since the last reset. - The static method
resetCounter()sets the counter back to 0, so the next ticket gets number 1 again.
Creating tickets for Ann, Bob and Cy after a reset gives them the numbers 1, 2 and 3, and issued() returns 3. With no tickets created, issued() returns 0. Two tickets for the same name still get different numbers, because the number comes from the counter, not from the name.
Approach: instance fields and static fields
Every ordinary field, such as name, exists once per object. A static field exists once per class. That is exactly the split this problem needs: name and number are different for every ticket, while the counter must be one value that all tickets see and change.
The key detail is that each ticket copies the counter's value into its own number at the moment it is created. The counter keeps moving as more tickets are made, but a ticket's number is its own field and doesn't move with it. If the code printed the shared counter instead of each ticket's own number, every ticket would show the last value.
Step by step
- Declare the counter as
public static int count = 0at the top of the class. The initializer runs once, when the class is loaded. - Declare the per-ticket fields
nameandnumberwithoutstatic, so each ticket has its own. - Store the name in the constructor with
this.name = name. - Add 1 to the counter with
count++. Every ticket made counts once, whatever its name. - Copy the counter into the ticket's number with
this.number = count. The counter has just been increased, so the first ticket after a reset gets 1. issuedreturnscount.resetCounterassigns 0 tocount.
The solution in Java
class Ticket {
public static int count = 0;
public String name;
public int number;
public Ticket(String name) {
this.name = name;
count++;
this.number = count;
}
public static int issued() {
return count;
}
public static void resetCounter() {
count = 0;
}
}
Things worth knowing about static members:
- You call a static method on the class name:
Ticket.issued(), with no ticket needed. For that reason a static method can use only static members. It has nothis, because no particular ticket is involved. - A constructor and instance methods can use static fields freely. Inside the class you write just
count; outside it you writeTicket.count. - Java also lets you write
someTicket.count, but it still reads the shared field, which is misleading. Prefer the class name.
Using the class
Ticket.resetCounter();
Ticket x = new Ticket("Ann");
Ticket y = new Ticket("Bob");
Ticket z = new Ticket("Cy");
System.out.println(x.name + " #" + x.number);
System.out.println(y.name + " #" + y.number);
System.out.println(z.name + " #" + z.number);
System.out.println(Ticket.issued());
Ticket.resetCounter();
System.out.println(Ticket.issued());
Ticket m = new Ticket("Mia");
System.out.println(m.number + " " + x.number + " " + Ticket.issued());
prints:
Ann #1
Bob #2
Cy #3
3
0
1 1 1
The last line shows both ideas. After the reset, Mia is ticket 1, and Ann's ticket still has number 1 as well, because a reset changes only the counter, not the tickets already made.
Why a reset matters
The counter is static, so it lives as long as the program does, not as long as any one ticket. Creating tickets in a second round without resetting would continue from the last number: after tickets 1, 2 and 3, the next ticket is 4. That is why a fresh round starts with resetCounter(): it sets the one shared value back to 0 and the next ticket is number 1 again. Tickets made before the reset keep their numbers, because those numbers were copied into their own fields.
Common mistakes
- Printing the counter instead of the ticket's number. If the tickets are printed after all are created, this version shows the same value for everyone:
It printsSystem.out.println(x.name + " #" + Ticket.count); System.out.println(y.name + " #" + Ticket.count); System.out.println(z.name + " #" + Ticket.count);Ann #3,Bob #3andCy #3. Each ticket must store its own number in the constructor. - Making
numberstatic. Then there is one number for all tickets, and every ticket would report the latest one. - Making
countan instance field. Each ticket would start its own counter at 0, so every ticket would get number 1 andissued()would not compile as a static method. - Increasing the counter after copying it. If
this.number = countruns beforecount++, numbers start at 0. - Using
thisin a static method. It doesn't compile, because a static method isn't called on any ticket.
Complexity
The constructor and both static methods do a constant amount of work, so each is O(1). Each ticket stores two values, a name and a number, and the class stores one counter.
