Concepts / Classes as Types

Classes as Types

Classes have a dual role: they can contain static members and describe objects.

  • Programming

A Word With Two Jobs

A common first impression is that a Java class has only one job. Some learners think a class is a container that holds static variables and subroutines, while others think a class is a description of what objects look like. Both impressions are incomplete. In Java, a class can serve both purposes at once.

This dual role is useful, but it can also be confusing. The word class refers both to a container and to a description of object structure. In this article you will trace what happens when a class name is used as a type, what an object gets from its class, and how the static part of a class differs from the part that each object carries for itself.

Using a Class Name as a Type

A class name can be used as a type. When you declare a variable with a class name as its type, that variable is meant to hold objects of that class. The type tells the program what kind of object the variable can refer to, and therefore which variables and subroutines can be reached through it.

book variabledeclared with type BookBook objectvariables and subroutinesdefined by Bookrefers to
When I declare a variable with a class as its type, what does the variable actually hold, and how does it refer to the object?

The diagram shows the key idea. The variable is declared with the class Book as its type, and it refers to a Book object. The variable does not contain the whole object's contents as a separate standalone thing. It is the handle through which the program reaches the object. Declaring the variable with a class type is what lets the program later use that object's variables and subroutines through the variable.

What an Object Gets From Its Class

The class defines an object's variables and subroutines. Each object created from the class has the variables and subroutines that the class describes, and each object can hold its own values for those variables. The class is the description; the object is one instance that follows that description.

java
Notes on the code
  • static int totalBooks belongs to the class itself
  • String title is a variable that each Book object has for itself
  • describe() is a subroutine that every Book object contains

This small class plays both roles described in the source. The static variable totalBooks is part of the class as a container. The variable title and the subroutine describe are the description of what every Book object contains. Notice that the class does not say what title is for any particular book. That is left for each object to decide when it is created.

Shared Structure Versus Individual Values

When several objects come from the same class, they share the same structure but not necessarily the same values. The class is the single blueprint: the names of the variables and the subroutines are defined once. Each object then keeps its own values for its instance variables. Two Book objects both have a title variable and a describe subroutine, but the first might hold Dune while the second holds Emma.

title variabledefined once in Bookfirst.titleDunedescribe subroutinedefined once in Booksecond.titleEmma
If several objects come from the same class, which parts are shared as the blueprint and which parts have their own separate values?
Worked example

Tracing two Book objects

Create two Book objects from the class above and determine which parts are shared and which are individual.

  1. 1
    Create the first object

    Book first = new Book("Dune"); The constructor sets title to Dune for this object only.

  2. 2
    Create the second object

    Book second = new Book("Emma"); The constructor sets title to Emma for this different object.

  3. 3
    Check the individual values

    first.title is Dune and second.title is Emma. Each object keeps its own title value.

  4. 4
    Check the shared structure

    Both objects have the same title variable and the same describe subroutine, because both were built from the Book class description.

  5. 5
    Check the static value

    totalBooks is not stored separately in each object. It is part of the class, so both constructor calls update the one shared count.

Result

The structure (variable names and subroutines) is shared through the class. The values of title are individual to each object. The count totalBooks is shared at the class level.

Output
Book: Dune
Book: Emma
2

Static Members Belong to the Class Itself

A static variable or static subroutine belongs to the class itself rather than to any one object. This is the container side of the dual role. The class can hold these static members whether or not any objects have been created, and it can also serve as the template from which objects are created. The concept map below shows both roles side by side.

Book classstatic container roletotalBooksobject descriptionroletitle and describeholds static membersdescribes objects
How does one class hold static members that belong to the class itself while also serving as the template for creating objects?

What do you think happens?

After the two Book objects from the earlier example are created, what does System.out.println(Book.totalBooks) print?

Reveal answer
Answer:

2

Each call to the Book constructor adds one to the static totalBooks variable. Both objects were created from the same class, so the single class-level count ends at 2. The name is written as Book.totalBooks because the variable belongs to the class rather than to a particular object.

Uniform Use of Objects

Because a class defines the variables and subroutines its objects contain, objects that share a common characteristic can be used in the same way. The source illustrates this with the PrintStream example: different objects can share a common subroutine such as println. Code that calls println on one PrintStream object can be written the same way as code that calls it on another, because both objects come from a class that defines that subroutine.

The practical benefit is that code can work with objects through the shared description they all follow. You do not need to rewrite the calling code for each individual object, as long as the objects share the structure the code relies on.

Mistakes Beginners Make With Classes as Types

  • Common mistake

    Thinking a class has only one job

    Why it fails

    The source is explicit that a class can both contain static variables and subroutines and describe objects. Treating it as only one of these hides how the same class name is used in both ways.

    Do this instead

    Keep both roles in mind: static members belong to the class itself, and the class also describes what each object contains.

  • Common mistake

    Assuming each object has its own copy of a static variable

    What it looks like

    static int totalBooks is updated by every Book constructor call, so it does not reset for each new object.

    Why it fails

    A static variable belongs to the class, not to any one object, so all objects of that class refer to the same static value.

    Do this instead

    Read static members as class-level data and instance variables as per-object data.

  • Common mistake

    Expecting a variable declared with a class type to contain no link to an object

    Why it fails

    A variable declared with a class as its type is used to hold objects of that class, and it is through that variable that the object's variables and subroutines are reached.

    Do this instead

    Think of the variable as the way the program reaches an object of that class, as shown in the first diagram.

  • Common mistake

    Confusing the variable name with the class name when calling a static member, such as writing a count through an object name instead of the class name

Trace the Count

EASY

Using the Book class from this article, add a third object with the title Ulysses. Before running anything, predict what Book.totalBooks prints after the third object is created, and what third.describe() prints.

Hints
  • Each call to the Book constructor adds one to totalBooks, and that variable belongs to the class.
  • The title of the third object is set only for that object, just as Dune and Emma were set for theirs.
  • describe() prints the title of the object it is called on.

Key Takeaways

  • A Java class has a dual role: it can contain static variables and subroutines that belong to the class itself, and it can describe the objects created from it.
  • A class name can be used as a type for variables that hold objects of that class.
  • The class defines an object's variables and subroutines, while each object can hold its own values for those variables.
  • Objects of the same class share the same structure, but their individual variable values can differ.
  • Because objects that share a common characteristic share subroutines such as println in the PrintStream example, they can be used in the same way by code.