Java tutorials  /  Java Classes and Objects
Chapter 16 · Java

Java Classes and Objects

A class in Java is a user-defined blueprint or template that defines the fields (data/attributes) and methods (behavior) common to all objects of a particular type. An object is a concrete instance of a class, created in memory at runtime using the 'new' keyword, with its own actual values for the fields defined by that class.

Think of a class like a cookie cutter, and objects like the actual cookies made from it. The cookie cutter (class) defines the general shape and structure — every cookie made from it will have that same shape. But each individual cookie (object) baked from that cutter can have its own specific toppings, size variations, or colors, even though they all share the same fundamental shape defined by the cutter. Similarly, a 'Car' class defines that every car has a color and speed, but each specific Car OBJECT you create can have its own actual color (red, blue) and speed value.

Consider a hospital's patient management system. A 'Patient' class defines the common structure every patient record must have — fields like 'patientId', 'name', 'dateOfBirth', and methods like 'scheduleAppointment()'. When a new patient walks in and registers, the system creates a brand new 'Patient' OBJECT specifically for them (e.g., 'Patient john = new Patient("P1001", "John Doe", ...)'), with their own actual, unique values filled in. The hospital might have thousands of individual Patient objects in memory at once, all built from that same single 'Patient' class blueprint, each representing one real, distinct person's data.

