Java OOPs
Java OOPs
/
/ Private
fields,
cannot
be
accessed
directly
outside enefits of Encapsulation:
B
the class
1. Data Protection & Security:
private
String name; Encapsulationhelpsinprotectingthedata.Bymakingthefields
private
int
age; private, we prevent external classes from directly modifying the
internal state of an object. Any modification can only happen via
/ Public getter for name
/ the setter method, which can contain validation logic. This
public
String
getName
() {
prevents invalid statesand promotes data integrity.
return
name; ○ For example, the setter for age in the above example
}
ensures that only valid ages (>= 18) can be set. This
prevents the object from entering an invalid state.
/ Public setter for name with validation
/ 2. Improved Maintainability:
public
void setName
(String name) {
Withencapsulation,theinternalstructureoftheclasscanchange
if
(name != null
&& !name.isEmpty()) { without affecting external code. For example, you coulddecideto
this
.name = name;
store the employee’s age as a Date object instead of an int, and
}
else
{ external code that uses the Employee class would not need to
throw
new
IllegalArgumentException(
"Name
cannot
hange because they’re interacting with the public getter and
c private
int
age;
setter methods, not the internal field.
3. Flexibility: ublic
p int
getAge
() {
Encapsulation allows you to change the implementation details return
age;
without affecting other parts of your program. For example, you }
mightlaterdecidetoaddloggingorcachingtothegettermethods,
and you can dothiswithoutchangingthecodethatcallsgetAge() ublic
p void
setAge
(
int
age) {
or getName().
this
.age = age;
4. Security:
}
Encapsulation enables the creation of read-only fields (by only
}
providing a getter method, and no setter) or write-only fields (by
only providing a setter method, and no getter). You can also After Change:
provide restricted access to certain fields to specific classes or import
java.util.Date;
packages usingprotectedordefaultaccess modifiers.
5. Ease of Debugging: public
class
Employee
{
Encapsulation helps withdebuggingbecauseyoucancontrolthe private
Date birthDate;
behaviorofaclassthroughitspublicmethods.Forexample,ifyou
detectanissuewithhowtheagefieldisbeingset,youcandebug ublic
p Date
getBirthDate
() {
and modify just the setter method without affecting other parts of return
birthDate;
the code. }
6. Loose Coupling:
Encapsulation promotes loose coupling between components. ublic
p void
setBirthDate
(Date birthDate) {
External classes don't need to know how an object works this
.birthDate = birthDate;
internally, they just interact with its public methods. This allows }
changes to the internal implementation without breaking external
code that relies on the public interface. / Calculate age from birth date (example)
/
public
int
getAge
() {
xample of Changing Internal Implementation WithoutBreaking
E // Logic to calculate age from birthDate
External Code: }
Let'ssaywechangetheEmployeeclasstostoretheemployee’sage }
as a Date object (to record the date of birth). Because of In this case, all external code remains unaffected because they are
encapsulation, any external class that interacts with Employee only only calling getAge() and setAge(), which are still available (just
uses the getter and setter methods. The code that uses the implemented differently).
Employee class doesn’t need to change. In Summary:
Before Change: ● Encapsulation helps protect data, promotes data integrity, and
public class Employee { allows for flexible and maintainable code.
● It hides the internal details of a class and exposes only the
necessaryfunctionalityviacontrolledaccessmethods(gettersand
setters). he super Keyword: The super keyword is usedtorefertotheparent
T
● This is key for separation of concerns, maintainability, and class from the child class. Here’s how you can use it:
securityin large-scale systems. ● Access parent class methods (if they’re overridden in the child
class):
super
.methodName();
C
● all the parent class constructor: super();
.
3 DescribeInheritanceinJava.Whatarethedifferenttypes
● Access parent class variables (if there's a conflict between
of inheritance supported, and how is the super keyword used?
parent and child):
What are its limitations?
Ans: In Java, inheritance allows a class (child class) to inherit super
.variableName;
propertiesandbehaviors(methods)fromanotherclass(parentclass).
It's mainly used to promote code reusability and to represent an
"is-a" relationship. For example, if you have a Dog class and an Limitations of Inheritance:
Animal class, Dog is a type of Animal. 1. Tight Coupling: Child classes depend heavily onparentclasses.
Iftheparentclasschanges,allchildclassesmayneedtochange,
Types of Inheritance in Java: which can break things or require a lot of refactoring.
1. Single Inheritance: A class can inherit from only one parent class. 2. Harder to Refactor: Since inheritance tightly couples classes,
changing the parent class can lead to a lotofrippleeffectsinthe
lass
c Animal
{ } child classes.
class
Dog
extends
Animal
{ } 3. NoMultipleInheritancewithClasses:Javadoesn'tallowaclass
2. Multilevel Inheritance: A class can inherit from another class, toinheritfrommorethanoneclass,whichavoidscomplexity(e.g.,
which in turn inherits from another class. the diamond problem). But you can still achieve multiple
inheritance viainterfaces.
lass
c Animal{ }
class
Dog
extendsAnimal
{ }
.
4 Explain Abstraction in Java. What are the key differences
class
Puppy
extendsDog
{ }
betweenAbstractClassesandInterfaces?Whenwouldyouchoose
3. Hierarchical Inheritance: Multiple classes can inherit from a one over the other?
single parent class.
ns: Abstraction in Java is about simplifying complexity by
A
lass
c Animal
{ } exposingonlyrelevantdetailsandhidingtheinternallogic.It'sone
class
Dog
extends
Animal
{ } of the core OOP principles and helps keep code modular and clean.
class
Cat
extends
Animal
{ }
ava supports abstraction through both abstract classes and
J
ote:Javadoesnotsupportmultipleinheritancewithclassestoavoid
N interfaces. While both letyoudefinemethodswithoutimplementations,
issues like the diamond problem (ambiguity when inheriting from there are key differences in how and when they’re used.
multiple classes). But you can achieve similar behavior usinginterfaces.
● A bstract classes can have both abstract and concrete methods, ohesion is about how focused a class is on a single responsibility. If
C
instance variables, and constructors. They're typically used when UserService is doing everything — from creating users, to validating
multiple related classes share common functionality. Since Java passwords, to sending emails and generating reports — it has low
allowsonlysingleinheritanceforclasses,abstractclassesarebest cohesion. It becomes harder to manage, test, and extend.
when there's a clear inheritance hierarchy
● Interfaces, especially after Java 8, are more about defining a In a better design, we would split this into:
contract. Earlier they only allowed abstract methods and ● UserService – handles user-related business logic
constants, but nowtheysupportdefault,static,andevenprivate ● AuthService – handles authentication
methods.Interfacesarebettersuitedwhenunrelatedclassesneed ● EmailService – handles email notifications
to follow the same behavior — like Comparable, Serializable, or ● AuditService – handles audit logging
domain-specific contracts like Auditable. his creates high cohesion, because each class now has a clearand
T
ne big difference is inheritance — a class can extend only one
O focused responsibility.
abstract class but can implement multiple interfaces, making In summary: Loose coupling allows components to evolve
interfaces more flexible when designing loosely coupled systems. independently, and high cohesion ensures each class is focused and
Inshort,useanabstractclasswhenyouhavesharedstateorlogic, easiertomaintain.Botharecriticalinkeepingevenasimplesystemlike
and use interfaces when you're defining capabilities that can cut user management clean, testable, and scalable.
across unrelated classes — especially when you need multiple
inheritance of behavior onc Bad Example in UMS Good Example in UMS
C
ept
II. Advanced OOP Concepts & Design Principles
oupl U
C serServicecreatesits U
serService depends on
ing own DB connection UserRepository interface
.WhatareCouplingandCohesioninthecontextofOOP?Whyare
6
ohe U
C serService handles R esponsibilities split across
they important
sion auth, email, and audit UserService, AuthService,
Ans: Coupling isabouthowmuchoneclassdependsonanother.Let’s
EmailService
say the UserService class directly creates and manages a
DatabaseConnection object. That’s an example of tight coupling,
because UserService is now directly dependent on the database
implementation. If we later decide to switch from MySQL to MongoDB,
we’d have to modify UserService. . Differentiate between Association, Aggregation, and
7
CompositioninJavawithexamples.Keywords:Ans:InAssociation,
Instead, if UserService dependsonaUserRepositoryinterfaceandthat twoclassesarejustrelated—likeaUserandaRole.They’reawareof
is injected via a framework like Spring, the service becomes loosely each other, but neither owns the other. It’s the most general form, and
coupled. The underlying data source can change without affecting the both can live independently.
service logic — making the code more flexible and testable.
In Aggregation, there's a whole-part relationship, but with shared oint to a different object, but theobjectitselfcanstillbemodifiedifit’s
p
wnership.Forexample,aDepartmenthasStudents,butthosestudents
o mutable.
stillexistifthedepartmentisdeleted.So,aggregationaddsstructurebut Finalmethod:Cannotbeoverriddenbysubclasses.Thisisusefulwhen
still keeps the objects loosely coupled. youwanttolockdowncertainbehaviortopreventaccidentalchangesin
child classes.
omposition is tighter — it’s an exclusive ownership. A User might
C Final class: Cannot be subclassed. This is often done to prevent
haveaUserProfile,andthatprofiledoesn’tmakesensewithouttheuser. inheritance altogether, ensuring the class’s design remains intact.
If the user is deleted, so is the profile. That’s a strong lifecycle Examples include String and wrapper classes like Integer.
dependency.
ublic
p void
setNext
(Logger nextLogger) {
this
.next = nextLogger;
🔄 Extensibility & Maintenance
}
● Adding a new destination?Just implement Logger (Strategy).
● Changing log creation logic? Update the LoggerFactory
(Factory).
● F
iltering log levels? Adjust the chain handlers (Chain of · Modularity: OOP encourages breaking down the system into
Responsibility). smaller, manageable pieces—each responsible for a specific part of
the functionality—which is crucial in large systems.
· Collaboration:Well-definedinterfacesallowdifferentteamsto
✅ Summary of Patterns Used workondifferentmodulessimultaneouslywithoutinterfering,enabling
parallel development and better coordination.
Pattern Purpose · Testability:Whenyourclassesarecohesiveandencapsulated,
it’s easier to write focused unit tests for each component, improving
Strategy ifferent logging behaviors
D reliability.
via polymorphism · Reduced Complexity: Abstraction helps hide complexdetails
Factory reation logic abstracted
C behind simple interfaces, so developers don’t need to understand
away from clients every part of the system to work effectively.
· Extensibility:Polymorphismandinheritanceletyourapplication
hain
C of F
iltering by log level or evolve smoothly as requirements change without major rewrites.
Responsibility conditional handling
Scalability pen/Closed
O dd
A features without
Principle (OCP) breaking existing code
7. How do OOP principles help in building large-scale,
1
enterprise-level applications? Reusability Inheritance, euse
R code across
· Maintainability: Encapsulation and modularity mean each Interfaces modules/projects
componenthidesitsinternaldetailsandexposesaclearinterface.So
whenyouneedtofixbugsoraddfeatures,youcandosoinisolation Modularity Classes, Objects reak
B complexity into
without breaking the entire system. manageable units
· Scalability:ThankstotheOpen/ClosedPrinciple,youcanadd
Collaboration Interfaces, arallel work with clear
P
new features by extending existing classes or implementing
Abstraction contracts
interfaces without modifying stable code. This makes the system
scalable and reduces regression risks Testability ohesion,
C Isolate components for unit
· Reusability:Inheritanceandinterfacespromotewritingreusable Encapsulation tests
components that can be shared across modules or even different
projects, cutting down duplication and speeding up development. educed
R Abstraction ide complexity
H behind
Complexity simple interfaces
difficult to understand or change. They also can lead to
Extensibility olymorphism,
P volvesystemwithoutmajor
E nexpected side effects when behavior is inherited unexpectedly.
u
Inheritance rewrites ● How I avoid it: I prefer composition over inheritance where
possible. I keep inheritance hierarchies shallow and use
interfaces to define behavior without forcing implementation
inheritance. This makes the design more flexible and easier to
8. What are some common OOP pitfalls you've encountered, and
1 maintain.
how do you avoid them? 5. Design by Copy-Paste
Copying code instead of abstractingreusablelogicleadstocode
Ans: Common OOP duplication,whichmakesbugshardertofixandfeaturesharderto
1. God Object / Monolithic Class extend.
This is when a single class tries to do too much—handling multiple ● HowIavoidit:Iconstantlylookforcommonpatternsandrefactor
responsibilities, managing too many data points, or controlling different duplicated code into shared methodsorutilityclasses.When
parts of the system. It becomes a maintenance nightmare and a appropriate,Iuseinheritanceorcompositiontoreuselogicwithout
bottleneck. copying.
● How I avoid it: I rigorously apply the Single Responsibility 6. Over-engineering and Premature Optimization
Principle (SRP). I breakdownlargeclassesintosmaller,focused Sometimes, developers introduce complex patterns or
components. Often, composition helps to delegateresponsibilities optimizationsbeforethey’rereallyneeded,makingthecodeharder
cleanly instead of stuffing everything into one class. to read and maintain.
2. Tight Coupling ● How I avoid it: I start with a simple design that meets current
When classes are tightly coupled, changes in one ripplethrough requirements. I embrace refactoring as the system evolves and
many others, making the system fragile and hard to test. only apply design patterns when their benefits outweigh the
● How I avoid it: I program to interfaces or abstractions, not complexitytheyadd.Ialsoprioritizewritingclean,readablecode
concrete implementations. Using dependency injection helps over trying to optimize too early.
decoupledependenciesandmakescomponentseasiertoswapor
mockduringtesting.Ialsominimizedirectreferencesbyrelyingon
well-defined contracts.
3. Low Cohesion
Sometimes a class ends up with unrelated methods and data,
which means it’s doing too many unrelated things, violating SRP.
This reduces readability and reusability.
● How I avoid it: I ensure that every class has a single, clear
purpose. If I find unrelated responsibilities creeping in, I refactor
by splitting the class into smaller, more cohesive units.
4. Over-inheritance / Deep Inheritance Hierarchies
Deep or complex inheritance trees make the design rigid and