W3docs

Java Classes and Objects

Define a Java class and create objects (instances) from it — the foundation of Java's object-oriented model.

A class is a definition; an object is an instance of that definition existing at runtime. The class describes what a Dog looks like and can do; an object is Rex, a specific dog living in memory while your program runs. Everything below builds on that distinction.

Defining a class

A class definition lives in its own .java file, named after the class. The body holds fields (the data each instance carries) and methods (the behavior each instance can perform).

public class Dog {
  String name;
  int    age;

  void describe() {
    System.out.println(name + ", age " + age);
  }
}

This declares a type. It does not create any dogs yet — exactly like writing int doesn't create an integer.

Creating an object with new

The new keyword asks the JVM to allocate space for one instance and hand back a reference to it:

Dog d = new Dog();

Three things happen on that line:

  1. Allocation. The JVM finds heap space big enough for a Dog.
  2. Default initialization. Each field gets a default value — null for objects, 0 for ints, false for booleans.
  3. Constructor call. The () invokes a constructor. We didn't write one, so Java supplied a default no-arg constructor that does nothing extra. The next chapter on constructors covers writing your own.

After this, d holds a reference — a tiny value that points at the heap object. The object itself is the bigger thing on the heap.

Reading and writing fields

You reach a field by writing <reference>.<field>:

d.name = "Rex";
d.age  = 3;
System.out.println(d.name);   // Rex

Field access is also how you call methods:

d.describe();    // Rex, age 3

The dot is the same in both cases; whether the right-hand side is a field or a method just depends on what follows.

References are not the object

This is the single most important sentence in this chapter: a variable of class type holds a reference, not the object itself.

Dog a = new Dog();
a.name = "Rex";

Dog b = a;           // copies the REFERENCE, not the dog
b.name = "Buddy";

System.out.println(a.name);   // Buddy

a and b point at the same heap object, so changing it through one is visible through the other. Compare with primitives:

int x = 5;
int y = x;       // copies the value
y = 9;
System.out.println(x);    // still 5

x and y are independent — primitives are copied by value. The chapter on pass-by-value goes deeper into what this means for method arguments.

null and NullPointerException

A reference variable can be null, meaning "doesn't point at any object":

Dog d = null;
d.describe();    // NullPointerException

null is what you get if you never assigned an object, or if a field of object type was never explicitly initialized. Dereferencing null (writing d.something when d == null) throws NullPointerException at runtime. Writing code that doesn't blow up on null is half of practical Java.

Warning
NullPointerException is a runtime error, not a compile error — the code compiles fine and only fails when that line actually runs. The fix is to make sure the variable points at a real object first (d = new Dog();) or to guard with a check (if (d != null) d.describe();) before dereferencing it.

Comparing objects: == vs equals

For references, == asks "do these two variables point at the same object?":

Dog a = new Dog();
Dog b = new Dog();
Dog c = a;

System.out.println(a == b);   // false — different objects
System.out.println(a == c);   // true  — same object

If you want to compare two objects' contents, you call an equals method instead — every class inherits a default one from Object, but the default just does reference equality. You override equals to mean what you want; see the equals & hashCode chapter later in this part.

One file, many objects

A single class definition supports unlimited instances. They all share the layout but each has its own state:

Dog rex   = new Dog();   rex.name   = "Rex";   rex.age   = 3;
Dog molly = new Dog();   molly.name = "Molly"; molly.age = 7;

rex.describe();     // Rex, age 3
molly.describe();   // Molly, age 7

A method like describe reads from this — the object it was called on — so the same code prints different output depending on which instance you call it on.

Where classes live

A .java file that declares public class Dog must be named Dog.java. You can have non-public classes in the same file, but only one public class per file, and its name has to match the filename. For small programs in this chapter we'll often put helper classes inside the same file as main using static nested classes, just to keep the example to one file.

A worked example

java— editable, runs on the server

What's next

You can declare a class and instantiate it, but so far the only field you've written has been "any value goes." The next chapter on class attributes goes through fields properly — declaration, defaults, instance vs class scope, and the conventions Java code follows.

Practice

Practice
Given Dog a = new Dog(); Dog b = a; b.name = 'Rex'; — what does System.out.println(a.name) print?
Given Dog a = new Dog(); Dog b = a; b.name = 'Rex'; — what does System.out.println(a.name) print?
Was this page helpful?