Classes and objects are the fundamental building blocks of object-oriented programming, allowing developers to model real-world entities (like a Patient, a Car, or a BankAccount) as self-contained units that bundle related data and behavior together. Without this structure, related data (like a person's name, age, and address) and the functions that operate on that data would remain disconnected and scattered, making large programs disorganized and hard to reason about. Classes let you define a reusable template once and then create as many independent, distinct objects from it as needed, each maintaining its own separate state in memory.

  • Instance Variables (Fields): Variables declared directly inside a class but outside any method, representing the state or data each individual object of that class will hold. Each object gets its own independent copy of these variables.
  • Instance Methods: Methods defined within a class that operate on a specific object's instance variables, requiring an actual object to be created before they can be called (e.g., 'myCar.accelerate()').
  • Static (Class) Members: Fields or methods declared with the 'static' keyword, which belong to the class itself rather than any individual object, and are shared across all instances of that class rather than each object having its own separate copy.
  • Local Variables: Variables declared inside a method or constructor's body, which exist only temporarily during that specific method call and are not part of the object's persistent state at all.
class ClassName { dataType instanceVariable; // field void methodName() { // instance method // uses instanceVariable } } // Creating an object: ClassName objectName = new ClassName();
A beginner wants to model a simple 'Car' with attributes like brand, color, and speed, and behaviors like accelerating and braking, then create two separate Car objects to demonstrate that each object maintains its own independent state.
Defining a Class and Creating Multiple Independent Objects
This example defines a 'Car' class with instance variables and a method, then creates two separate Car objects to show that each maintains its own independent state, even though both come from the same class.
Java
class Car { String brand; int speed; void accelerate(int increment) { speed += increment; System.out.println(brand + " is now going " + speed + " km/h"); } } public class CarDemo { public static void main(String[] args) { Car car1 = new Car(); car1.brand = "Toyota"; car1.speed = 0; Car car2 = new Car(); car2.brand = "Honda"; car2.speed = 0; car1.accelerate(40); car2.accelerate(60); System.out.println("Car1 speed: " + car1.speed); System.out.println("Car2 speed: " + car2.speed); } }
Toyota is now going 40 km/h Honda is now going 60 km/h Car1 speed: 40 Car2 speed: 60
'class Car' defines the blueprint with 'brand' and 'speed' as instance variables. 'new Car()' is called twice, creating two entirely separate objects, 'car1' and 'car2', each with its own independent copy of 'brand' and 'speed' stored at different memory locations. Calling 'car1.accelerate(40)' only modifies 'car1's own 'speed' field, leaving 'car2's 'speed' completely untouched, proving that each object maintains fully independent state despite sharing the exact same class definition.
Using the 'this' Keyword to Resolve Field-Parameter Naming Conflicts
This example demonstrates the common use of the 'this' keyword inside a method to distinguish between an instance variable and a parameter that share the exact same name.
Java
class Student { String name; void setName(String name) { this.name = name; } } public class ThisKeywordDemo { public static void main(String[] args) { Student student = new Student(); student.setName("Aditi"); System.out.println("Student name: " + student.name); } }
Student name: Aditi
Inside 'setName', both the instance variable and the method's parameter are named 'name', creating ambiguity. 'this.name' explicitly refers to the CURRENT OBJECT's instance variable, while the plain 'name' on the right side refers to the method's parameter, so 'this.name = name;' correctly assigns the parameter's incoming value to the object's own field. Without 'this', writing just 'name = name;' would be a meaningless no-op, leaving the object's actual field unset.
  • Confusing a Class Definition with an Object: Beginners sometimes treat the class itself as if it were usable data (e.g., trying to access 'Car.speed' directly without creating an object first, when 'speed' is a non-static instance variable). A class is only a blueprint/template; you must create an actual OBJECT with 'new' before you can access or modify any of its non-static instance variables or call its instance methods.
  • Forgetting That Each Object Has Its Own Independent Copy of Instance Variables: Beginners occasionally assume that changing a field on one object will somehow also affect another separate object of the same class. Unless a field is explicitly declared 'static' (making it shared across all instances), every single object created from a class maintains its own completely independent set of instance variables in memory.
  • Not Understanding That Local Variables Don't Persist Between Method Calls: A variable declared inside a method (a local variable) only exists temporarily while that specific method call is executing, and is completely destroyed once the method finishes. Beginners sometimes mistakenly expect a local variable's value to somehow be remembered the next time the same method is called on the same object, not realizing that persistent state must be stored in instance variables (fields) instead, not local variables.
  • Omitting 'this' When Field and Parameter Names Match: Writing 'speed = speed;' inside a method or constructor where a parameter shares the exact same name as an instance field does not actually assign the parameter's value to the object's field at all — it's effectively a no-op, since without 'this', 'speed' on both sides refers to the same local parameter variable. This commonly leaves the object's real field at its default value (like 0), unexpectedly.
  • Follow Standard Class Naming Conventions: Name classes using PascalCase and nouns that clearly represent the real-world entity being modeled (e.g., 'BankAccount', 'Employee'), making the codebase intuitive and self-documenting for anyone reading it.
  • Keep Instance Variables Private and Provide Controlled Access: Rather than allowing direct external access to an object's fields (as shown in simplified beginner examples), declare instance variables as 'private' and provide public getter/setter methods, enabling validation logic and protecting the object's internal state from invalid direct modification (this is the encapsulation principle in action).
  • Use 'this' Explicitly Whenever Naming Conflicts Are Possible: Whenever a constructor or method parameter shares the same name as an instance field (a very common and often intentional naming convention), always use 'this.fieldName = parameterName;' explicitly, to avoid the meaningless no-op mistake and make the code's intent unambiguous to any reader.
  • Model One Class Per Distinct Real-World Concept: Design each class to represent a single, well-defined real-world concept or entity (like a single Car, a single Employee), rather than combining multiple unrelated responsibilities into one bloated class, keeping the codebase modular, understandable, and easier to maintain or extend over time.
What is the difference between a class and an object in Java?
A class is a blueprint, template, or logical definition that specifies what fields (data) and methods (behavior) its instances will have, but a class itself does not occupy memory for actual data storage — it's purely a structural definition. An object is a concrete, actual instance of a class, created at runtime in memory using the 'new' keyword, with its own real, specific values assigned to the fields defined by its class. You can create many different objects from the exact same class, each maintaining independent state, similar to how many different houses (objects) can be built from the same architectural blueprint (class).
What is the difference between an instance variable and a local variable in Java?
An instance variable is declared directly within a class, but outside any method or constructor body, and represents part of an object's persistent state — it exists for as long as the object itself exists in memory, and each object gets its own independent copy. A local variable is declared inside a method, constructor, or block, and only exists temporarily during that specific execution — it is created when that method/block begins executing and is completely destroyed once it finishes, with no persistence between separate calls. Additionally, instance variables are automatically assigned default values (like 0, null, false) if not explicitly initialized, whereas local variables have no default value at all and MUST be explicitly initialized before being used, or the code will not compile.
What is the purpose of the 'this' keyword in Java, and provide a scenario where it is essentially required?
The 'this' keyword refers to the current object instance on which a method or constructor is being invoked. It serves several purposes: distinguishing between an instance field and a method/constructor parameter that share the identical name (e.g., 'this.name = name;'), invoking another overloaded constructor within the same class ('this(args)'), and passing the current object instance as an argument to another method that requires it. The most common and essentially required scenario is within a constructor or setter method where the parameter name intentionally matches the field name it's meant to initialize — without 'this.fieldName', the assignment would be ambiguous and would actually just be a meaningless self-assignment of the local parameter rather than setting the object's actual field.
Create a 'Book' class with instance variables 'title' and 'author', and a method 'displayInfo()' that prints both. Create two different Book objects with different values and call displayInfo() on each.
class Book { String title; String author; void displayInfo() { System.out.println(title + " by " + author); } } public class BookObjectDemo { public static void main(String[] args) { Book book1 = new Book(); book1.title = "1984"; book1.author = "George Orwell"; Book book2 = new Book(); book2.title = "Brave New World"; book2.author = "Aldous Huxley"; book1.displayInfo(); book2.displayInfo(); } } // Output: // 1984 by George Orwell // Brave New World by Aldous Huxley
What will be the output of the following code, and explain why, based on how instance variables work? class Counter { int count; void increment() { count++; } } public class Test { public static void main(String[] args) { Counter c1 = new Counter(); Counter c2 = new Counter(); c1.increment(); c1.increment(); c2.increment(); System.out.println("c1 count: " + c1.count); System.out.println("c2 count: " + c2.count); } }
The output will be: c1 count: 2 c2 count: 1 This happens because 'c1' and 'c2' are two entirely separate 'Counter' objects, each with its own independent copy of the 'count' instance variable, stored at different memory locations. Calling 'c1.increment()' twice only affects c1's own 'count' field (incrementing it to 2), while 'c2.increment()' called once only affects c2's own, completely separate 'count' field (incrementing it to 1). Since 'count' is a non-static instance variable, no sharing of state occurs between the two distinct objects.
Write a class 'Rectangle' with a method 'setDimensions(int length, int width)' that correctly uses the 'this' keyword to assign the parameters to matching-named instance fields, then calculates and prints the area.
class Rectangle { int length; int width; void setDimensions(int length, int width) { this.length = length; this.width = width; } int calculateArea() { return length * width; } } public class RectangleThisDemo { public static void main(String[] args) { Rectangle rect = new Rectangle(); rect.setDimensions(8, 5); System.out.println("Area: " + rect.calculateArea()); } } // Output: // Area: 40

A class is a blueprint defining the fields and methods shared by all its instances, while an object is a concrete, independent instance of that class created using 'new', with its own actual data in memory. Understanding the distinction between instance variables (persistent, per-object state) and local variables (temporary, method-scoped), along with the correct use of the 'this' keyword to resolve naming conflicts, forms the essential foundation for everything else in object-oriented Java programming, including constructors, inheritance, and polymorphism.

© 2026 CompileX. Maintained by Aditya Kumar Sharma.