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());
}
}