An initialization issue

exercise No. 216

Q:

We consider a class representing book instances containing a compiler error in line 3:

01 public class Book {
02 
03    final int numberOfPages; // Error: Variable 'numberOfPages' 
04                             //might not have been initialized
05    String title;
06
07    public Book(final String title, final int numberOfPages) {
08        this.numberOfPages = numberOfPages;
09        this.title = title;
10    }
11
12    public Book() {}
13 }

Answer the following questions:

  1. Why is numberOfPages in contrast to title being flagged for »possibly not being initialized«?

  2. The instance variable numberOfPages does get initialized in Line 8. Why does the error appear anyway?

  3. Give a sensitive way solving the problem

Tip

Consider the default constructor's role.

A:

Having two constructors public Book(String, int) and public Book() there are thus two ways creating book instances:

  • // Neither numberOfPages nor title will be initialized
    final book = new Book();
  • // Both numberOfPages and title will be initialized
    final book = new Book("Learning Java", 120);

The three answers thus are:

  1. title is being declared without using final and may thus be assigned or changed at any time after instance creation.

    On contrary numberOfPages is being declared as final. Therefore initialization can only happen (once) at object creation time. The initialization must thus be part of every constructor within class Book.

  2. Initialization does happen in Book(String, int) but not within the default constructor public Book(). This allows for numberOfPages not being initialized during instance creation. The final modifier disallows any subsequent assignment.

  3. There are multiple solutions resolving the issue:

    1. Removing the final modifier in the definition of numberOfPages:

      01 public class Book {
      02 
      03    int numberOfPages;  
      04                             
      05    String title; ...
    2. Adding a parameter numberOfPages to the default constructor as well:

      01 public class Book {
      02 
      03    final int numberOfPages;  
            ...
      12    public Book(final int numberOfPages) {this.numberOfPages = numberOfPages;}
      13 }
    3. Assigning a default value:

      01 public class Book {
      02 
      03    final int numberOfPages;  
            ....
      12    public Book() {this.numberOfPages = 0;}
      13 }

      Albeit being syntactically possible this solution obviously lacks consistency since any book of zero pages does not make sense.