2025-06-18
A comprehensive journey through OOP concepts with practical examples and real-world applications
Let's consider a problem: A university needs to manage student data, including roll numbers, names, and marks. The goal is to create an application that can store and manipulate this data efficiently.
Initially, one might think of using separate arrays for each property:
However, this approach is not ideal because it scatters related data across multiple arrays. A better solution is to use a class to group these properties into a single entity.
A class is a named group of properties(attributes) and Methods(functions). It allows you to combine related data into a single entity.
In this case, a
class can be created to hold the roll number, name, and marks of a student.By convention, class names start with a capital letter.
Using a class, you can create a
data type:java
This creates a
object named , which will contain the three properties: roll number, name, and marks.A class is a logical construct or a template, while an object is a physical instance of that class. Think of a class as a blueprint and an object as the actual building constructed from that blueprint.
Consider a
class. It defines the properties and functions that all cars have, such as price, number of seats, and engine type. Different companies like BMW, Audi, and Ferrari use this template to create their own cars.text
Each car has the same properties (engine, price, seats), but the values of these properties can be different for each car.
The
class defines the rules for what a human is: two arms, two legs, a head, etc. Actual humans (objects) are instances of this class, each with their own unique characteristics.Objects are characterized by:
To create an object, you use the
keyword. This keyword allocates memory for the object and returns a reference to it.java
Here,
is a reference variable of type . The part creates the object in memory.Important: In Java, all objects are stored in heap memory.
Dynamic memory allocation means that memory is allocated at runtime. When the Java code compiles, it doesn't know how much memory will be needed. The
keyword allocates memory when the program is running.To access the properties of an object, you use the dot operator (
).java
This will print the value of the
property of the object.Instance variables are variables that are declared inside the class but outside any method or constructor. They hold the state of the object.
Let's create a
class with properties for roll number, name, and marks.java
When an object is created, its properties are initialized with default values.
You can modify the properties of an object using the dot operator.
java
A constructor is a special type of function that is called when an object is created. It is used to initialize the object's properties.
If you don't define a constructor in your class, Java will provide a default constructor. This constructor takes no arguments and initializes all properties to their default values.
You can define your own constructors to initialize the object's properties with specific values.
java
The
keyword is used to refer to the current object. It is used to differentiate between the instance variables and the local variables.java
Here,
refers to the instance variable , while refers to the local variable .java
java
Constructor overloading is the ability to define multiple constructors with different parameters. This allows you to create objects in different ways.
java
The
keyword is used to prevent a variable from being modified after it has been initialized.java
If a variable is declared as
and it is a primitive type, its value cannot be changed.If a variable is declared as
and it is a reference type, the reference cannot be changed, but the object's properties can be changed.java
Java has automatic garbage collection, which means that it automatically reclaims memory that is no longer being used. When an object is about to be garbage collected, the
method is called.Note: You cannot manually destroy objects in Java.
The
method is used to perform any cleanup operations before an object is garbage collected.java
When you assign one object reference to another, you are not creating a new object. You are simply creating another reference to the same object.
java
In this case,
and both refer to the same object. If you modify the object through , the changes will also be visible through .Wrapper classes are used to convert primitive types into objects. For example, the
class is used to wrap an .java
Wrapper classes are useful because they allow you to treat primitive types as objects. This is necessary in some cases, such as when you need to store primitive types in a collection.
In Java, primitive types are passed by value, while objects are passed by reference. This means that when you pass a primitive type to a method, the method receives a copy of the value. When you pass an object to a method, the method receives a copy of the reference.
Static members (variables and methods) belong to the class itself rather than to any specific instance of the class. This means there's only one copy of a static variable, shared among all objects of that class.
Static variables are initialized only once, when the class is first loaded. They are not tied to any particular object. The speaker uses the example of a
class with a variable. The population count is a property of all humans collectively, not of each individual human.java
Note: Access static variables using the class name (
) rather than an object reference (). Although using an object reference might work, it's not the recommended practice.
Static methods, like static variables, belong to the class itself. They can be called without creating an object of the class. A common example is the
method, which is the entry point of a Java program.java
The
method must be static because it needs to be executed before any objects are created.
Static methods have some limitations:
java
Static blocks are used to initialize static variables. They are executed only once, when the class is first loaded.
java
Static blocks are useful for performing complex initialization logic that cannot be done in a single line.
Only nested classes (classes declared inside another class) can be declared as static. A static nested class is like a static member of the outer class. It can be accessed using the outer class name.
java
A non-static nested class (also called an inner class) has access to the members of the outer class, even if they are private. A static nested class does not have this access.
Packages are used to organize classes and interfaces into namespaces, providing a way to manage large codebases and avoid naming conflicts. Think of packages as folders or directories that contain related files.
To declare a class as part of a package, use the
keyword at the beginning of the source file.java
The package name should follow a hierarchical structure, often based on the organization's domain name in reverse order (e.g.,
).
To use a class from a different package, you need to import it using the
keyword.java
You can also import all classes from a package using a wildcard:
When working with packages, access modifiers like
, , and control the visibility of classes and members. If a class or member is not declared with any access modifier (package-private), it is only accessible within the same package.The speaker breaks down the ubiquitous
statement.Because
is a static member, you don't need to create an object of the class to use it.
The
method is a method inherited from the class that provides a string representation of an object. By default, it returns a string containing the class name and the object's hash code. You can override this method in your own classes to provide a more meaningful string representation.java
Overriding
is useful for debugging and logging.
The speaker introduces the Singleton design pattern, which ensures that a class has only one instance and provides a global point of access to it.
java
The Singleton pattern is useful when you need to control the creation of objects and ensure that only one instance exists (e.g., for managing resources or configurations).
Inheritance is a core concept where a class (child class) inherits properties and functions from another class (base class or parent class). This promotes code reuse and establishes a hierarchy between classes.
Note: Think of real-life inheritance, where children inherit traits and properties from their parents.
In OOP, the child class gains access to the members of the base class. For example, if a base class defines
, , and , a child class inheriting from it can directly use these properties. Additionally, the child class can have its own unique properties.java
The
keyword in Java is used to establish the inheritance relationship. The child class can then access the base class's members.java
When a constructor is called for the child class, it's crucial to initialize the parent class's variables as well. This is often done using the
keyword.Note: If a member in the base class is declared as
, it cannot be directly accessed by the child class.
Consider a
class with properties like , , and . A class can extend and add a property.java
In the
constructor, calls the constructor of the class to initialize the inherited properties. If you don't call the super constructor, the parent class's variables will not be properly initialized.Important: The type of the reference variable determines what members can be accessed, not the type of the object itself.
java
The
keyword is used to refer to the superclass (parent class). It has two main uses:When calling the superclass constructor, it must be the first statement in the subclass constructor. This ensures that the superclass is properly initialized before the subclass adds its own specific initialization.
There are several types of inheritance:
Polymorphism means "many forms." In OOP, it refers to the ability of an object to take on many forms. This is achieved through method overloading and method overriding.
Method overloading occurs when a class has multiple methods with the same name but different parameters (different number, type, or order of parameters). The compiler determines which method to call based on the arguments passed.
java
Method overriding occurs when a subclass provides a specific implementation for a method that is already defined in its superclass. The method in the subclass must have the same name, return type, and parameters as the method in the superclass.
java
Note: The
annotation is used to indicate that a method is intended to override a method in the superclass. It's good practice to use this annotation to catch errors at compile time.
In this example, even though
is a reference, the method that is called is the one defined in the class. This is because the object is actually a object, and the method is overridden.Java uses dynamic method dispatch to determine which version of an overridden method to call at runtime. This is based on the actual type of the object, not the type of the reference variable.
The
keyword can be used to prevent method overriding. If a method is declared as , it cannot be overridden in any subclass.java
The
keyword can also be used to prevent inheritance. If a class is declared as , it cannot be subclassed.Static methods cannot be overridden. While a subclass can define a static method with the same signature as a static method in the superclass, this is method hiding, not method overriding. The method that is called depends on the class that is used to reference the method.
java
Encapsulation is the bundling of data (attributes) and methods that operate on that data into a single unit (a class). It also involves hiding the internal implementation details of the class from the outside world and providing a public interface for accessing and manipulating the data.
Note: Encapsulation is about protecting the data and controlling access to it.
This is typically achieved by declaring the attributes of a class as
and providing public getter and setter methods (accessors and mutators) for accessing and modifying the attributes.java
In this example, the
and attributes are declared as , which means they can only be accessed from within the class. The public , , , and methods provide a controlled way to access and modify these attributes.Abstraction is the process of hiding complex implementation details and exposing only the essential information to the user. It allows the user to interact with an object without needing to know how it works internally.
Note: Abstraction is about simplifying the interface and hiding complexity.
Abstraction can be achieved through abstract classes and interfaces. An abstract class is a class that cannot be instantiated and may contain abstract methods (methods without an implementation). A subclass of an abstract class must provide an implementation for all abstract methods.
An interface is a collection of abstract methods. A class can implement multiple interfaces, which allows it to inherit multiple behaviors.
Key Difference: Encapsulation is about what data is exposed, while abstraction is about how the data is exposed.
Access control in Java is about protecting data by restricting access to class members. Let's explore the different access modifiers:
When a member (variable or method) is declared
, it can only be accessed from within the same class. Here's an example:java
Note: The
modifier ensures data hiding, which is a key aspect of encapsulation. You can access or modify private members using getter and setter methods.
Members declared as
can be accessed from anywhere, inside or outside the class, and from any package.java
Warning: Using
members extensively can reduce encapsulation and make the code more vulnerable to unintended modifications.
The
modifier allows access within the same class, the same package, and by subclasses, even if they are in a different package. Here's how it works:java
Tip:
is often used in inheritance scenarios where you want subclasses to have access to certain members but prevent access from unrelated classes.
If no access modifier is specified, the member has default (or package-private) access. This means it is accessible only within the same package.
java
Note: Default access is useful for hiding implementation details within a package.
Packages are used to organize classes and interfaces into namespaces, providing better modularity and preventing naming conflicts. There are two types of packages:
Java provides many built-in packages, such as
, , , , , and . The package is automatically imported into every Java program.You can create your own packages to organize your classes. To create a package, declare the package name at the beginning of the Java file:
java
Tip: Packages help in managing large projects by grouping related classes together.
In Java, the
class is the root of the class hierarchy. Every class implicitly or explicitly inherits from the class. It provides several important methods:The
method returns a string representation of the object. It's often overridden to provide a more meaningful representation.java
The
method checks if two objects are equal. The default implementation checks if the two objects are the same instance. It's often overridden to compare the contents of the objects.java
Warning: When overriding
, you should also override to maintain consistency.
The
method returns a hash code value for the object. It's used by hash-based collections like .java
The
method returns the runtime class of the object.java
The
method is called by the garbage collector when the object is no longer in use. It's used to perform cleanup operations.Note: The use of
is discouraged in modern Java development. It's better to use try-with-resources or other explicit cleanup mechanisms.
The
operator checks if an object is an instance of a particular class or interface.java
Java does not support multiple inheritance directly. This is because if a class could inherit from two classes that both have a method with the same name, it would be ambiguous which method to call. This is often referred to as the "diamond problem."
Abstraction allows us to create parent classes that define a contract for their subclasses. The parent class specifies what needs to be done, but leaves the how to the child classes. This is achieved through abstract methods.
Note: An abstract method has no body in the parent class. It's essentially a placeholder that must be implemented by any concrete (non-abstract) subclass.
Consider a
class. It might have an abstract method called . The parent class dictates that every career must have a method, but the specific implementation of will differ depending on the career (e.g., doctor, coder).java
An abstract class serves as a template. It can contain both abstract methods (methods without implementation) and concrete methods (methods with implementation). The key characteristic of an abstract class is that it cannot be instantiated directly.
Important: If a class contains one or more abstract methods, the class itself must be declared abstract.
java
In this example,
is an abstract method. Any class that extends must provide an implementation for . If it doesn't, the subclass must also be declared abstract.To use an abstract class, you must create a concrete subclass that provides implementations for all of the abstract methods.
java
Here,
and are concrete subclasses of . They both provide implementations for the method. This is known as overriding the abstract method.This example demonstrates runtime polymorphism. The actual method that gets called is determined at runtime based on the object's type.
java
Although you cannot create objects of an abstract class directly, abstract classes can have constructors. These constructors are called when a subclass is instantiated, using the
keyword.Abstract classes can contain static methods. Static methods are associated with the class itself, not with any particular instance of the class. Therefore, they can be called directly using the class name.
java
Abstract classes can also contain normal (non-abstract) methods. These methods provide a default implementation that subclasses can either use as is or override.
The
keyword prevents a class from being inherited. Therefore, you cannot have a , as it would be contradictory.An interface is a completely abstract "class" that is used to group related method declarations without providing an implementation. It's a contract that specifies what a class must do, but not how it should do it.
Note: All methods in an interface are implicitly
and .
java
To use an interface, a class implements the interface using the
keyword. The class must provide implementations for all of the methods declared in the interface.java
Unlike classes, a class can implement multiple interfaces. This allows a class to inherit multiple contracts.
java
Interfaces can also extend other interfaces. This allows you to create a hierarchy of interfaces.
java
Starting with Java 8, interfaces can have default methods. Default methods provide a default implementation for a method in the interface. This allows you to add new methods to an interface without breaking existing implementations.
java
Interfaces can also have static methods, similar to abstract classes. These methods are associated with the interface itself and can be called directly using the interface name.
Interfaces can be nested inside classes or other interfaces. This allows you to group related interfaces together.
| Feature | Abstract Class | Interface | | -------------------- | ------------------------------------------------- | ----------------------------------------------------- | | Abstraction Level | Partial abstraction (can have concrete methods) | Full abstraction (all methods are abstract) | | Multiple Inheritance | Not supported | Supported (a class can implement multiple interfaces) | | Implementation | Uses
keyword | Uses keyword | | Instance Variables | Can have instance variables | Cannot have instance variables | | Method Access | Can have , , methods | All methods are implicitly |Consider a car factory that produces cars with different engines (petrol, diesel, electric) and media players. Using interfaces, we can define contracts for engines and media players, and then create concrete classes for each type of engine and media player. This allows us to easily create different car configurations without tightly coupling the engine and media player implementations.
The Java Collections Framework provides a set of interfaces and classes that help in storing and manipulating groups of objects. It's a fundamental part of Java development, essential for organizing data efficiently.
The Collections Framework is built around several core interfaces. Understanding these interfaces is crucial for effectively using the framework.
The
interface is the root interface in the Collections Framework. It represents a group of objects, known as elements. Common operations include adding, removing, and checking for the presence of elements.The
interface extends the interface and represents an ordered collection of elements. Elements can be accessed by their index, and duplicate elements are allowed. Key implementations of the interface include and .The
interface extends the interface but does not allow duplicate elements. It models the mathematical set abstraction. Implementations include and .The
interface represents a collection of key-value pairs. Each key is associated with a value, and keys must be unique within the map. Implementations include and .java
Note:
is a legacy class and is generally preferred in single-threaded environments due to its better performance.
java
The primary difference between
and is thread safety. is synchronized, making it suitable for multi-threaded environments, while is not synchronized and offers better performance in single-threaded scenarios.Enums (enumerations) are a special type in Java that represents a group of named constants. They are used to define a set of possible values for a variable.
Here's a simple example of an enum representing the days of the week:
java
Enums can be used like any other data type. You can declare variables of an enum type and assign them one of the enum's constants.
java
Enums can have methods and fields, just like classes. This allows you to add behavior and state to your enums.
java
Internally, enums are implemented as classes that extend
. Each enum constant is an instance of the enum class. Enums are implicitly , so they cannot be subclassed.Note: Enums are very powerful and can significantly improve the readability and maintainability of your code by providing a clear and type-safe way to represent a fixed set of values.
Enums come with two useful methods:
and .java
The speaker begins by discussing the standard
in Java and then transitions into creating a custom to understand its internal mechanisms. The goal is to replicate some of the core functionalities of the , such as adding, removing, and resizing elements.The custom
starts with a fixed-size integer array. A variable is maintained to track the number of elements currently stored in the list. The initial capacity is set to 10.java
Before adding elements, it's essential to check if the array is full. If it is, the array needs to be resized. The
method checks if the current size equals the array's length.java
The
method doubles the array's size and copies the existing elements to the new array.Note: Resizing involves creating a new array with double the capacity, copying the elements from the old array to the new array, and then updating the
reference to point to the new array.
java
The
method first checks if the array is full. If it is, it calls the method. Then, it adds the new element to the end of the array and increments the size.java
The
method removes an element at a given index. It shifts the subsequent elements to fill the gap and decrements the size.java
The
method retrieves the element at a given index.java
The
method returns the current size of the list.java
The
method sets the value at a given index.java
The speaker transitions to Generics to allow the
to work with different data types instead of being restricted to integers.Generics provide type safety and allow you to write code that can work with different types without the need for casting. In Java, Generics are implemented using type parameters.
To make the
generic, you replace the specific type (e.g., ) with a type parameter (e.g., ).java
Note: When using generics, the internal array is of type
, and you need to cast the retrieved elements to the appropriate type when using the method.
The speaker touches on type erasure, which means that the type information is not available at runtime. The Java compiler uses type information to ensure type safety at compile time, but this information is erased during runtime.
The speaker discusses how to compare objects in Java using the
interface. This is essential for sorting and other operations that require comparing objects.To make a class comparable, you need to implement the
interface and provide an implementation for the method.java
Note: The
method should return a negative value if the current object is less than the other object, a positive value if it is greater, and zero if they are equal.
Once a class implements
, you can use to sort a list of objects of that class.java
The speaker briefly introduces lambda expressions as a way to write concise and functional code. Lambda expressions can be used to implement functional interfaces.
A functional interface is an interface with a single abstract method. Lambda expressions can be used to provide an implementation for this method.
java
The speaker covers exception handling in Java, including the
, , , , and keywords.Exceptions are events that disrupt the normal flow of a program. Java provides a mechanism to handle exceptions and prevent programs from crashing.
The
block contains the code that might throw an exception. The block contains the code that handles the exception. The block contains the code that is always executed, regardless of whether an exception is thrown or not.java
The
keyword is used to throw an exception. The keyword is used to declare that a method might throw an exception.java
You can create your own custom exceptions by extending the
class.java
The speaker discusses object cloning in Java, including shallow copy and deep copy.
To implement cloning, a class must implement the
interface and override the method.java
Note: To perform a deep copy, you need to create new instances of all mutable objects referenced by the original object.
The Java Collections Framework provides a set of interfaces and classes that help in storing and manipulating groups of objects. It's a fundamental part of Java development, essential for organizing data efficiently.
The Collections Framework is built around several core interfaces. Understanding these interfaces is crucial for effectively using the framework.
The
interface is the root interface in the Collections Framework. It represents a group of objects, known as elements. Common operations include adding, removing, and checking for the presence of elements.The
interface extends the interface and represents an ordered collection of elements. Elements can be accessed by their index, and duplicate elements are allowed. Key implementations of the interface include and .The
interface extends the interface but does not allow duplicate elements. It models the mathematical set abstraction. Implementations include and .The
interface represents a collection of key-value pairs. Each key is associated with a value, and keys must be unique within the map. Implementations include and .java
Note:
is a legacy class and is generally preferred in single-threaded environments due to its better performance.
java
The primary difference between
and is thread safety. is synchronized, making it suitable for multi-threaded environments, while is not synchronized and offers better performance in single-threaded scenarios.Enums (enumerations) are a special type in Java that represents a group of named constants. They are used to define a set of possible values for a variable.
Here's a simple example of an enum representing the days of the week:
java
Enums can be used like any other data type. You can declare variables of an enum type and assign them one of the enum's constants.
java
Enums can have methods and fields, just like classes. This allows you to add behavior and state to your enums.
java
Internally, enums are implemented as classes that extend
. Each enum constant is an instance of the enum class. Enums are implicitly , so they cannot be subclassed.Note: Enums are very powerful and can significantly improve the readability and maintainability of your code by providing a clear and type-safe way to represent a fixed set of values.
Enums come with two useful methods:
and .java
This comprehensive guide has covered all the fundamental and advanced concepts of Object-Oriented Programming in Java. From basic classes and objects to complex topics like generics, exception handling, and object cloning, you now have a solid foundation to build robust, maintainable, and scalable Java applications.
Remember, the best way to master these concepts is through practice. Try implementing these examples, experiment with variations, and build your own projects to reinforce your understanding.
Happy coding! 🚀