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:
- Allocation. The JVM finds heap space big enough for a
Dog. - Default initialization. Each field gets a default value —
nullfor objects,0for ints,falsefor booleans. - 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); // RexField access is also how you call methods:
d.describe(); // Rex, age 3The 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); // Buddya 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 5x 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(); // NullPointerExceptionnull 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.
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 objectIf 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 7A 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
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.