Bundling data and methods within a class, hiding internal state
Creating new classes from existing ones, reusing code
One interface, multiple implementations
Hiding complex implementation details
A class is a blueprint for objects. An object is an instance of a class.
// Define a class public class Car { // Fields (attributes) String brand; String model; int year; // Constructor public Car(String brand, String model, int year) { this.brand = brand; this.model = model; this.year = year; } // Method public void displayInfo() { System.out.println("Brand: " + brand + ", Model: " + model + ", Year: " + year); } } public class Main { public static void main(String[] args) { // Create objects Car car1 = new Car("Toyota", "Camry", 2020); Car car2 = new Car("Honda", "Civic", 2022); // Access object methods car1.displayInfo(); car2.displayInfo(); } }
Constructors initialize new objects. They have the same name as the class.
public class Student { String name; int age; // Default constructor public Student() { this.name = "Unknown"; this.age = 0; } // Parameterized constructor public Student(String name, int age) { this.name = name; this.age = age; } // Overloaded constructor public Student(String name) { this.name = name; this.age = 18; // Default age } public void display() { System.out.println("Name: " + name + ", Age: " + age); } } public class Main { public static void main(String[] args) { Student s1 = new Student(); // Default Student s2 = new Student("Alice", 20); // Parameterized Student s3 = new Student("Bob"); // Overloaded s1.display(); s2.display(); s3.display(); } }
The this
keyword refers to the current object in a method or constructor.
public class Person { String name; int age; public Person(String name, int age) { // Using 'this' to distinguish instance variables from parameters this.name = name; this.age = age; } public void setAge(int age) { // Using 'this' to refer to the current object's field this.age = age; } public void display() { // Using 'this' to call another method this.printInfo(); } private void printInfo() { System.out.println("Name: " + this.name + ", Age: " + this.age); } }
Methods define behaviors of objects. Overloading allows multiple methods with the same name but different parameters.
public class Calculator { // Method to add two integers public int add(int a, int b) { return a + b; } // Overloaded method to add three integers public int add(int a, int b, int c) { return a + b + c; } // Overloaded method to add two doubles public double add(double a, double b) { return a + b; } // Overloaded method to add an array of integers public int add(int[] numbers) { int sum = 0; for (int num : numbers) { sum += num; } return sum; } } public class Main { public static void main(String[] args) { Calculator calc = new Calculator(); System.out.println("Sum of two integers: " + calc.add(5, 7)); System.out.println("Sum of three integers: " + calc.add(5, 7, 3)); System.out.println("Sum of two doubles: " + calc.add(3.5, 2.7)); int[] nums = {1, 2, 3, 4, 5}; System.out.println("Sum of array: " + calc.add(nums)); } }
Access modifiers control the visibility of classes, fields, methods, and constructors.
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | No |
default | Yes | Yes | No | No |
private | Yes | No | No | No |
public class AccessExample { public int publicVar = 1; protected int protectedVar = 2; int defaultVar = 3; // default (package-private) private int privateVar = 4; public void publicMethod() { System.out.println("Public method"); } protected void protectedMethod() { System.out.println("Protected method"); } void defaultMethod() { System.out.println("Default method"); } private void privateMethod() { System.out.println("Private method"); } }
The static
keyword is used for memory management. Static members belong to the class rather than any object instance.
public class StaticDemo { // Static variable static int count = 0; // Instance variable int id; // Static block static { System.out.println("Static block executed once when class is loaded"); } public StaticDemo() { id = ++count; // Increment static count for each object } // Static method public static void displayCount() { System.out.println("Total objects created: " + count); } public static void main(String[] args) { StaticDemo obj1 = new StaticDemo(); StaticDemo obj2 = new StaticDemo(); StaticDemo obj3 = new StaticDemo(); StaticDemo.displayCount(); // Call static method System.out.println("ID of obj2: " + obj2.id); } }
Inheritance allows a class to inherit properties and methods from another class.
// Base class class Animal { void eat() { System.out.println("Animal is eating"); } } // Derived class (Single inheritance) class Dog extends Animal { void bark() { System.out.println("Dog is barking"); } } // Multilevel inheritance class BabyDog extends Dog { void weep() { System.out.println("Baby dog is weeping"); } } // Hierarchical inheritance class Cat extends Animal { void meow() { System.out.println("Cat is meowing"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.eat(); dog.bark(); BabyDog babyDog = new BabyDog(); babyDog.eat(); babyDog.bark(); babyDog.weep(); Cat cat = new Cat(); cat.eat(); cat.meow(); } }
The super
keyword refers to the parent class object and is used to call parent class methods and constructors.
class Person { String name; int age; Person(String name, int age) { this.name = name; this.age = age; } void display() { System.out.println("Name: " + name + ", Age: " + age); } } class Employee extends Person { double salary; Employee(String name, int age, double salary) { super(name, age); // Call parent constructor this.salary = salary; } @Override void display() { super.display(); // Call parent method System.out.println("Salary: $" + salary); } } public class Main { public static void main(String[] args) { Employee emp = new Employee("John", 30, 50000); emp.display(); } }
Method overriding allows a subclass to provide a specific implementation of a method that is already provided by its parent class.
class Shape { void draw() { System.out.println("Drawing a shape"); } } class Circle extends Shape { @Override void draw() { System.out.println("Drawing a circle"); } } class Square extends Shape { @Override void draw() { System.out.println("Drawing a square"); } } public class Main { public static void main(String[] args) { Shape shape1 = new Circle(); Shape shape2 = new Square(); shape1.draw(); // Calls Circle's draw() shape2.draw(); // Calls Square's draw() } }
The final
keyword is used to restrict users. It can be applied to variables, methods, and classes.
// Final variable final int MAX_VALUE = 100; // Final method class Parent { final void display() { System.out.println("This is a final method"); } } class Child extends Parent { // Cannot override final method // void display() { } // This would cause a compile error } // Final class final class FinalClass { // Class cannot be extended } // class ExtendedClass extends FinalClass { } // Not allowed
Abstract classes cannot be instantiated and may contain abstract methods that must be implemented by subclasses.
// Abstract class abstract class Animal { // Abstract method (no implementation) abstract void makeSound(); // Concrete method void sleep() { System.out.println("Animal is sleeping"); } } class Dog extends Animal { @Override void makeSound() { System.out.println("Dog barks: Woof! Woof!"); } } class Cat extends Animal { @Override void makeSound() { System.out.println("Cat meows: Meow! Meow!"); } } public class Main { public static void main(String[] args) { Animal dog = new Dog(); Animal cat = new Cat(); dog.makeSound(); dog.sleep(); cat.makeSound(); cat.sleep(); } }
Interfaces define a contract for classes. They can contain abstract methods, default methods, static methods, and constants.
// Interface interface Drawable { // Abstract method void draw(); // Default method default void resize() { System.out.println("Resizing the shape"); } // Static method static void displayInfo() { System.out.println("This is a Drawable interface"); } } // Implementing the interface class Circle implements Drawable { @Override public void draw() { System.out.println("Drawing a circle"); } } class Rectangle implements Drawable { @Override public void draw() { System.out.println("Drawing a rectangle"); } } public class Main { public static void main(String[] args) { Drawable circle = new Circle(); Drawable rectangle = new Rectangle(); circle.draw(); circle.resize(); rectangle.draw(); rectangle.resize(); Drawable.displayInfo(); // Call static method } }
Polymorphism allows objects of different classes to be treated as objects of a common super class.
class Animal { void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override void sound() { System.out.println("Dog barks"); } } class Cat extends Animal { @Override void sound() { System.out.println("Cat meows"); } } public class Main { public static void main(String[] args) { Animal animal; // Runtime polymorphism animal = new Dog(); animal.sound(); // Calls Dog's sound() animal = new Cat(); animal.sound(); // Calls Cat's sound() // Compile-time polymorphism Calculator calc = new Calculator(); System.out.println(calc.add(5, 7)); System.out.println(calc.add(3.5, 2.7)); } }
Encapsulation is the technique of making fields private and providing access via public methods.
public class BankAccount { // Private fields private String accountNumber; private double balance; // Public constructor public BankAccount(String accountNumber) { this.accountNumber = accountNumber; this.balance = 0.0; } // Public methods to access private fields public String getAccountNumber() { return accountNumber; } public double getBalance() { return balance; } // Public method to modify balance with validation 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("Withdrawn: $" + amount); } else { System.out.println("Insufficient funds"); } } } public class Main { public static void main(String[] args) { BankAccount account = new BankAccount("123456789"); account.deposit(1000); account.withdraw(500); account.withdraw(700); // Should fail System.out.println("Account: " + account.getAccountNumber()); System.out.println("Balance: $" + account.getBalance()); } }