Java Tutorial
🔍

Java Classes and Objects

Java Classes and Objects

A class is a blueprint. An object is something built from that blueprint. Every Java program you write — every field, every method, every piece of logic — lives inside a class, and almost everything your program does at runtime happens through objects created from those classes.

This is not an abstract idea. A class in Java is simply a way of describing what something looks like and what it can do. An object is a specific instance of that description — with its own data, its own state, and its own lifecycle.

What Is a Class in Java?

A class defines the structure and behaviour of a group of objects. It specifies:

  • Fields — the data each object will hold (also called instance variables or attributes)
  • Methods — the operations each object can perform
  • Constructors — the instructions for creating a new object from the class

A class does not occupy memory by itself. It is a template. Memory is allocated only when an object is created from the class.

Java
1// File: Product.java 2 3public class Product { 4 5 // Fields — each object gets its own copy of these 6 private String productName; 7 private double price; 8 private int stockCount; 9 10 // Constructor — called when a new Product object is created 11 public Product(String productName, double price, int stockCount) { 12 this.productName = productName; 13 this.price = price; 14 this.stockCount = stockCount; 15 } 16 17 // Methods — operations this object can perform 18 public String getProductName() { return productName; } 19 public double getPrice() { return price; } 20 public int getStockCount() { return stockCount; } 21 22 public boolean isInStock() { 23 return stockCount > 0; 24 } 25 26 public String getSummary() { 27 return productName + " | Rs." + price 28 + " | Stock: " + stockCount 29 + " | " + (isInStock() ? "Available" : "Out of stock"); 30 } 31}

This class defines what every Product object will look like. No object exists yet — this is just the blueprint.

What Is an Object in Java?

An object is a specific instance of a class created at runtime using the new keyword. Each object has its own copy of the class's instance fields and exists independently of other objects created from the same class.

Java
1// File: ProductDemo.java 2 3public class ProductDemo { 4 5 public static void main(String[] args) { 6 7 // Creating three separate objects from the same Product class 8 Product laptop = new Product("Laptop 15-inch", 54999.0, 12); 9 Product mouse = new Product("Wireless Mouse", 1299.0, 0); 10 Product keyboard = new Product("Mechanical Keyboard", 4599.0, 5); 11 12 // Each object has independent state 13 System.out.println(laptop.getSummary()); 14 System.out.println(mouse.getSummary()); 15 System.out.println(keyboard.getSummary()); 16 17 System.out.println("\nIs laptop in stock? " + laptop.isInStock()); 18 System.out.println("Is mouse in stock? " + mouse.isInStock()); 19 } 20}
Output:
Laptop 15-inch | Rs.54999.0 | Stock: 12 | Available
Wireless Mouse | Rs.1299.0 | Stock: 0 | Out of stock
Mechanical Keyboard | Rs.4599.0 | Stock: 5 | Available

Is laptop in stock?  true
Is mouse in stock?   false

laptop, mouse, and keyboard are three separate objects. Changing the stock count of laptop has no effect on mouse or keyboard. Each object owns its own copy of productName, price, and stockCount.

Class vs Object in Java

The relationship between a class and an object is the most fundamental concept in Java — and also the most commonly misexplained in interviews. The table below makes the distinction concrete.

AspectClassObject
What it isBlueprint / TemplateInstance of the blueprint
When it existsCompile timeRuntime
MemoryNo heap memory allocatedHeap memory allocated per object
How manyOne class definitionMany objects from one class
Created withclass keywordnew keyword
ContainsField definitions, method definitionsActual field values, method access
ExampleProductnew Product("Laptop", 54999.0, 12)

A Class Is Written Once — Objects Are Created Many Times

The Product class is defined once in source code. From that single definition, the program can create dozens — or millions — of independent Product objects at runtime, each with its own data.

