7.1 From Parallel Arrays to Objects
Prerequisites: Variables, Arrays, and Methods
Estimated time: 25 minutes
You are ready to continue when: You can distinguish between classes, objects, fields, and reference variables, and draw alias relationships between objects
A library program needs a title, author, ISBN, price, and borrowing state for every book. The books below are fictional practice data; the ISBN is a placeholder, with no format validation yet. Storing each field in a separate array produces this design:
String[] titles = new String[1000];
String[] authors = new String[1000];
String[] isbns = new String[1000];
double[] prices = new double[1000];
boolean[] borrowed = new boolean[1000];The 17th position must always represent the same book across the five arrays. When adding, deleting, or sorting by title, if you miss updating one array, the data will become misaligned.
1. Defining a Class Creates a Type, and Objects Store Instance State
class Book {
String title;
String author;
String isbn;
double price;
boolean borrowed;
}Book is a class. It declares what fields each Book object has. Objects are specific instances created during program execution, and each object has its own set of instance fields.
public class Library {
public static void main(String[] args) {
Book first = new Book();
first.title = "Java Study Notes";
first.author = "Lin";
first.isbn = "ISBN-DEMO-001";
first.price = 99.0;
Book second = new Book();
second.title = "Computer Systems Notes";
System.out.println(first.title);
System.out.println(second.title);
}
}After saving both classes in Library.java, compile and run it as in earlier chapters, the output is:
Java Study Notes
Computer Systems NotesA source file can have at most one public top-level class, and the filename must match the class name. Here, Library is public, and Book uses package-level visibility, so they can coexist in Library.java.
2. What new Book() Does
When new Book() is executed, Java creates a Book object. It first sets the instance fields to their default values, then executes the field initializers, initialization blocks, and the selected constructor. Since the current class does not have an explicitly defined constructor, the compiler provides a default no-argument constructor. The constructors lesson will explain this rule.
Book book = new Book();
System.out.println(book.title); // null
System.out.println(book.price); // 0.0
System.out.println(book.borrowed); // falseThe language specification does not require you to describe local reference variables as "necessarily on the stack," nor should you refer to reference values as operable raw memory addresses. A reliable source code model is:
bookis a variable of typeBook;- It can hold a reference value of some
Bookobject, or it can holdnull; - Instance members of an object can be accessed through a non-null reference.
JVM implementations use stack frames, the heap, and runtime optimizations. Escape analysis and other optimizations can change physical storage; object semantics do not depend on guessing an address.
3. Assigning and Copying Reference Values, Not Object Copies
Book first = new Book();
first.title = "Java Study Notes";
Book alias = first;
alias.title = "Revised Java Study Notes";
System.out.println(first.title);
// Revised Java Study NotesAt this point, there is only one Book object, and both first and alias store references to it. The two variables are called aliases. When drawing, separate "variables" and "objects":
first ──┐
├──> Book object { title = "Revised Java Study Notes" }
alias ──┘If you run alias = new Book() again, it will only make alias point to a new object, while first still points to the old object.
first == alias compares whether two references point to the same object, not the content of the fields. To compare by content, the class must define the equals contract, which will be covered in the subsequent chapter on object methods.
4. null Represents the Current Lack of Object References
Book selected = null;
// System.out.println(selected.title); // NullPointerExceptionAccessing an instance field or method of a null reference will fail. When designing APIs, it is important to explicitly determine whether null is allowed; if "non-existence" is a normal business state, further study of empty collections, Optional, or specialized state objects can be undertaken later.
Setting a variable to null only breaks that single reference. An object is only eligible for garbage collection when it is no longer reachable. The exact timing of collection is not guaranteed, and null should not be used as a manual release command.
5. Keep Related Data Together
Parallel arrays organize data by "all book titles, all authors"; Book[] organizes data by "each book":
Book[] shelf = new Book[2];
shelf[0] = first;
shelf[1] = new Book();Note that new Book[2] only creates two reference components, defaulting them to null and not automatically creating two books.
A class keeps fields together and places borrowing, returning, and validation rules next to them. In the next lesson, we'll add behavior to Book.
Professional Glossary
| Term | Precise Definition |
|---|---|
| Class | A program structure that declares type members and object behaviors |
| Object | A class instance or an array; this page focuses on Book instances |
| Instance Field | State owned by each object |
| Reference Variable | A variable that stores an object reference or null |
| Alias | Multiple reference values pointing to the same object |
| Identity Comparison | a == b Checks if two references point to the same object |
Before Moving On
Convert the five parallel arrays into two Book objects and one Book[], marking the array components as initially null. Then, draw separately Book book, new Book(), alias = book, and alias = new Book(); variables, reference values, and objects should not be combined into a single box. Setting variables to null should only break one reference, not equal to immediately reclaiming the object.
→ Next: Fields, Methods, and this
Specification: JLS §15.9: Class Instance Creation Expressions.