The test part (main()) is an application which instantiates the class, not another class. The class by itself does nothing.
The following question is certainly beyond the scope of a beginning Java course, but you might as well be exposed to the general idea of protecting variables against concurrent access. What happens if - thinking of this as an analog - two librarians try to add a new book at the same time? Is is possible for one of them to get the nextId, and then before it is incremented, the other to also get the same nextId, resulting in two books with the same id?
It is definitely unlikely, but I'm not sure the possibility can be categorically excluded. For example, in a multi-threaded program where a
thread is interrupted at exactly the wrong instant and then another thread gets control. You're probably thinking, 'what is a thread?'. Imagine the logic of your program as a track, with two runners running down the track at the same time. Or in this situation, two librarians. There is a way to deal with this. A method to get the nextId could be written, and declared 'synchronized'.
private synchronized int getTheNextId()
{
return nextId++;
}
The constructor would call this method instead of accessing the nextId variable directly. Only one thread is allowed to go through this method at a time. You may be wondering how nextId could be read twice without it being incremented between the first and the second access. It depends on what kind of machine instructions the CPU is capable of executing and what kind of Java byte code is generated and what the JVM does. For example, there *could* be an atomic instruction at the hardware level which does all of this - atomic meaning something that can't be divided into any more parts - an all or nothing instruction as it were. I have seen processors with special registers which increment automatically when they are read. But the above Java code might also be implemented as several separate machine code instructions - one to read the value from memory into a register, another to increment the register, and another to write the register back to memory. If a thread were interrupted just after executing the first instruction, another thread could run through the same code, and also read the memory into a register in its own context (a context is each thread's copy of the register contents).