Java Classes and Objects - Complete Guide
Introduction to Classes and Objects
Classes and objects are the fundamental building blocks of Object-Oriented Programming (OOP) in Java. A class is a blueprint or template that defines the properties and behaviors of objects, while an object is an instance of a class that represents a real-world entity.
Understanding classes and objects is essential for creating modular, reusable, and maintainable Java programs that model real-world scenarios effectively.
Defining Classes in Java
A class in Java is defined using the class keyword followed by the class name and a code block containing class members such as fields, constructors, and methods.
// Class definition
public class Car {
// Fields (attributes)
private String brand;
private String model;
private int year;
private double price;
// Constructor
public Car(String brand, String model, int year, double price) {
this.brand = brand;
this.model = model;
this.year = year;
this.price = price;
}
// Methods (behaviors)
public void startEngine() {
System.out.println("Engine started for " + brand + " " + model);
}
public void stopEngine() {
System.out.println("Engine stopped for " + brand + " " + model);
}
public void displayInfo() {
System.out.println("Brand: " + brand);
System.out.println("Model: " + model);
System.out.println("Year: " + year);
System.out.println("Price: $" + price);
}
// Getter example
public String getBrand() {
return brand;
}
}
// Main class to demonstrate class usage
public class Main {
public static void main(String[] args) {
// Creating objects from the Car class
Car car1 = new Car("Toyota", "Camry", 2022, 25000.0);
Car car2 = new Car("Honda", "Civic", 2023, 23000.0);
// Accessing object methods
car1.displayInfo();
car1.startEngine();
System.out.println();
car2.displayInfo();
car2.startEngine();
car2.stopEngine();
// Accessing object fields through getters (recommended)
System.out.println("\nCar 1 brand: " + car1.getBrand());
}
}
Brand: Toyota Model: Camry Year: 2022 Price: $25000.0 Engine started for Toyota Camry Brand: Honda Model: Civic Year: 2023 Price: $23000.0 Engine started for Honda Civic Engine stopped for Honda Civic Car 1 brand: Toyota
Class Components and Structure
A well-structured Java class typically contains the following components that work together to define the object's characteristics and behaviors.
public class BankAccount {
// Fields
private String accountNumber;
private String accountHolder;
private double balance;
private static int totalAccounts = 0;
// Constructor
public BankAccount(String accountNumber, String accountHolder, double initialBalance) {
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.balance = initialBalance;
totalAccounts++;
}
// Instance methods
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: $" + amount);
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrew: $" + amount);
} else {
System.out.println("Invalid withdrawal or insufficient funds");
}
}
public void displayBalance() {
System.out.println("Balance: $" + balance);
}
// Static method
public static int getTotalAccounts() {
return totalAccounts;
}
// Getters and setters
public String getAccountHolder() {
return accountHolder;
}
public void setAccountHolder(String accountHolder) {
if (accountHolder != null && !accountHolder.trim().isEmpty()) {
this.accountHolder = accountHolder;
}
}
}
public class BankDemo {
public static void main(String[] args) {
BankAccount account1 = new BankAccount("123456", "John Doe", 1000);
BankAccount account2 = new BankAccount("789012", "Jane Smith", 500);
account1.deposit(200);
account1.withdraw(150);
account1.displayBalance();
account2.deposit(1000);
account2.withdraw(2000);
account2.displayBalance();
System.out.println("Total accounts: " + BankAccount.getTotalAccounts());
System.out.println("Account 1 holder: " + account1.getAccountHolder());
account1.setAccountHolder("Johnathan Doe");
System.out.println("Account 1 holder after change: " + account1.getAccountHolder());
}
}
Deposited: $200.0 Withdrew: $150.0 Balance: $1050.0 Deposited: $1000.0 Invalid withdrawal or insufficient funds Balance: $1500.0 Total accounts: 2 Account 1 holder: John Doe Account 1 holder after change: Johnathan Doe
Object Creation and Memory Management
Objects in Java are created with the `new` keyword and stored in heap memory. Reference variables point to these objects. Java uses automatic garbage collection to reclaim memory from objects that are no longer referenced.
public class ObjectMemoryDemo {
public static void main(String[] args) {
String str1 = new String("Hello");
String str2 = new String("Hello");
String str3 = "Hello";
String str4 = "Hello";
System.out.println("str1 == str2: " + (str1 == str2));
System.out.println("str1.equals(str2): " + str1.equals(str2));
System.out.println("str3 == str4: " + (str3 == str4));
Rectangle rect1 = new Rectangle(5, 10);
Rectangle rect2 = rect1;
System.out.println("rect1 area: " + rect1.getArea());
System.out.println("rect2 area: " + rect2.getArea());
rect1.setWidth(8);
System.out.println("After modification:");
System.out.println("rect1 area: " + rect1.getArea());
System.out.println("rect2 area: " + rect2.getArea());
Rectangle rect3 = null;
System.out.println("rect3 is null: " + (rect3 == null));
System.out.println("\nObject lifecycle:");
for (int i = 0; i < 3; i++) {
Rectangle temp = new Rectangle(i + 1, i + 2);
System.out.println("Created rectangle with area: " + temp.getArea());
}
System.gc();
}
}
class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
System.out.println("Rectangle created: " + width + "x" + height);
}
public double getArea() {
return width * height;
}
public void setWidth(double width) {
this.width = width;
}
public void setHeight(double height) {
this.height = height;
}
}
str1 == str2: false str1.equals(str2): true str3 == str4: true Rectangle created: 5.0x10.0 rect1 area: 50.0 rect2 area: 50.0 After modification: rect1 area: 80.0 rect2 area: 80.0 rect3 is null: true Object lifecycle: Rectangle created: 1.0x2.0 Created rectangle with area: 2.0 Rectangle created: 2.0x3.0 Created rectangle with area: 6.0 Rectangle created: 3.0x4.0 Created rectangle with area: 12.0
Best Practices for Classes and Objects
- ✅ Use meaningful and descriptive class names (PascalCase)
- ✅ Each class should have a single clear responsibility
- ✅ Keep fields private and expose them through getters/setters
- ✅ Override toString(), equals(), and hashCode() when appropriate
- ✅ Use constructors for correct initialization
- ✅ Avoid unnecessary object creation to optimize memory
- ✅ Use static members for class-level data and behavior
- ✅ Consider interfaces for defining contracts between classes