OOP Java Complete Notes
OOP Java Complete Notes
void display() {
[Link](id + " " + name + " " + university);
}
public static void main(String[] args) {
Student s1 = new Student();
[Link] = 1; [Link] = "Ali";
Student s2 = new Student();
[Link] = 2; [Link] = "Rohail";
[Link]();
[Link]();
}
}
// Output:
// 1 Ali DUET
// 2 Rohail DUET <-- university is shared
Counter() {
count++; // increments shared counter each time object
is made
}
1. private
Access is only within the same class. Cannot be accessed from outside
the class at all. If you need to access private variables from outside, use
getter/setter methods.
class Data {
private String name; // only accessible inside Data class
// getter method
public String getName() {
return [Link];
}
// setter method
public void setName(String name) {
[Link] = name;
}
}
public class Main {
public static void main(String[] args) {
Data d = new Data();
[Link]("Programiz");
[Link]([Link]());
}
}
3. protected
Accessible within the package AND by subclasses outside the package
through inheritance. If you do not create a child class, it cannot be
accessed from outside the package.
class Animal {
protected void display() {
[Link]("Animal");
}
}
class Dog extends Animal {
public static void main(String[] args) {
Dog d = new Dog();
[Link](); // OK — Dog is a subclass
}
}
4. public
The access level is everywhere. It can be accessed from within the class,
outside the class, within the package, and outside the package. No
restrictions.
public class Animal {
public void display() {
[Link]("Animal");
}
}
✅ Memory tip: private < default < protected < public (increasing
visibility order)
3. Destructor in Java / Garbage Collection
What is a Destructor?
A destructor is a special method used to destroy an object and free
memory when the object is no longer needed. It works opposite to a
constructor: constructor creates/initializes, destructor destroys.
⚠ Java does NOT have explicit destructors like C++. Java uses
automatic Garbage Collection (GC) instead.
Constructor vs Destructor
Feature Constructor Destructor
Purpose Initialize object Destroy object
Called when Object is created Object is removed/GC
runs
Feature Constructor Destructor
In Java Yes (explicit) No explicit — GC
handles it
Automatic? No — you write it Yes — GC does it
automatically
Keyword Same name as class finalize() method (Java)
What is Inheritance?
Inheritance is a mechanism in Java where one class acquires all the
properties and behaviors of a parent class. It represents an IS-A
relationship between two classes. The main purpose is code reusability
— child classes can reuse methods of the parent class.
Keyword used: extends
class Parent {
// parent code
}
Simple Example:
class super {
public void display() {
[Link]("I am parent class");
}
}
class sub extends super {
public static void main(String[] args) {
sub message = new sub();
[Link](); // calls parent method
}
}
// Output: I am parent class
Key Terms
• Superclass (Parent class) — the class being inherited from.
• Subclass (Child class) — the class that inherits.
• IS-A relationship — e.g., a Car IS-A Vehicle.
• Method Overriding — child class redefines a method of the parent
class.
• super keyword — used to call parent class constructor or method.
5. Polymorphism
What is Polymorphism?
Polymorphism means "many forms". It is the ability of an object to take
more than one form. In Java, it allows multiple objects of different
subclasses to be treated as objects of a single parent class, while
automatically selecting the proper method to apply based on the actual
object type.
More precisely: it means a call to a member function will cause a different
function to be executed depending on the type of object that invokes it.
Types of Polymorphism
Type Also Called How Achieved When
Resolved
Compile-time Static / Early Method Overloading, At compile
Binding Operator Overloading time
Run-time Dynamic / Late Method Overriding At runtime
Binding (Virtual Functions) by JVM
Overloading vs Overriding
Feature Overloading Overriding
Occurs in Same class Parent and child class
Parameters Must be different Must be same
Return type Can differ Must be same (or
covariant)
Binding Compile time (static) Runtime (dynamic)
Polymorphism Compile-time Runtime
Keyword None needed @Override
(recommended)
6. Abstract Classes
What is Abstraction?
Abstraction is the process of hiding implementation details and showing
only the functionality to the user. It lets you focus on what the object does,
not how it does it.
Two ways to achieve abstraction in Java:
• Abstract class (0% to 100% abstraction)
• Interface (100% abstraction)
Abstract Class
A class declared with the abstract keyword. It can have both abstract
methods (no body) and non-abstract methods (with body).
Key Rules:
• Must be declared with abstract keyword.
• Can have abstract AND non-abstract methods.
• Cannot be instantiated — you cannot create objects of an abstract
class directly.
• Can have constructors and static methods.
• Can have final methods (which force subclass not to override them).
• Subclass must implement all abstract methods (or itself be
abstract).
// Abstract class — cannot create object of it directly
abstract class Bike {
abstract void run(); // abstract method — no body
}
// This is correct:
class English extends Language { /* implement methods */ }
Language obj = new English(); // OK
Abstract Method
A method declared with abstract keyword that has no body. The subclass
must provide the implementation.
abstract void printStatus(); // no method body — subclass must
implement
T getValue() {
return value;
}
}
Generic Method
class Printer {
public <T> void print(T item) {
[Link](item);
}
}
Benefits of Generics
• Type safety — detects type errors at compile time.
• Code reusability — one class works for multiple types.
• Eliminates need for explicit type casting.
8. Exception Handling in Java
What is an Exception?
An exception is an unwanted or unexpected event that disrupts the normal
flow of a program. Exception handling allows the program to gracefully
handle runtime errors.
Exception Hierarchy
• Throwable — root of all exceptions.
• Error — serious problems (StackOverflowError, OutOfMemoryError)
— not recoverable.
• Exception — recoverable problems.
• — Checked exceptions: must be handled (IOException,
SQLException).
• — Unchecked exceptions (RuntimeException):
NullPointerException, ArrayIndexOutOfBoundsException, etc.
try-catch-finally Block
try {
// code that might throw an exception
int result = 10 / 0;
} catch (ArithmeticException e) {
// handle the exception
[Link]("Cannot divide by zero: " +
[Link]());
} catch (Exception e) {
// catch any other exception
[Link]("Error: " + [Link]());
} finally {
// always executes — used for cleanup (closing files, etc.)
[Link]("This always runs");
}
throw Example:
public class Main {
static void checkAge(int age) {
if (age < 18)
throw new ArithmeticException("Not eligible to
vote");
else
[Link]("Eligible to vote");
}
public static void main(String[] args) {
checkAge(15); // throws exception
}
}
// Output: Exception in thread "main"
[Link]: Not eligible to vote
Custom Exception
class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
What is Serialization?
Serialization is the process of converting an object into a byte stream so
it can be saved to a file, database, or sent over a network. Deserialization
is the reverse — converting the byte stream back into an object.
Key Points
• A class must implement the Serializable interface to be serialized.
• The Serializable interface is a marker interface — it has no
methods.
• Use ObjectOutputStream to serialize (write) objects.
• Use ObjectInputStream to deserialize (read) objects.
• Fields marked with transient keyword are NOT serialized.
• The class must have the same serialVersionUID for deserialization
to work.
transient Keyword
Fields marked as transient are skipped during serialization. Use this for
sensitive data like passwords.
class Student implements Serializable {
int id;
String name;
transient String password; // will NOT be serialized
}
class Test {
int value;
public:
Test(int v = 0) { value = v; }
int getValue() const { return value; } // const function —
cannot modify
void setValue(int v) { value = v; } // non-const
function
};
int main() {
const Test t(10);
cout << [Link](); // OK — calling const function on
const object
// [Link](20); // ERROR — cannot call non-const on
const object
}
Non-Constant Function
A non-const function can modify the object's data. It can only be called on
non-const objects. If you try to call a non-const function on a const object,
the compiler gives an error.
⚠ If a const object tries to call a non-const function, the error is:
"passing const X as this argument discards qualifiers"
Data Members & Member Functions — Memory
Representation
• Each newly created object has its own copies of the class's data
members.
• Member functions are stored only ONCE in memory — shared by all
objects.
• This makes sense because all objects use the same function code.
• Data items hold different values per object — each object gets a
separate copy.
• Functions are identical across objects — created once when class is
defined.
Diagram concept: Object 1 has data1, data2. Object 2 has data1, data2.
Object 3 has data1, data2. All three share the same function1() and
function2() in memory.
Defining a Class
A CLASS is a template (specification, blueprint) for a collection of objects
that share a common set of attributes and operations. Objects are
instances of a class.
Types of Relationships
Relationship Symbol/Line Description Example
Association Solid line with A general connection Employee
arrow between two classes works for
Company
Aggregation Open diamond HAS-A (weak): parts Faculty has
can exist without the CourseTeachi
whole ng
Composition Filled diamond HAS-A (strong): parts SalesOrder
cannot exist without has LineItems
the whole
Dependency Dashed arrow A change in one class Dependent
may affect another class uses
(weaker) Reference
Relationship Symbol/Line Description Example
class
Generalization Solid line + IS-A relationship Car IS-A
open triangle (inheritance). Arrow Vehicle
arrow points to parent
Realization Dashed line + Class is derived from Interface class
open triangle an interface instead of -> Derived
a base class class
Generalization
Deriving a class out of a parent class, having some inherited property (from
the parent) and some new property of the derived class. The term
generalization refers to inheritance viewed from the bottom up — from
derived class to parent class. Represented by a solid line with a large open
arrowhead pointing towards the parent class.
Dependency
A dependency is a weaker form of relationship. It states that a change in
specification of one class may affect another class that uses it, but not vice
versa. Represented by dashed lines with an arrow.
Realization
Realization is very similar to inheritance. The difference is that a class is
derived from an interface instead of a base class. An interface is an
abstract class. Represented by a dashed line with an open arrowhead.
12. Class Templates (C++)
int main() {
cout << myMax<int>(3, 7) << endl; // uses int version
-> 7
cout << myMax<char>('g', 'e') << endl; // uses char version
-> g
return 0;
}
// Compiler internally generates:
// int myMax(int x, int y) { return (x>y)?x:y; }
// char myMax(char x, char y) { return (x>y)?x:y; }
Box<string> strBox;
[Link]("Hello");
cout << [Link](); // Hello
}
3 Components of STL
Component Purpose Analogy
Containers Store and hold data (objects) Data Storage
Algorithms Manipulate and process data Data Access /
in containers Operations
Iterators Pointer-like objects to access Like array indexes
individual elements in but for any container
containers
1. Containers
Container classes store objects and data. There are 7 standard first-class
container classes and 3 container adaptor classes.
Sequence Containers — accessed in sequential order:
Container Description
vector Dynamic array — resizable, random access, fast at
end
list Doubly linked list — fast insert/erase anywhere, no
random access
Container Description
deque Double-ended queue — fast insert/erase at both front
and back
2. Iterators
Iterators are pointer-like entries used to access individual elements in a
container. They are commonly used to move sequentially from element to
element — a process called iterating through the container.
#include<vector>
#include<iostream>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40};
int main() {
vector<int> v = {3, 1, 4, 1, 5, 9};
int total = 0;
for (int x : v) total += x;
cout << "Sum: " << total;
}