OOP Practice Sheet (Java) — 32 Programs with Sample Outputs
How to run:
javac [Link]
java ClassName
Note: Some programs show an example run for input-based code; your output may differ
depending on your input.
Encapsulation
1) Getter/Setter Basics (BankAccount)
Level: Very Basic
Suggested File: P01_Encapsulation_GetSet.java
Concept/Logic:
• Private field is hidden; access is controlled via public methods.
Code:
class BankAccount {
private double balance;
public void setBalance(double amount) {
balance = amount;
}
public double getBalance() {
return balance;
}
}
public class P01_Encapsulation_GetSet {
public static void main(String[] args) {
BankAccount acc = new BankAccount();
[Link](5000);
[Link]("Balance = " + [Link]());
}
}
Sample Output:
Balance = 5000.0
2) Validation in Methods (Deposit/Withdraw)
Level: Basic
Suggested File: P02_Encapsulation_Validation.java
Concept/Logic:
• Rules are enforced inside methods to protect data (no negative deposit, no overdraft).
Code:
class BankAccount {
private double balance;
public void deposit(double amount) {
if (amount <= 0) {
[Link]("Invalid deposit!");
return;
}
balance += amount;
}
public void withdraw(double amount) {
if (amount <= 0 || amount > balance) {
[Link]("Invalid withdrawal!");
return;
}
balance -= amount;
}
public double getBalance() {
return balance;
}
}
public class P02_Encapsulation_Validation {
public static void main(String[] args) {
BankAccount acc = new BankAccount();
[Link](2000);
[Link](500);
[Link](5000);
[Link]("Balance = " + [Link]());
}
}
Sample Output:
Invalid withdrawal!
Balance = 1500.0
3) Read-only Field with final (Account Number)
Level: Basic → Intermediate
Suggested File: P03_Encapsulation_FinalField.java
Concept/Logic:
• Some fields should never change (final). No setter is provided.
Code:
class BankAccount {
private final String accountNumber;
private double balance;
public BankAccount(String accountNumber) {
[Link] = accountNumber;
}
public String getAccountNumber() {
return accountNumber;
}
public void deposit(double amount) {
if (amount > 0) balance += amount;
}
public double getBalance() {
return balance;
}
}
public class P03_Encapsulation_FinalField {
public static void main(String[] args) {
BankAccount acc = new BankAccount("PK-101");
[Link](1000);
[Link]([Link]() + " => " +
[Link]());
}
}
Sample Output:
PK-101 => 1000.0
4) Immutable Class (Student)
Level: Intermediate
Suggested File: P04_Encapsulation_Immutable.java
Concept/Logic:
• Immutable objects have only final fields and no setters; state never changes after
construction.
Code:
final class Student {
private final String name;
private final int age;
public Student(String name, int age) {
if (name == null || [Link]()) throw new
IllegalArgumentException("Name required");
if (age <= 0) throw new IllegalArgumentException("Age must be
positive");
[Link] = name;
[Link] = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
public class P04_Encapsulation_Immutable {
public static void main(String[] args) {
Student s = new Student("Ali", 19);
[Link]([Link]() + " - " + [Link]());
}
}
Sample Output:
Ali - 19
5) Defensive Copy (Protect internal array)
Level: Intermediate
Suggested File: P05_Encapsulation_DefensiveCopy.java
Concept/Logic:
• If you store arrays/collections internally, return a copy so outside code cannot modify
internal state.
Code:
import [Link];
class Marks {
private final int[] scores;
public Marks(int[] scores) {
[Link] = [Link](scores, [Link]);
}
public int[] getScores() {
return [Link](scores, [Link]);
}
}
public class P05_Encapsulation_DefensiveCopy {
public static void main(String[] args) {
int[] arr = {90, 80, 70};
Marks m = new Marks(arr);
int[] got = [Link]();
got[0] = 0; // this should NOT change internal array
[Link]([Link]([Link]()));
}
}
Sample Output:
[90, 80, 70]
6) Encapsulated Counter with static (Shared)
Level: Basic
Suggested File: P06_Encapsulation_StaticCounter.java
Concept/Logic:
• Use private static field to keep shared state; provide controlled access via methods.
Code:
class User {
private static int count = 0;
private final String name;
public User(String name) {
[Link] = name;
count++;
}
public String getName() { return name; }
public static int getCount() { return count; }
}
public class P06_Encapsulation_StaticCounter {
public static void main(String[] args) {
new User("A");
new User("B");
new User("C");
[Link]("Users created = " + [Link]());
}
}
Sample Output:
Users created = 3
7) Singleton (Encapsulation + controlled instance)
Level: Advanced
Suggested File: P07_Encapsulation_Singleton.java
Concept/Logic:
• Private constructor prevents external objects; a public method returns the single instance.
Code:
class Logger {
private static final Logger instance = new Logger();
private Logger() { }
public static Logger getInstance() {
return instance;
}
public void log(String msg) {
[Link]("[LOG] " + msg);
}
}
public class P07_Encapsulation_Singleton {
public static void main(String[] args) {
Logger a = [Link]();
Logger b = [Link]();
[Link]("Hello");
[Link](a == b); // same instance
}
}
Sample Output:
[LOG] Hello
true
8) Encapsulation with Input (Simple ATM Menu)
Level: Intermediate
Suggested File: P08_Encapsulation_ATM.java
Concept/Logic:
• User input interacts only through methods; balance stays private.
Code:
import [Link];
class Account {
private double balance;
public void deposit(double amount) {
if (amount > 0) balance += amount;
else [Link]("Invalid deposit");
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) balance -= amount;
else [Link]("Invalid withdrawal");
}
public double getBalance() {
return balance;
}
}
public class P08_Encapsulation_ATM {
public static void main(String[] args) {
Scanner sc = new Scanner([Link]);
Account acc = new Account();
[Link]("1) Deposit 2) Withdraw 3) Balance 4) Exit");
int choice;
do {
[Link]("Enter choice: ");
choice = [Link]();
if (choice == 1) {
[Link]("Amount: ");
[Link]([Link]());
} else if (choice == 2) {
[Link]("Amount: ");
[Link]([Link]());
} else if (choice == 3) {
[Link]("Balance = " + [Link]());
}
} while (choice != 4);
[Link]("Bye");
}
}
Sample Output:
Example Run (one possible):
1) Deposit 2) Withdraw 3) Balance 4) Exit
Enter choice: 1
Amount: 1000
Enter choice: 3
Balance = 1000.0
Enter choice: 4
Bye
Inheritance
9) Basic extends (Animal → Dog)
Level: Very Basic
Suggested File: P09_Inheritance_Extends.java
Concept/Logic:
• Child inherits parent methods.
Code:
class Animal {
void eat() {
[Link]("Animal eats");
}
}
class Dog extends Animal {
void bark() {
[Link]("Dog barks");
}
}
public class P09_Inheritance_Extends {
public static void main(String[] args) {
Dog d = new Dog();
[Link]();
[Link]();
}
}
Sample Output:
Animal eats
Dog barks
10) Overriding + super (Dog overrides eat)
Level: Basic
Suggested File: P10_Inheritance_OverrideSuper.java
Concept/Logic:
• Override to change behavior; call super to reuse base logic.
Code:
class Animal {
void eat() {
[Link]("Animal eats food");
}
}
class Dog extends Animal {
@Override
void eat() {
[Link]();
[Link]("Dog eats meat");
}
}
public class P10_Inheritance_OverrideSuper {
public static void main(String[] args) {
new Dog().eat();
}
}
Sample Output:
Animal eats food
Dog eats meat
11) super() constructor call (Person → Student)
Level: Basic → Intermediate
Suggested File: P11_Inheritance_SuperConstructor.java
Concept/Logic:
• Child constructor calls parent constructor using super(...).
Code:
class Person {
private final String name;
public Person(String name) {
[Link] = name;
}
public String getName() { return name; }
}
class Student extends Person {
private final int roll;
public Student(String name, int roll) {
super(name);
[Link] = roll;
}
public int getRoll() { return roll; }
}
public class P11_Inheritance_SuperConstructor {
public static void main(String[] args) {
Student s = new Student("Raahim", 12);
[Link]([Link]() + " roll=" + [Link]());
}
}
Sample Output:
Raahim roll=12
12) Multilevel (Animal → Dog → Puppy)
Level: Intermediate
Suggested File: P12_Inheritance_Multilevel.java
Concept/Logic:
• Multilevel inheritance forms a hierarchy.
Code:
class Animal {
void sleep() { [Link]("Animal sleeps"); }
}
class Dog extends Animal {
void bark() { [Link]("Dog barks"); }
}
class Puppy extends Dog {
void weep() { [Link]("Puppy weeps"); }
}
public class P12_Inheritance_Multilevel {
public static void main(String[] args) {
Puppy p = new Puppy();
[Link]();
[Link]();
[Link]();
}
}
Sample Output:
Animal sleeps
Dog barks
Puppy weeps
13) Hierarchical (Animal → Dog, Cat)
Level: Intermediate
Suggested File: P13_Inheritance_Hierarchical.java
Concept/Logic:
• One parent, many children.
Code:
class Animal {
void sound() { [Link]("Some sound"); }
}
class Dog extends Animal {
@Override void sound() { [Link]("Bark"); }
}
class Cat extends Animal {
@Override void sound() { [Link]("Meow"); }
}
public class P13_Inheritance_Hierarchical {
public static void main(String[] args) {
new Dog().sound();
new Cat().sound();
}
}
Sample Output:
Bark
Meow
14) final method prevents overriding
Level: Intermediate
Suggested File: P14_Inheritance_FinalMethod.java
Concept/Logic:
• final method cannot be overridden; ensures stable behavior.
Code:
class Base {
final void show() {
[Link]("This cannot be overridden");
}
}
class Child extends Base {
// void show() { } // ERROR if uncommented
}
public class P14_Inheritance_FinalMethod {
public static void main(String[] args) {
new Child().show();
}
}
Sample Output:
This cannot be overridden
15) Composition over Inheritance (Car has Engine)
Level: Advanced
Suggested File: P15_Inheritance_Composition.java
Concept/Logic:
• Prefer composition when behavior should be contained, not inherited.
Code:
class Engine {
void start() { [Link]("Engine starts"); }
}
class Car {
private final Engine engine = new Engine();
void startCar() {
[Link]();
[Link]("Car moves");
}
}
public class P15_Inheritance_Composition {
public static void main(String[] args) {
new Car().startCar();
}
}
Sample Output:
Engine starts
Car moves
16) instanceof + safe casting
Level: Advanced
Suggested File: P16_Inheritance_Instanceof.java
Concept/Logic:
• Check actual object type before casting to avoid ClassCastException.
Code:
class Animal { }
class Dog extends Animal { void bark(){ [Link]("Bark"); } }
class Cat extends Animal { void meow(){ [Link]("Meow"); } }
public class P16_Inheritance_Instanceof {
public static void main(String[] args) {
Animal a = new Dog();
if (a instanceof Dog d) { // pattern matching (Java 16+)
[Link]();
} else if (a instanceof Cat c) {
[Link]();
}
}
}
Sample Output:
Bark
Polymorphism
17) Method Overloading (add)
Level: Very Basic
Suggested File: P17_Polymorphism_Overloading.java
Concept/Logic:
• Same method name, different parameters (compile-time polymorphism).
Code:
class Calculator {
int add(int a, int b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
double add(double a, double b) { return a + b; }
}
public class P17_Polymorphism_Overloading {
public static void main(String[] args) {
Calculator c = new Calculator();
[Link]([Link](2, 3));
[Link]([Link](2, 3, 4));
[Link]([Link](2.5, 1.5));
}
}
Sample Output:
5
9
4.0
18) Runtime Polymorphism (Shape reference)
Level: Basic
Suggested File: P18_Polymorphism_Runtime.java
Concept/Logic:
• Parent reference points to child; overridden method chosen at runtime.
Code:
class Shape {
void draw() { [Link]("Drawing shape"); }
}
class Circle extends Shape {
@Override void draw() { [Link]("Drawing circle"); }
}
class Rectangle extends Shape {
@Override void draw() { [Link]("Drawing rectangle"); }
}
public class P18_Polymorphism_Runtime {
public static void main(String[] args) {
Shape s1 = new Circle();
Shape s2 = new Rectangle();
[Link]();
[Link]();
}
}
Sample Output:
Drawing circle
Drawing rectangle
19) Polymorphism in Arrays (Areas)
Level: Basic → Intermediate
Suggested File: P19_Polymorphism_Array.java
Concept/Logic:
• Treat many child objects uniformly through base type.
Code:
class Shape {
double area() { return 0; }
}
class Circle extends Shape {
private final double r;
Circle(double r){ this.r = r; }
@Override double area(){ return [Link] * r * r; }
}
class Rectangle extends Shape {
private final double w, h;
Rectangle(double w, double h){ this.w=w; this.h=h; }
@Override double area(){ return w*h; }
}
public class P19_Polymorphism_Array {
public static void main(String[] args) {
Shape[] arr = { new Circle(2), new Rectangle(3,4) };
for (Shape s : arr) [Link]("%.2f
", [Link]());
}
}
Sample Output:
12.57
12.00
20) Interface Polymorphism (Flyable)
Level: Intermediate
Suggested File: P20_Polymorphism_Interface.java
Concept/Logic:
• Same interface used with different implementations.
Code:
interface Flyable {
void fly();
}
class Bird implements Flyable {
public void fly() { [Link]("Bird flies"); }
}
class Plane implements Flyable {
public void fly() { [Link]("Plane flies"); }
}
public class P20_Polymorphism_Interface {
public static void main(String[] args) {
Flyable f1 = new Bird();
Flyable f2 = new Plane();
[Link]();
[Link]();
}
}
Sample Output:
Bird flies
Plane flies
21) Covariant Return Type
Level: Intermediate
Suggested File: P21_Polymorphism_Covariant.java
Concept/Logic:
• Overridden method may return a subtype (covariant) in Java.
Code:
class Animal {
Animal get(){ return new Animal(); }
}
class Dog extends Animal {
@Override Dog get(){ return new Dog(); }
void bark(){ [Link]("Bark"); }
}
public class P21_Polymorphism_Covariant {
public static void main(String[] args) {
Animal a = new Dog();
Dog d = (Dog) [Link]();
[Link]();
}
}
Sample Output:
Bark
22) Strategy Pattern (Payment)
Level: Advanced
Suggested File: P22_Polymorphism_Strategy.java
Concept/Logic:
• Swap behavior at runtime by changing the strategy object.
Code:
interface PaymentStrategy {
void pay(int amount);
}
class CashPayment implements PaymentStrategy {
public void pay(int amount) { [Link]("Paid " + amount + " by
Cash"); }
}
class CardPayment implements PaymentStrategy {
public void pay(int amount) { [Link]("Paid " + amount + " by
Card"); }
}
class Cart {
private PaymentStrategy strategy;
void setStrategy(PaymentStrategy s){ strategy = s; }
void checkout(int amount){
if(strategy==null) { [Link]("Select payment method");
return; }
[Link](amount);
}
}
public class P22_Polymorphism_Strategy {
public static void main(String[] args) {
Cart cart = new Cart();
[Link](new CashPayment());
[Link](1000);
[Link](new CardPayment());
[Link](2500);
}
}
Sample Output:
Paid 1000 by Cash
Paid 2500 by Card
23) Dynamic Dispatch in Methods (processShape)
Level: Advanced
Suggested File: P23_Polymorphism_Dispatch.java
Concept/Logic:
• A single method can work with any subtype; runtime decides which override runs.
Code:
class Shape {
void draw(){ [Link]("Shape"); }
}
class Circle extends Shape {
@Override void draw(){ [Link]("Circle"); }
}
class Square extends Shape {
@Override void draw(){ [Link]("Square"); }
}
public class P23_Polymorphism_Dispatch {
static void process(Shape s){
[Link]();
}
public static void main(String[] args) {
process(new Circle());
process(new Square());
}
}
Sample Output:
Circle
Square
24) Overloading vs Overriding (quick demo)
Level: Intermediate
Suggested File: P24_Polymorphism_OverloadVsOverride.java
Concept/Logic:
• Overloading: same name, different params. Overriding: same signature in child.
Code:
class Parent {
void show(int x){ [Link]("Parent show(int): " + x); }
}
class Child extends Parent {
// Overloading (different params)
void show(String s){ [Link]("Child show(String): " + s); }
// Overriding (same signature)
@Override
void show(int x){ [Link]("Child show(int): " + x); }
}
public class P24_Polymorphism_OverloadVsOverride {
public static void main(String[] args) {
Parent p = new Child();
[Link](10); // overriding
Child c = new Child();
[Link]("Hello"); // overloading
}
}
Sample Output:
Child show(int): 10
Child show(String): Hello
Abstraction
25) Abstract Class (Vehicle → Bike)
Level: Very Basic
Suggested File: P25_Abstraction_AbstractClass.java
Concept/Logic:
• Abstract class cannot be instantiated; forces implementation of abstract methods.
Code:
abstract class Vehicle {
abstract void start();
}
class Bike extends Vehicle {
@Override void start(){ [Link]("Bike starts"); }
}
public class P25_Abstraction_AbstractClass {
public static void main(String[] args) {
Vehicle v = new Bike();
[Link]();
}
}
Sample Output:
Bike starts
26) Interface (Printable)
Level: Basic
Suggested File: P26_Abstraction_Interface.java
Concept/Logic:
• Interface defines what to do, not how.
Code:
interface Printable {
void print();
}
class Document implements Printable {
public void print(){ [Link]("Printing document"); }
}
public class P26_Abstraction_Interface {
public static void main(String[] args) {
Printable p = new Document();
[Link]();
}
}
Sample Output:
Printing document
27) Template Method Style (Notification)
Level: Basic → Intermediate
Suggested File: P27_Abstraction_TemplateMethod.java
Concept/Logic:
• Common steps in base class; varying step as abstract method.
Code:
abstract class Notification {
public final void send(String msg){
connect();
deliver(msg);
disconnect();
}
private void connect(){ [Link]("Connecting..."); }
private void disconnect(){ [Link]("Disconnected"); }
protected abstract void deliver(String msg);
}
class EmailNotification extends Notification {
@Override protected void deliver(String msg){ [Link]("Email: "
+ msg); }
}
class SMSNotification extends Notification {
@Override protected void deliver(String msg){ [Link]("SMS: " +
msg); }
}
public class P27_Abstraction_TemplateMethod {
public static void main(String[] args) {
new EmailNotification().send("Hello");
new SMSNotification().send("Hi");
}
}
Sample Output:
Connecting...
Email: Hello
Disconnected
Connecting...
SMS: Hi
Disconnected
28) Dependency Inversion (Database interface)
Level: Intermediate
Suggested File: P28_Abstraction_DIP.java
Concept/Logic:
• High-level module depends on abstraction, not concrete class.
Code:
interface Database {
void save(String data);
}
class MySQLDatabase implements Database {
public void save(String data){ [Link]("Saved to MySQL: " +
data); }
}
class MongoDatabase implements Database {
public void save(String data){ [Link]("Saved to Mongo: " +
data); }
}
class UserService {
private final Database db;
UserService(Database db){ [Link] = db; }
void register(String name){ [Link]("User=" + name); }
}
public class P28_Abstraction_DIP {
public static void main(String[] args) {
new UserService(new MySQLDatabase()).register("Raahim");
new UserService(new MongoDatabase()).register("Ali");
}
}
Sample Output:
Saved to MySQL: User=Raahim
Saved to Mongo: User=Ali
29) Interface default method
Level: Intermediate
Suggested File: P29_Abstraction_DefaultMethod.java
Concept/Logic:
• Interfaces can provide default implementations (reusable behavior).
Code:
interface Greeter {
void sayHello(String name);
default void sayBye(){
[Link]("Bye!");
}
}
class FriendlyGreeter implements Greeter {
public void sayHello(String name){
[Link]("Hello, " + name);
}
}
public class P29_Abstraction_DefaultMethod {
public static void main(String[] args) {
Greeter g = new FriendlyGreeter();
[Link]("Raahim");
[Link]();
}
}
Sample Output:
Hello, Raahim
Bye!
30) Multiple Interfaces (ScannerDevice)
Level: Intermediate
Suggested File: P30_Abstraction_MultipleInterfaces.java
Concept/Logic:
• A class can implement multiple interfaces (multiple abstraction sources).
Code:
interface Printable { void print(); }
interface Scannable { void scan(); }
class MultiFunctionPrinter implements Printable, Scannable {
public void print(){ [Link]("Printing..."); }
public void scan(){ [Link]("Scanning..."); }
}
public class P30_Abstraction_MultipleInterfaces {
public static void main(String[] args) {
MultiFunctionPrinter m = new MultiFunctionPrinter();
[Link]();
[Link]();
}
}
Sample Output:
Printing...
Scanning...
31) Abstract Factory (simple UI factory)
Level: Advanced
Suggested File: P31_Abstraction_AbstractFactory.java
Concept/Logic:
• Create families of related objects without specifying concrete classes.
Code:
interface Button { void paint(); }
interface TextBox { void render(); }
class WindowsButton implements Button {
public void paint(){ [Link]("Windows Button"); }
}
class WindowsTextBox implements TextBox {
public void render(){ [Link]("Windows TextBox"); }
}
class MacButton implements Button {
public void paint(){ [Link]("Mac Button"); }
}
class MacTextBox implements TextBox {
public void render(){ [Link]("Mac TextBox"); }
}
interface UIFactory {
Button createButton();
TextBox createTextBox();
}
class WindowsFactory implements UIFactory {
public Button createButton(){ return new WindowsButton(); }
public TextBox createTextBox(){ return new WindowsTextBox(); }
}
class MacFactory implements UIFactory {
public Button createButton(){ return new MacButton(); }
public TextBox createTextBox(){ return new MacTextBox(); }
}
public class P31_Abstraction_AbstractFactory {
static void run(UIFactory factory){
[Link]().paint();
[Link]().render();
}
public static void main(String[] args) {
run(new WindowsFactory());
run(new MacFactory());
}
}
Sample Output:
Windows Button
Windows TextBox
Mac Button
Mac TextBox
32) Mega Program: All 4 Pillars Together (Bank Account)
Level: Advanced (All pillars together)
Suggested File: P32_AllPillars_Mega.java
Concept/Logic:
• Encapsulation: private balance + controlled methods
• Inheritance: SavingsAccount extends Account
• Polymorphism: override withdraw()
• Abstraction: Account is abstract
Code:
abstract class Account {
private final String id;
private double balance;
public Account(String id, double initial) {
[Link] = id;
if (initial < 0) throw new IllegalArgumentException("Initial cannot be
negative");
[Link] = initial;
}
public String getId() { return id; }
public double getBalance() { return balance; }
protected void setBalance(double b) { [Link] = b; }
public void deposit(double amount) {
if (amount <= 0) {
[Link]("Invalid deposit");
return;
}
setBalance(getBalance() + amount);
}
public abstract void withdraw(double amount);
}
class SavingsAccount extends Account {
private final double minBalance = 500;
public SavingsAccount(String id, double initial) {
super(id, initial);
}
@Override
public void withdraw(double amount) {
if (amount <= 0) {
[Link]("Invalid withdraw");
return;
}
if (getBalance() - amount < minBalance) {
[Link]("Min balance must remain " + minBalance);
return;
}
setBalance(getBalance() - amount);
[Link]("Withdraw OK");
}
}
public class P32_AllPillars_Mega {
public static void main(String[] args) {
Account acc = new SavingsAccount("SA-1", 2000);
[Link](1000);
[Link](2200);
[Link](200);
[Link]("Final Balance = " + [Link]());
}
}
Sample Output:
Min balance must remain 500.0
Withdraw OK
Final Balance = 800.0