Creating Classes and Objects
Explore the fundamentals of object-oriented programming by learning how to define classes as blueprints and create objects as instances in Java. Understand fields and methods, use constructors for initialization, and organize code with packages to manage complex data effectively while maintaining independent object states.
Up to this point, we have relied on Java’s primitive types to store simple values like numbers and characters. However, real-world software rarely deals with isolated numbers; it models complex entities like users, bank accounts, or inventory items.
To manage this complexity, Java allows us to create our own custom data types. We define the structure and behavior of these types in a single class definition, and then we use that blueprint to build as many specific instances as our application requires.
From primitives to blueprints
If we were building a warehouse simulation, we might need to track a robot’s name and battery level. Using only primitives, we would create separate variables:
String robotName = "R2";int robotBattery = 100;
This approach breaks down quickly if we have fifty robots. We would need one hundred unrelated variables, making it impossible to track which battery level belongs to which robot.
Java solves this with classes and objects.
Class: This is the blueprint or template. It defines what a “Robot” looks like (it has a name and a battery level) and what it can do.
Object: This is a specific instance built from that blueprint. “R2” is one object; “C3” is another.
Crucially, because “R2” and “C3” are created from the same class, they possess the exact same attributes and behavior. We do not need to rewrite the logic for batteryLevel or work() for each new robot. We write the code once in the class, and every object follows that logic automatically.
We write the class code once, but we can create thousands of unique objects from it.
Defining a class and fields
We define a class using the class keyword. Inside the class, we declare variables called fields (also known as instance variables). These fields represent the state of an object.
Note: In Java, each public class is typically defined in its own file matching the class name. For the examples below, we have created a file named Robot.java for the class definition.
Here, we define a simple Java class named Robot.
Line 1: We declare a new custom type named
Robot. By convention, class names start with an uppercase letter.Lines 3–4: We define two fields:
name(to store text) andbatteryLevel(to store an integer). EveryRobotobject we create will have its own copy of these variables.
Adding behavior with methods
Objects do not just store data; they perform actions. We define these actions using methods inside the class. Unlike the static methods we wrote previously, these instance methods operate directly on the object’s data. They can access and modify the fields we defined.
Line 4: We assign a default value of
100tobatteryLevel. Every new robot will start fully charged.Lines 7–10: The
introducemethod prints the specific values ofnameandbatteryLevelfor the robot calling the method.Lines 13–16: The
workmethod simulates activity by printing a message and decreasing thebatteryLevelfield by 10.
Instantiating objects
A class definition does not run by itself. To use it, we must create an instance of the class (an object) in memory. We do this using the new keyword.
The new keyword allocates memory for the object and returns a reference to it. We store this reference in a variable of the class type.
In line 5, Robot myBot declares a variable that can hold a reference to a Robot object. The = new Robot() creates the actual object in memory and assigns its address to myBot.
Accessing members with dot notation
Once we have an object reference, we access fields and methods using the dot operator (.). This allows us to read or write to the object’s fields and call its methods.
Line 8: We use
myBot.nameto assign the string “R2” to thenamefield of this specific object.Line 11: We call
myBot.introduce(), which executes the code inside theintroducemethod usingmyBot’s data.Line 12: We call
myBot.work(), which reduces the battery level by 10.Line 15: We call the
introduce()method again shows the updated battery level (90%).
Independent state
The power of object-oriented programming lies in independence. If we create multiple objects of the same class, each maintains its own storage. Changing the fields of one object does not affect the others.
Lines 5–6: We allocate two separate
Robotobjects in memory.bot1points to the first,bot2points to the second.Lines 9–10: We assign different names.
bot1.namebecomes Alpha, whilebot2.namebecomes Beta.Line 13: We call
work()only onbot1. This reducesbot1’s battery to 90.Lines 17 and 20:
bot1reports 90% battery, whilebot2remains at the default 100%. The state ofbot2is untouched by the actions ofbot1.
Classes enable us to model systems in which many independent actors (such as robots, users, or buttons) coexist and interact without their data becoming confused. We accessed fields like name directly (bot1.name = "Alpha"). While this is simple, it leaves our data vulnerable to invalid changes.