Classes and Objects in Java
-
Last Updated: February 4, 2025
-
By: javahandson
-
Series
Learn Java in a easy way
Understand Classes and Objects in Java with clear explanations, real-world examples, object creation steps, memory concepts (heap vs stack), constructors, methods, and best practices. A complete beginner-friendly guide to master core Java fundamentals.
When we begin our journey with Java, one of the first and most important concepts we encounter is the concept of classes and objects. These are not just basic topics—they form the foundation of everything we build in Java. Almost every concept we learn later, whether it is inheritance, polymorphism, or even frameworks like Spring, is built on top of these two ideas.
To truly understand Java, we need to clearly understand what classes and objects are and how they work together to model real-world problems.
In simple terms, a class in Java is a blueprint for creating objects. It defines the structure and behavior of the objects created from it. However, at this stage, it is only a logical definition—it does not represent anything real yet.
When we create a class, we describe what kind of data an object should hold and what operations it should perform. For example, if we think about a Car, we can define properties such as color, brand, and speed, along with actions like start, stop, and accelerate. All of this goes inside a class.
It is important to understand that a class does not occupy memory for real-world usage in the way objects do. It simply acts as a guide or a plan. We can think of it as instructions that tell Java how to create an object and how it should behave.
An object is the actual implementation of a class. When we create an object, we use the class’s blueprint to construct a concrete instance in memory.
Unlike a class, an object exists at runtime and occupies memory in the heap. It represents a real entity that has both state and behavior. The state refers to the data it holds, and the behavior refers to the actions it can perform.
For instance, if we have a Car class, we can create an object like myCar. This object will have actual values, such as a specific color and speed. So while the class defines what a car is, the object represents a specific car.
To make this concept more intuitive, let us relate it to a real-world example. Consider a Student.
We can define a Student class that contains common properties such as name, age, and marks. However, this class itself does not represent any particular student. It only defines what a student should look like.
Now, when we create objects like Suraj, Amar, or Iqbal, each of them becomes an individual student with their own data. Suraj might be a different age and have different marks than Amar. Even though they are created from the same class, each object is unique.
Another simple way to understand this is by thinking about a house. The class is like a blueprint, and the object is the actual house built using that blueprint. We can build multiple houses from the same design, but each house exists independently.
A class in Java is a blueprint or template for creating objects. It defines the structure and behavior of the objects created from it. When we write a class, we are essentially describing a new type in Java.
At this stage, a class does not represent a real entity. It is only a logical definition. The actual entities are created later when we create objects from the class. This separation between definition (class) and instance (object) is what makes Java powerful and flexible.
For example, if we want to represent a student in our application, we can create a Student class. This class will define what information a student should have and what actions a student can perform. Later, we can create multiple student objects from this class, each having its own data.
We can clearly understand a class by thinking of it as a blueprint.
A blueprint defines how something should be built, but it is not the actual thing. In the same way, a class defines how objects should be structured and how they should behave, but it does not create any real objects by itself.
Let’s take a simple example of a Car class. It may define:
However, until we create an object, there is no actual car in memory. Once we create objects like car1 or car2, each object becomes a real entity with its own data.
This is why we say: A class is a blueprint, and objects are real instances created from it.
The structure of a class in Java is simple and consistent. We define a class using the class keyword, followed by the class name and its body.
class ClassName {
// fields
// constructors
// methods
}
Here, the class body is written inside curly braces { }. Inside this body, we define everything that belongs to the class.
There are a few important conventions we follow:
Following these conventions makes our code more readable and professional.
A class is not just a container. It is composed of different components that together define an object’s complete behavior.
The most important components of a class are:
Fields (variables) → represent data or state
Methods → represent behavior or actions
Constructors → initialize objects
Let us understand each of these in detail.
Fields are variables declared inside a class. They represent the data that an object holds.
For example, in a Student class, we may define fields like name and age. These fields will store the values for each student object. Every object created from the class will have its own copy of these fields.
So, fields define an object’s state, and that state can vary from one object to another.
Methods define an object’s behavior. They represent what an object can do.
For example, in a Student class, we may have a method to display student details or calculate grades. Methods usually work with data stored in fields and perform operations on it.
In simple terms:
A constructor is a special part of a class that is used to initialize objects.
Whenever we create an object, the constructor is automatically called. It helps us assign initial values to the object’s fields. The constructor has the same name as the class and has no return type.
For example, when we create a Student object, the constructor can assign values to the name and age at creation.
Let us now see a simple and complete example:
class Student {
String name;
int age;
Student(String studentName, int studentAge) {
name = studentName;
age = studentAge;
}
void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
In this example, we can clearly identify all the components of a class:
Fields → name, age
Constructor → Student(String studentName, int studentAge)
Method → displayDetails()
This class defines what a student should look like and what they can do. Later, we can create multiple student objects from this class.
Once we understand what a class is, the next step is to understand objects, because this is where our program actually starts working with real data.
A class only defines a structure, but an object is the actual entity created using that structure. When we create an object, Java allocates memory and gives us something we can work with at runtime. This is why objects are often referred to as the real-world representation of a class.
An object is simply an instance of a class. In other words, it is a concrete realization of the blueprint that we defined earlier.
When we create an object:
For example, if we define a Student class, we can create multiple objects such as student1, student2, and student3. Even though all these objects are created from the same class, each one is independent and can store different values.
This is a key idea: A class is common, but objects are unique.
To understand objects more clearly, we need a basic idea of how memory works in Java. Don’t worry—we will keep this simple.
Whenever we create an object, Java uses two types of memory:
Heap memory → where the actual object is created
Stack memory → where the reference variable is stored
Let us look at an example:
Student s1 = new Student("Suraj", 40);
Here’s what happens internally:
new Student("Suraj", 40) creates an object in the heap memorys1 is a reference variable stored in the stack memorySo, we are not directly accessing the object. Instead, we use the reference (s1) to interact with it. This concept becomes very important later, when we deal with topics such as memory management, garbage collection, and object references.
Every object in Java is defined by two important characteristics:
State → the data stored inside the object
Behavior → the actions the object can perform
For example, if we consider a Car object:
start(), stop(), and accelerate()Each object maintains its own state. Even if we create multiple objects from the same class, their data can be different. However, all objects share the same behavior defined in the class.
This combination of state and behavior is what allows us to model real-world entities effectively in Java.
Let us look at a simple example to make this clear:
class Student {
String name;
int age;
void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
student1.name = "Suraj";
student1.age = 40;
student1.displayDetails();
}
}
Output:
Name: Suraj
Age: 40
In this example, we first define a Student class. Then, inside the main() method, we create an object using the new keyword.
The object student1:
name and age)displayDetails() to perform an actionThis clearly shows how an object holds both state and behavior.
Now that we understand what classes and objects are, the next step is to see how we actually create and use them in a Java program. This is one of the most important parts for beginners, as it is where theory turns into practice.
We will go step by step so that we clearly understand what is happening at each stage.
Step 1: Define a Class – This is where we decide what data the object will hold and what actions it can perform.
Let us create a simple Student class:
class Student {
String name;
int age;
void displayDetails() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
In this class, we have:
Two fields → name and age
One method → displayDetails()
At this point, we have only defined the structure. No object has been created yet.
Step 2: Create an Object Using new – Once the class is defined, we can create an object using the new keyword.
Student student1 = new Student();
Here’s what is happening:
Student → tells Java the type of object we are creatingnew Student() → creates a new object in memorystudent1 → is a reference variable that points to that objectSo now, we have a real object in memory that we can work with.
Step 3: Access Fields and Methods – After creating the object, we can access its fields and methods using the dot (.) operator.
student1.name = "Suraj"; student1.age = 40; student1.displayDetails();
Here:
This is how we interact with objects in Java.
So far, we have seen how to create objects using the new keyword. However, to truly understand Java—and to stand out in interviews—we need to go one level deeper and understand what actually happens internally when we create an object.
When we write a simple line like:
Student s1 = new Student("Suraj", 40);
It may look straightforward, but Java performs several important steps behind the scenes. Understanding this flow will give us a much clearer picture of how objects are created and managed in memory.
When we use the new keyword, Java performs the following sequence of operations:
Let us go through each of these steps in detail.
a. Memory Allocation in Heap – The first thing Java does is allocate memory for the object on the heap. The heap is the area where all objects are stored. The JVM determines how much memory is required based on the fields defined in the class. Once the memory is allocated, the object is created in the heap.
At this point, the object exists in memory but is not fully initialized.
b. Default Values Initialization – After allocating memory, Java automatically assigns default values to all the fields of the object.
For example:
int → 0
double → 0.0
boolean → false
Object references → null
This step ensures that the object is in a valid and predictable state even before we explicitly assign values. So even if we do not initialize fields manually, Java guarantees that they will not contain garbage values.
c. Constructor Invocation – Once default values are assigned, Java calls the class’s constructor. The constructor is responsible for initializing the object with meaningful values. In our example:
Student(String name, int age) {
this.name = name;
this.age = age;
}
The constructor takes the values “Suraj” and 40 and assigns them to the object’s fields.
This is the step where the object becomes properly initialized and ready to use.
d. Reference Assignment – Finally, the reference variable is assigned to point to the object created in the heap.
Student s1 = new Student("Suraj", 40);
Here:
From this point onward, we use s1 to access the object’s fields and methods.
We can think of the process like this:
new → creates an object in the heap
Default values → assigned automatically
Constructor → sets actual values
Reference → connects us to the object
This entire process happens very quickly, but understanding it helps us write better and more efficient code. This internal flow is not just theoretical. It helps us understand:
These concepts are frequently asked in interviews and are crucial for understanding advanced topics such as garbage collection, object lifecycles, and memory optimization.
When we work with classes in Java, variables can exist at different levels depending on where and how they are declared. Understanding these types is very important because it directly affects how memory is used and how data behaves in our program.
In a class, we mainly deal with three types of variables:
Let us understand each one in detail.
Instance variables are variables declared inside a class but outside any method. These variables belong to an object, not the class itself.
This means that every object created from the class will have its own copy of instance variables. As a result, the values of instance variables can differ from one object to another.
For example, in a Student class, fields like name and age are instance variables. Each student object will have its own name and age.
Static variables are declared using the static keyword. Unlike instance variables, they belong to the class rather than to individual objects.
This means:
Static variables are useful when we want to maintain data that is common across all objects, such as a counter or configuration value.
Local variables are declared inside methods, constructors, or blocks. These variables are temporary and exist only during the execution of that method.
They do not belong to the class or the object. Instead, they are created when the method is called and destroyed once the method completes.
We can read more about variables in this article Class Members in Java
Now that we understand how data is stored in a class, the next step is to understand how we define behavior. This is where methods come into the picture.
A method is a block of code that defines what an object can do. It represents an object’s behavior and typically operates on data stored in its fields. In other words, a method is simply a function defined inside a class. It allows us to perform operations on data. For example, in a Student class, we may have methods to display details, calculate grades, or update marks.
So, while fields represent state, methods represent behavior.
Method Syntax:
The general structure of a method looks like this:
returnType methodName(parameters) {
// method body
}
For example:
void displayDetails() {
System.out.println("Displaying details");
}
Here:
void → return typedisplayDetails → method name() → parameters (empty in this case)Once a method is defined, we can call it using an object.
Student student1 = new Student(); student1.displayDetails();
Here, we use the student1 object to call the method. This is how objects interact with methods in Java.
We can read more about methods in this article Class Members in Java
Constructors are a very important part of a class because they help us initialize objects properly at the time of creation. A constructor is a special block in a class that is automatically called when we create an object. It is mainly used to initialize the object’s fields with meaningful values.
Key characteristics:
Constructor vs Method
Although constructors look similar to methods, they are different:
Understanding this difference is very important for beginners.
We can read more about constructors in this article Class Members in Java
The this keyword is a small concept, but it is extremely powerful and commonly used in Java.
It refers to the current object on which the method or constructor is being executed.
a. Referring to the Current Object – We use this to refer to the current object.
For example:
this.name = name;
Here:
this.name → instance variable
name → parameter
This helps Java distinguish between the two.
b. Resolving Ambiguity – Sometimes, parameter names and instance variable names are the same. In such cases, this helps resolve ambiguity.
class Student {
String name;
Student(String name) {
this.name = name;
}
}
}
Without this, Java would get confused about which name we are referring to.
c. Calling Another Constructor (this()) – We can also use this() to call another constructor from within the same class.
class Student {
String name;
int age;
Student() {
this("Unknown", 0);
}
Student(String name, int age) {
this.name = name;
this.age = age;
}
}
This helps us reuse constructor logic and avoid code duplication.
So far, we have been working with a single object. However, in real-world applications, we rarely deal with just one object. Instead, we create multiple objects of the same class, and each behaves independently.
Understanding this concept is very important because it helps us visualize how Java models real-world scenarios. Once we define a class, we can create as many objects as we want using that class. Each object is created using the new keyword and stored in a separate reference variable.
For example, if we have a Student class, we can create multiple student objects like this:
Student student1 = new Student(); Student student2 = new Student(); Student student3 = new Student();
Even though all these objects are created from the same class, they are completely separate entities in memory.
Each Object Has Its Own Data.
One of the most important things to understand is that each object maintains its own state.
This means:
For example, if we assign different values to each object:
student1.name = "Suraj"; student2.name = "Amar"; student3.name = "Iqbal";
Each object now holds its own unique data, even though they all belong to the same class.
This is exactly how real-world entities behave. Even if multiple students belong to the same category, each student has their own identity and data.
Let us look at a complete example:
class Student {
String name;
int age;
void displayDetails() {
System.out.println("Name: " + name + ", Age: " + age);
}
}
public class Main {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1.name = "Suraj";
s1.age = 40;
s2.name = "Iqbal";
s2.age = 38;
s1.displayDetails();
s2.displayDetails();
}
}
Output:
Name: Suraj, Age: 40
Name: Iqbal, Age: 38
In this example:
s1 and s2Even though s1 and s2 are created from the same class:
This is a powerful concept because it allows us to create scalable and flexible applications. We can reuse the same class to create multiple objects without rewriting code.
As we start writing classes and working with objects, following a few best practices can make our code cleaner, more maintainable, and easier to understand.
a. Naming Conventions – We should always follow standard Java naming conventions.
Using meaningful names helps others (and even us later) easily understand the code’s purpose.
b. Keep Classes Focused (Single Responsibility) – A class should ideally have one responsibility. This means it should represent a single concept or entity.
For example, a Student class should handle student-related data and behavior. It should not handle unrelated tasks like database operations or file handling.
Keeping classes focused makes the code easier to maintain and extend.
c. Avoid Too Many Responsibilities in One Class – When we try to put too much logic into a single class, it becomes difficult to manage and understand.
Instead of creating large, complex classes, we should break them into smaller, well-defined classes. This improves readability and reduces the chances of errors.
In this article, we explored one of the most fundamental concepts in Java—classes and objects. We started by understanding what a class is and how it acts as a blueprint. Then we saw how objects are created from that blueprint and how they represent real entities in memory. We also learned how to create classes and objects step by step, how variables and methods work, and what happens internally when an object is created.
Along the way, we also covered important supporting concepts such as constructors, the this keyword, memory representation, and how multiple objects behave independently. Finally, we discussed common mistakes and best practices that help us write better code. If we simplify everything, we can say:
Once we are comfortable with these concepts, we are well prepared to move on to deeper object-oriented topics such as inheritance, polymorphism, and abstraction.
We cannot create an object without a class. Every object must be created from a class because the class defines its structure and behavior.
When we write: Student s1 = new Student();
The Student class tells Java what the object should contain and how it should behave. Without a class, Java would not know how to create the object. However, there are a few advanced cases where objects are created in slightly different ways, such as:
Even in these cases, a class definition still exists behind the scenes. So fundamentally, every object in Java is based on a class.
We can create any number of objects from a class, depending on the memory available.
A class acts like a blueprint, and we can use that blueprint to create multiple independent objects. For example, a Student class can be used to create hundreds or even thousands of student objects in an application.
The only limitation is memory. If the heap memory is exhausted, Java will throw an error such as OutOfMemoryError.
Objects are stored in the heap memory. When we create an object using the new keyword:
The actual object is created in the heap, and a reference variable is stored in the stack, which points to that object