Java
1public class ClassVsObjectDemo { 2 3 public static void main(String[] args) { 4 5 // One class — three completely independent objects 6 Product productOne = new Product("Laptop", 54999.0, 10); 7 Product productTwo = new Product("Mouse", 1299.0, 0); 8 Product productThree = new Product("Keyboard", 4599.0, 5); 9 10 System.out.println("Product 1 in stock: " + productOne.isInStock()); 11 System.out.println("Product 2 in stock: " + productTwo.isInStock()); 12 System.out.println("Product 3 in stock: " + productThree.isInStock()); 13 } 14}
Output:
Product 1 in stock: true
Product 2 in stock: false
Product 3 in stock: true

The Blueprint Analogy — Visualised

The diagram below shows how one class produces multiple independent objects, each occupying its own space on the heap.

          Product class (blueprint — compile time)
          +------------------------------------------+
          | Fields:  productName, price, stockCount  |
          | Methods: isInStock(), getSummary()        |
          +------------------------------------------+
                  |           |            |
                 new         new          new
                  |           |            |
    +-------------+  +-----------+  +---------------+
    | Object 1    |  | Object 2  |  | Object 3      |
    | name: Laptop|  | name:Mouse|  | name: Keyboard|
    | price:54999 |  | price:1299|  | price: 4599   |
    | stock: 10   |  | stock: 0  |  | stock: 5      |
    +-------------+  +-----------+  +---------------+
         (heap)          (heap)           (heap)

Each object is independent. Changing stockCount on Object 1 has zero effect on Objects 2 or 3. All three share the same method definitions from the class — but operate on their own data.

Interview tip: When asked to explain class vs object, use the blueprint analogy but back it immediately with the memory point — a class allocates no heap memory; only objects do. That level of precision is what separates a strong answer from a surface-level one.

Objects Are References — Not the Values Themselves

When you assign an object to a variable, the variable holds a reference — a memory address pointing to the object on the heap — not the object itself.

Java
1public class ReferencePointDemo { 2 3 public static void main(String[] args) { 4 5 Product original = new Product("Headphones", 2499.0, 10); 6 7 // alias does NOT create a new object 8 // both variables point to the same object in memory 9 Product alias = original; 10 11 System.out.println("Same object? " + (original == alias)); 12 13 // Creating a genuinely independent copy requires new 14 Product independentCopy = new Product("Headphones", 2499.0, 10); 15 System.out.println("Independent object? " + (original == independentCopy)); 16 } 17}
Output:
Same object?         true
Independent object?  false

original == alias is true because both variables hold the same memory address. original == independentCopy is false because new created a separate object on the heap with its own address — even though the data is identical. A mistake that appears often in fresher pull requests is treating object assignment as copying — it is not.

Anatomy of a Java Class

Every class has a defined structure. Understanding each part's role prevents the common mistake of putting logic in the wrong place.

public class ClassName {

    // 1. Fields (instance variables)
    //    Each object gets its own copy.
    //    Usually private — accessed through methods.

    // 2. Static fields (class variables)
    //    Shared by all objects of this class.
    //    Only one copy exists regardless of how many objects are created.

    // 3. Constructors
    //    Called when new ClassName() is used.
    //    Initialise the object's fields.
    //    Not inherited by subclasses.

    // 4. Instance methods
    //    Operate on a specific object's data.
    //    Can access and modify instance fields.

    // 5. Static methods
    //    Belong to the class, not any specific object.
    //    Cannot access instance fields directly.
    //    Called on the class name, not on an object.
}

Instance Variables vs Static Variables

Instance variables belong to each individual object. Each object created from the class gets its own independent copy — changing one object's field does not affect others.

Static variables (also called class variables) belong to the class itself. Only one copy exists, shared by all objects of that class.

Java
1// File: StoreCounter.java 2 3public class StoreCounter { 4 5 // Static — shared across all StoreCounter objects 6 private static int totalObjectsCreated = 0; 7 8 // Instance — each object has its own copy 9 private final String storeName; 10 private int visitorCount; 11 12 public StoreCounter(String storeName) { 13 this.storeName = storeName; 14 this.visitorCount = 0; 15 totalObjectsCreated++; // increments the shared counter on every creation 16 } 17 18 public void recordVisit() { 19 visitorCount++; 20 } 21 22 public String getReport() { 23 return storeName + " — Visitors: " + visitorCount; 24 } 25 26 // Static method — accesses only static data 27 public static int getTotalObjectsCreated() { 28 return totalObjectsCreated; 29 } 30}
Java
1// File: StoreCounterDemo.java 2 3public class StoreCounterDemo { 4 5 public static void main(String[] args) { 6 7 StoreCounter mumbaiStore = new StoreCounter("Mumbai Store"); 8 StoreCounter bangaloreStore = new StoreCounter("Bangalore Store"); 9 10 mumbaiStore.recordVisit(); 11 mumbaiStore.recordVisit(); 12 mumbaiStore.recordVisit(); 13 bangaloreStore.recordVisit(); 14 15 System.out.println(mumbaiStore.getReport()); 16 System.out.println(bangaloreStore.getReport()); 17 18 // Static method called on the class — not on any object 19 System.out.println("Total StoreCounter objects created: " 20 + StoreCounter.getTotalObjectsCreated()); 21 } 22}
Output:
Mumbai Store — Visitors: 3
Bangalore Store — Visitors: 1
Total StoreCounter objects created: 2

Each store tracks its own visitorCount independently. But totalObjectsCreated is one shared counter — both constructor calls increment the same value, which is why it shows 2 regardless of which store object you ask.

How Object Creation Works Internally

When you write new Product("Laptop", 54999.0, 12), four things happen in sequence:

Step 1: Memory allocation
        The JVM allocates a block of memory on the heap
        large enough to hold all the object's instance fields.

Step 2: Default initialisation
        All fields are set to their type defaults:
        int → 0, double → 0.0, boolean → false, Object → null

Step 3: Constructor execution
        The constructor runs and sets the fields to the
        values provided in the arguments.

Step 4: Reference returned
        The new operator returns a reference (memory address)
        to the created object, which is stored in the variable.

The variable laptop does not contain the object — it contains a reference to where the object lives on the heap. This distinction matters when you pass objects to methods or assign one variable to another.

The this Keyword

Inside any instance method or constructor, the keyword this refers to the current object — the specific object on which the method was called. It serves two primary purposes.

Resolving Name Ambiguity

When a constructor parameter has the same name as an instance field, this disambiguates which is which.

Java
1public class OrderItem { 2 3 private final String productSku; 4 private final int quantity; 5 private final double unitPrice; 6 7 public OrderItem(String productSku, int quantity, double unitPrice) { 8 // Without this., productSku would refer to the parameter, not the field 9 this.productSku = productSku; 10 this.quantity = quantity; 11 this.unitPrice = unitPrice; 12 } 13 14 public double getLineTotal() { 15 return quantity * unitPrice; 16 } 17 18 public String getSummary() { 19 return productSku + " x" + quantity + " @ Rs." + unitPrice 20 + " = Rs." + getLineTotal(); 21 } 22}

Returning the Current Object — Method Chaining

Returning this from a method allows method chaining — calling multiple methods on the same object in a single expression. This is the pattern used by StringBuilder and many builder classes.

Java
1// File: QueryBuilder.java 2 3public class QueryBuilder { 4 5 private String tableName = ""; 6 private String conditions = ""; 7 private int limit = 100; 8 9 public QueryBuilder from(String tableName) { 10 this.tableName = tableName; 11 return this; // returns current object for chaining 12 } 13 14 public QueryBuilder where(String condition) { 15 this.conditions = condition; 16 return this; 17 } 18 19 public QueryBuilder limit(int limit) { 20 this.limit = limit; 21 return this; 22 } 23 24 public String build() { 25 return "SELECT * FROM " + tableName 26 + (conditions.isEmpty() ? "" : " WHERE " + conditions) 27 + " LIMIT " + limit; 28 } 29}
Java
1// File: QueryBuilderDemo.java 2 3public class QueryBuilderDemo { 4 5 public static void main(String[] args) { 6 7 // Method chaining — each method returns this, enabling the chain 8 String query = new QueryBuilder() 9 .from("orders") 10 .where("status = 'PENDING'") 11 .limit(50) 12 .build(); 13 14 System.out.println("Generated query: " + query); 15 } 16}
Output:
Generated query: SELECT * FROM orders WHERE status = 'PENDING' LIMIT 50

Real-World Example — Employee Management System

The Business Problem

You are building the employee records module for an IT services company — similar to the HR systems used by TCS or Infosys. The system must store employee data, track total headcount automatically, and generate formatted pay slip summaries. This requires both instance data (individual employee details) and class-level data (total headcount shared across all employees).

Implementation

Java
1// File: EmployeeConfig.java 2 3public final class EmployeeConfig { 4 5 public static final double DA_RATE = 0.10; // Dearness Allowance 6 public static final double HRA_RATE = 0.15; // House Rent Allowance 7 public static final double PF_RATE = 0.12; // Provident Fund deduction 8 9 private EmployeeConfig() {} 10}
Java
1// File: Employee.java 2 3public class Employee { 4 5 // Static — shared across all Employee objects 6 private static int totalEmployees = 0; 7 8 // Instance — each employee has independent data 9 private final String employeeId; 10 private final String fullName; 11 private final String department; 12 private final double basicSalary; 13 14 public Employee(String employeeId, String fullName, 15 String department, double basicSalary) { 16 this.employeeId = employeeId; 17 this.fullName = fullName; 18 this.department = department; 19 this.basicSalary = basicSalary; 20 totalEmployees++; 21 } 22 23 public String getEmployeeId() { return employeeId; } 24 public String getFullName() { return fullName; } 25 public String getDepartment() { return department; } 26 public double getBasicSalary(){ return basicSalary; } 27 28 public double getGrossSalary() { 29 double da = basicSalary * EmployeeConfig.DA_RATE; 30 double hra = basicSalary * EmployeeConfig.HRA_RATE; 31 return basicSalary + da + hra; 32 } 33 34 public double getNetSalary() { 35 double pf = basicSalary * EmployeeConfig.PF_RATE; 36 return getGrossSalary() - pf; 37 } 38 39 public String getPaySlip() { 40 return String.format( 41 "%-22s | %-10s | %-20s | Basic: Rs.%-7.0f | Gross: Rs.%-7.0f | Net: Rs.%.0f", 42 fullName, employeeId, department, 43 basicSalary, getGrossSalary(), getNetSalary() 44 ); 45 } 46 47 public static int getTotalEmployees() { 48 return totalEmployees; 49 } 50}
Java
1// File: EmployeeDemo.java 2 3public class EmployeeDemo { 4 5 public static void main(String[] args) { 6 7 Employee empOne = new Employee("TCS-001", "Ananya Krishnan", "Backend Engineering", 85000.0); 8 Employee empTwo = new Employee("TCS-002", "Rohan Desai", "DevOps", 72000.0); 9 Employee empThree = new Employee("TCS-003", "Meena Subramanian", "QA Automation", 68000.0); 10 11 System.out.println("=== Pay Slip Report ===\n"); 12 System.out.println(empOne.getPaySlip()); 13 System.out.println(empTwo.getPaySlip()); 14 System.out.println(empThree.getPaySlip()); 15 16 System.out.println("\nTotal employees on record: " 17 + Employee.getTotalEmployees()); 18 } 19}
Output:
=== Pay Slip Report ===

Ananya Krishnan        | TCS-001    | Backend Engineering  | Basic: Rs.85000   | Gross: Rs.106250  | Net: Rs.96050
Rohan Desai            | TCS-002    | DevOps               | Basic: Rs.72000   | Gross: Rs.90000   | Net: Rs.81360
Meena Subramanian      | TCS-003    | QA Automation        | Basic: Rs.68000   | Gross: Rs.85000   | Net: Rs.76840

Total employees on record: 3

Three independent objects with three independent salary calculations. The totalEmployees counter is shared — every constructor call increments the same static field. The salary constants live in EmployeeConfig so when PF rates change under government notification, only one file changes — not every class that calculates salary. During code reviews, hardcoded tax rates inside method bodies are consistently flagged for exactly this reason.

Best Practices

Keep fields private and expose behaviour through methods

Direct field access from outside a class couples the caller to the internal representation. If you later change a field from double to BigDecimal, every caller that accessed it directly must also change. Methods give you a stable interface independent of internal storage choices.

Give classes a single, clear responsibility

A class that handles database queries, formats output, sends emails, and calculates taxes is doing too much. Each class should represent one concept and own the logic that belongs to that concept. The Employee class knows about salary calculation. A separate PaySlipFormatter handles display. A separate PayrollService handles persistence.

Name classes as nouns and methods as verbs

Product, Employee, OrderItem are nouns — they represent things. calculateTax(), recordVisit(), getSummary() are verbs — they describe actions. This naming convention is standard across Java teams and makes intent immediately readable.

Use static members only for class-level data and utilities

Static fields model data that belongs to the class — a counter of all instances, a shared configuration value. Static methods model operations that do not depend on any specific object's state — utility functions, factory methods. When you find yourself accessing instance fields from a static method, the method probably should not be static.

Common Mistakes

Mistake 1 — Confusing Object Assignment with Copying

Java
1Product itemA = new Product("Pen", 20.0, 100); 2Product itemB = itemA; // itemB points to the SAME object as itemA 3 4// They are not two separate products — they are two names for one object 5System.out.println(itemA == itemB); // true — same memory reference

When you need two independent objects with the same initial values, create two separate objects with new — or implement a copy constructor that explicitly creates a new object with duplicated field values.

Mistake 2 — Making All Fields and Methods Static

Java
1// Wrong — treating a class like a collection of utility functions 2public class OrderProcessor { 3 4 public static String orderId = ""; // shared across everything — race condition risk 5 public static double total = 0.0; 6 7 public static void process() { 8 // operates on shared state — not thread-safe, not scalable 9 } 10}

Static fields are shared across every object and every thread. Using them for data that is conceptually per-object is a design error that causes subtle bugs under concurrent load. During code reviews, unnecessary static on fields and methods is one of the most frequently flagged issues in Java code written by developers transitioning from procedural backgrounds.

Mistake 3 — Forgetting this When Parameter Names Shadow Fields

Java
1public class Discount { 2 3 private double rate; 4 5 public Discount(double rate) { 6 rate = rate; // assigns the parameter to itself — the field is never set 7 // Correct: this.rate = rate; 8 } 9 10 public double getRate() { 11 return rate; // returns 0.0 — the field was never initialised 12 } 13}

Without this.rate, both sides of the assignment refer to the constructor parameter. The field stays at its default value of 0.0. This compiles without error and produces wrong results silently. IntelliJ IDEA flags rate = rate as a warning — but only if you notice it.

Interview Questions

Q1. What is the difference between a class and an object in Java?

A class is a compile-time blueprint that defines the structure and behaviour a group of objects will share — its fields, methods, and constructors. An object is a runtime entity created from that blueprint using the new keyword. A class consumes no heap memory on its own; each object consumes heap memory proportional to its fields. The relationship is the same as a building blueprint versus the actual buildings constructed from it — one blueprint, many buildings, each independent.

Q2. What is the difference between instance variables and static variables?

Instance variables belong to each object individually — every object created from the class gets its own separate copy, and changing one object's instance variable has no effect on others. Static variables belong to the class itself — only one copy exists in memory, shared by all objects of that class. Instance variables model per-object state like an employee's salary. Static variables model class-level state like a count of all employees created.

Q3. What does the this keyword do in Java?

this is a reference to the current object — the specific object on which the method or constructor is executing. It is most commonly used to resolve ambiguity when a constructor parameter has the same name as an instance field (this.name = name), and to return the current object from a method to enable method chaining (return this). It can also call another constructor in the same class using this(args).

Q4. What happens in memory when you create a Java object with new?

The JVM allocates a block of memory on the heap sized to hold all the object's instance fields. All fields are default-initialised — numeric types to 0, booleans to false, references to null. Then the specified constructor runs and sets the fields to the provided values. Finally, new returns a reference — a memory address — to the caller, which stores it in a variable. The variable does not contain the object; it contains a pointer to where the object lives on the heap.

Q5. What is the difference between a static method and an instance method?

An instance method operates on a specific object's state — it can read and modify instance fields and is called on an object reference. A static method belongs to the class and has no access to instance fields directly — it can only work with static fields and its own parameters. Static methods are called on the class name rather than on an object. Use static methods for utility operations that do not depend on object state. Use instance methods for operations that read or modify a specific object's data.

Q6. Can a Java class exist without any objects being created from it?

Yes. Static fields and static methods are accessible as soon as the class is loaded by the JVM — without any object being created. Some utility classes are designed this way: Math, Arrays, and Collections in the Java standard library have private constructors to prevent instantiation intentionally. The class exists and its static members are usable; it simply never produces objects.

FAQs

What is a class in Java?

A class is a blueprint or template that defines the structure and behaviour of objects. It specifies what data each object will hold through fields and what operations each object can perform through methods. A class is a compile-time construct — it defines the shape; objects are the runtime instances created from that shape.

What is an object in Java?

An object is a specific instance of a class, created at runtime using the new keyword. Each object has its own independent copy of the class's instance fields. Multiple objects can be created from the same class, each with different data and independent state.

What is the difference between a class and an object?

A class is the template — it exists at compile time, allocates no heap memory, and is defined once. An object is the instance — it exists at runtime, occupies heap memory, and can be created many times from the same class. The class defines what the object looks like and can do; the object is the actual entity with real data.

What is the difference between a field and a variable in Java?

A field is a variable declared directly inside a class body — it belongs to the class or its objects and persists as long as the object exists. A local variable is declared inside a method body — it exists only during the method's execution and is destroyed when the method returns.

What is the new keyword used for in Java?

The new keyword creates a new object on the heap. It allocates memory, initialises fields to default values, runs the constructor, and returns a reference to the newly created object. Without new, no object is created — a variable of a class type will be null until assigned an object.

Why should fields be private in Java?

Making fields private restricts access to within the class itself, forcing external code to interact through methods. This means the internal storage format can change without affecting callers, validation can be enforced through setter methods, and the class maintains full control over its own state. This is the foundation of encapsulation.

Summary

Classes are the blueprints; objects are what programs actually run. Every field declared in a class becomes independent data in each object — one class, many independent objects, each with its own state on the heap. Static fields and methods belong to the class itself, shared by all objects. The new keyword triggers memory allocation on the heap, default initialisation, and constructor execution, returning a reference the variable stores — not the object itself.

The class vs object distinction goes deeper than syntax. A class allocates no memory; objects do. Assigning one object variable to another creates two references to the same object, not two independent copies. The this keyword is the object's self-reference — essential for disambiguating field names in constructors and enabling builder-style method chaining.

For interviews, be ready to explain the class-versus-object distinction backed by the memory allocation point, the difference between instance and static members with a concrete example, and what happens step-by-step when new creates an object. These three points are the foundation every subsequent OOP topic — constructors, encapsulation, inheritance — builds directly on.

What to Read Next

TopicLink
How constructors initialise objects and how constructor chaining worksConstructors →
How access modifiers control visibility of fields and methodsAccess Modifiers →
How encapsulation protects class data using private fields and methodsEncapsulation →
How the static keyword works for class-level fields and methodsstatic Keyword →
How inheritance extends one class from another to reuse behaviourInheritance →
Java Classes and Objects | DevStackFlow