Enums, Exceptions, and Robust Error Handling
Enums and Domain States
You are viewing a free preview lesson.
Lesson Overview
Real applications-এ অনেক values একটি fixed set-এর মধ্যে সীমাবদ্ধ থাকে।
Examples:
Course status
Enrollment status
Payment status
Difficulty level
User role
Content type
Publication visibility
একটি course-এর status arbitrary text হওয়া উচিত নয়।
Valid values হতে পারে:
DRAFT
REVIEW
PUBLISHED
ARCHIVED
Weak design:
private String status;
এতে invalid values ঢুকতে পারে:
published
Publish
PUBLISHD
active
anything
Java-তে fixed, named, type-safe values model করার জন্য ব্যবহার করা হয়:
enum
এই lesson-এ আমরা শিখব:
enumকী- String constants-এর সমস্যা
- Enum declare এবং use করা
- Enum comparison
values()এবংvalueOf()switchwith enum- Fields, constructors, এবং methods inside enum
- Domain state transitions
- External input safely parse করা
- Enum নাম persistence/API-তে ব্যবহারের trade-off
- কেন
ordinal()persist করা উচিত নয় - Enum কখন ব্যবহার করা উচিত এবং কখন নয়
Learning Objectives
এই lesson শেষে আপনি পারবেন:
- Fixed domain valuesকে
enumদিয়ে model করতে - Invalid string state prevent করতে
- Enum values compare করতে
- Enum-এর ওপর
switchলিখতে - Enum-এর মধ্যে fields এবং methods রাখতে
- Valid state transitions enforce করতে
- Unsafe
valueOf()usage identify করতে - External text থেকে enum safely parse করতে
name(),toString(), এবংordinal()distinguish করতে
The Problem with Strings
Suppose a course stores status as String:
public final class Course {
private String status;
public Course(
String status
) {
this.status = status;
}
}
Caller can create:
new Course(
"PUBLISHED"
);
But also:
new Course(
"publish"
);
new Course(
"PUBLISED"
);
new Course(
""
);
Compiler cannot understand which strings are valid।
String Comparison Is Fragile
if (
course.getStatus()
.equals(
"PUBLISHED"
)
) {
}
Potential problems:
- Typo
- Case mismatch
- Whitespace
- Repeated literal values
- Refactoring difficulty
- No compile-time validation
- Unsupported status accepted
String Constants Improve Only Part of the Problem
Possible improvement:
public final class CourseStatuses {
public static final String DRAFT =
"DRAFT";
public static final String PUBLISHED =
"PUBLISHED";
private CourseStatuses() {
}
}
Usage:
course.setStatus(
CourseStatuses.PUBLISHED
);
But method still accepts any String:
course.setStatus(
"BROKEN"
);
Constants reduce repeated literals।
They do not create a truly restricted type।
Define an Enum
public enum CourseStatus {
DRAFT,
REVIEW,
PUBLISHED,
ARCHIVED
}
Usage:
CourseStatus status =
CourseStatus.DRAFT;
The variable can hold only valid CourseStatus values।
Invalid:
CourseStatus status =
"DRAFT";
Compiler rejects it।
Invalid:
CourseStatus status =
CourseStatus.ACTIVE;
Compiler rejects it because ACTIVE is not declared।
Enum Is a Type
CourseStatus
একটি real Java type।
Method parameter:
public void changeStatus(
CourseStatus status
) {
}
Field:
private CourseStatus status;
Return type:
public CourseStatus getStatus() {
return status;
}
Compiler now understands the valid domain।
A Course Using Enum State
public final class Course {
private final long id;
private final String title;
private CourseStatus status;
public Course(
long id,
String title
) {
if (id <= 0) {
throw new IllegalArgumentException(
"Course ID must be positive."
);
}
if (
title == null
|| title.isBlank()
) {
throw new IllegalArgumentException(
"Course title is required."
);
}
this.id = id;
this.title = title.strip();
this.status =
CourseStatus.DRAFT;
}
public CourseStatus getStatus() {
return status;
}
}
Course always starts with:
CourseStatus.DRAFT
Caller arbitrary initial state inject করতে পারে না।
Comparing Enum Values
Enum values compare করতে == ব্যবহার করা safe এবং common।
if (
status
== CourseStatus.PUBLISHED
) {
}
Also works:
status.equals(
CourseStatus.PUBLISHED
);
But == preferred because enum constants are unique instances।
Null-Safe Enum Comparison
Suppose:
CourseStatus status =
null;
This is safe:
if (
status
== CourseStatus.PUBLISHED
) {
}
This can fail:
status.equals(
CourseStatus.PUBLISHED
);
because status is null।
However, well-designed domain objects should usually reject null enum state।
Enums Can Be Used in switch
public static String describeStatus(
CourseStatus status
) {
if (status == null) {
return "Unknown status";
}
return switch (status) {
case DRAFT ->
"The course is being prepared.";
case REVIEW ->
"The course is waiting for review.";
case PUBLISHED ->
"The course is available to learners.";
case ARCHIVED ->
"The course is no longer active.";
};
}
Because every enum constant is covered, no default is required।
Why Exhaustive switch Is Useful
Suppose enum later adds:
SUSPENDED
An exhaustive switch expression may stop compiling until the new value is handled।
This helps prevent forgotten behavior।
A broad default can hide missing cases:
default ->
"Other";
Use default only when fallback behavior is genuinely correct।
Traditional switch Statement
public static void printStatus(
CourseStatus status
) {
switch (status) {
case DRAFT:
System.out.println(
"Draft"
);
break;
case REVIEW:
System.out.println(
"In review"
);
break;
case PUBLISHED:
System.out.println(
"Published"
);
break;
case ARCHIVED:
System.out.println(
"Archived"
);
break;
}
}
Modern switch expression is often more concise।
values()
Every enum automatically provides:
values()
Example:
CourseStatus[] statuses =
CourseStatus.values();
Iterate:
for (
CourseStatus status
: CourseStatus.values()
) {
System.out.println(
status
);
}
Output:
DRAFT
REVIEW
PUBLISHED
ARCHIVED
valueOf()
Every enum also provides:
valueOf(String name)
Example:
CourseStatus status =
CourseStatus.valueOf(
"PUBLISHED"
);
Result:
CourseStatus.PUBLISHED
valueOf() Is Exact
This fails:
CourseStatus.valueOf(
"published"
);
Because enum constant name is:
PUBLISHED
It is case-sensitive।
This also fails:
CourseStatus.valueOf(
" PUBLISHED "
);
Whitespace is not ignored।
Failure:
IllegalArgumentException
Null input creates:
NullPointerException
Do Not Call valueOf() Directly on Untrusted Input
Weak:
CourseStatus status =
CourseStatus.valueOf(
requestStatus
);
User input may be:
published
unknown
empty
null
The method can throw runtime exceptions।
External input should be normalized and validated deliberately।
Safe Parsing Method
public enum CourseStatus {
DRAFT,
REVIEW,
PUBLISHED,
ARCHIVED;
public static CourseStatus fromText(
String value
) {
if (
value == null
|| value.isBlank()
) {
return null;
}
String normalizedValue =
value.strip()
.toUpperCase();
for (
CourseStatus status
: values()
) {
if (
status.name()
.equals(
normalizedValue
)
) {
return status;
}
}
return null;
}
}
Usage:
CourseStatus status =
CourseStatus.fromText(
" published "
);
Result:
CourseStatus.PUBLISHED
Unknown value returns:
null
Should Parsing Return Null?
Returning null is simple, but caller must check it।
Alternative designs:
Throw a custom exception
Return Optional<CourseStatus>
Return a Result<CourseStatus>
Return a default value
The correct choice depends on API requirements।
Do not silently map unknown input to a real status unless that fallback is valid।
Weak:
return DRAFT;
for every unknown input।
This may hide client bugs।
name()
CourseStatus.PUBLISHED.name()
returns:
PUBLISHED
name() is the exact constant identifier declared in code।
It cannot be overridden।
Useful for:
- Stable technical representation
- Logs
- Database string storage
- API values, if treated as a contract
toString()
By default:
CourseStatus.PUBLISHED.toString()
also returns:
PUBLISHED
But toString() can be overridden।
Therefore technical persistence should generally use:
name()
rather than a display-oriented toString()।
Custom Display Label
public enum CourseStatus {
DRAFT(
"Draft"
),
REVIEW(
"In Review"
),
PUBLISHED(
"Published"
),
ARCHIVED(
"Archived"
);
private final String displayName;
CourseStatus(
String displayName
) {
this.displayName =
displayName;
}
public String getDisplayName() {
return displayName;
}
}
Usage:
CourseStatus.PUBLISHED
.getDisplayName();
Result:
Published
Enum Constructors Are Not Public
Enum constructor:
CourseStatus(
String displayName
)
is used only by declared constants।
Caller cannot do:
new CourseStatus(
"Custom"
);
Enum instances are fixed by the declaration।
Enum with Multiple Fields
public enum Difficulty {
BEGINNER(
1,
"Beginner"
),
INTERMEDIATE(
2,
"Intermediate"
),
ADVANCED(
3,
"Advanced"
);
private final int level;
private final String displayName;
Difficulty(
int level,
String displayName
) {
this.level = level;
this.displayName =
displayName;
}
public int getLevel() {
return level;
}
public String getDisplayName() {
return displayName;
}
}
Usage:
Difficulty.ADVANCED.getLevel()
returns:
3
Enum Can Have Behavior
public enum EnrollmentStatus {
PENDING,
ACTIVE,
CANCELLED,
COMPLETED;
public boolean isActive() {
return this
== ACTIVE;
}
public boolean isTerminal() {
return this
== CANCELLED
|| this
== COMPLETED;
}
}
Usage:
if (
enrollment.getStatus()
.isTerminal()
) {
}
This is clearer than repeating:
status == CANCELLED
|| status == COMPLETED
throughout the application।
Behavior Belongs in the Enum When It Depends on the Value
Good enum behavior:
isTerminal()
canBeCancelled()
requiresPayment()
because these are directly determined by the enum constant।
Avoid putting unrelated service logic inside enum:
sendEmail()
saveToDatabase()
callPaymentGateway()
Enums should not become dependency-heavy service containers।
Domain State Transitions
Enums define valid states।
But enum alone does not define which transitions are allowed।
Possible course lifecycle:
DRAFT
↓
REVIEW
↓
PUBLISHED
↓
ARCHIVED
Not every transition should be valid।
Example invalid:
DRAFT → ARCHIVED
ARCHIVED → PUBLISHED
PUBLISHED → DRAFT
Domain class should enforce transition rules।
Weak Status Setter
public void setStatus(
CourseStatus status
) {
this.status = status;
}
Caller can perform any transition:
course.setStatus(
CourseStatus.ARCHIVED
);
even if course is still a new draft।
A generic setter exposes state without protecting lifecycle।
Use Domain Operations
public boolean submitForReview() {
if (
status
!= CourseStatus.DRAFT
) {
return false;
}
status =
CourseStatus.REVIEW;
return true;
}
public boolean publish() {
if (
status
!= CourseStatus.REVIEW
) {
return false;
}
status =
CourseStatus.PUBLISHED;
return true;
}
public boolean archive() {
if (
status
!= CourseStatus.PUBLISHED
) {
return false;
}
status =
CourseStatus.ARCHIVED;
return true;
}
Caller expresses intent:
course.submitForReview();
course.publish();
course.archive();
Not raw assignment।
A Complete Course Lifecycle
CourseStatus.java
package io.liveklass.course;
public enum CourseStatus {
DRAFT(
"Draft"
),
REVIEW(
"In Review"
),
PUBLISHED(
"Published"
),
ARCHIVED(
"Archived"
);
private final String displayName;
CourseStatus(
String displayName
) {
this.displayName =
displayName;
}
public String getDisplayName() {
return displayName;
}
public boolean isPubliclyVisible() {
return this
== PUBLISHED;
}
public boolean isEditable() {
return this
== DRAFT
|| this
== REVIEW;
}
public boolean isTerminal() {
return this
== ARCHIVED;
}
public static CourseStatus fromText(
String value
) {
if (
value == null
|| value.isBlank()
) {
return null;
}
String normalizedValue =
value.strip()
.toUpperCase();
for (
CourseStatus status
: values()
) {
if (
status.name()
.equals(
normalizedValue
)
) {
return status;
}
}
return null;
}
}
Course.java
package io.liveklass.course;
public final class Course {
private final long id;
private final String title;
private CourseStatus status;
public Course(
long id,
String title
) {
if (id <= 0) {
throw new IllegalArgumentException(
"Course ID must be positive."
);
}
if (
title == null
|| title.isBlank()
) {
throw new IllegalArgumentException(
"Course title is required."
);
}
this.id = id;
this.title = title.strip();
this.status =
CourseStatus.DRAFT;
}
public boolean submitForReview() {
if (
status
!= CourseStatus.DRAFT
) {
return false;
}
status =
CourseStatus.REVIEW;
return true;
}
public boolean returnToDraft() {
if (
status
!= CourseStatus.REVIEW
) {
return false;
}
status =
CourseStatus.DRAFT;
return true;
}
public boolean publish() {
if (
status
!= CourseStatus.REVIEW
) {
return false;
}
status =
CourseStatus.PUBLISHED;
return true;
}
public boolean archive() {
if (
status
!= CourseStatus.PUBLISHED
) {
return false;
}
status =
CourseStatus.ARCHIVED;
return true;
}
public long getId() {
return id;
}
public String getTitle() {
return title;
}
public CourseStatus getStatus() {
return status;
}
public boolean isEditable() {
return status.isEditable();
}
public boolean isPubliclyVisible() {
return status.isPubliclyVisible();
}
}
Main.java
package io.liveklass;
import io.liveklass.course.Course;
public class Main {
public static void main(
String[] args
) {
Course course =
new Course(
1L,
"Java and OOP Foundation"
);
printState(
course
);
System.out.println(
"Publish directly: "
+ course.publish()
);
System.out.println(
"Submit for review: "
+ course.submitForReview()
);
printState(
course
);
System.out.println(
"Publish: "
+ course.publish()
);
printState(
course
);
System.out.println(
"Archive: "
+ course.archive()
);
printState(
course
);
}
private static void printState(
Course course
) {
System.out.println();
System.out.println(
"Status: "
+ course.getStatus()
.getDisplayName()
);
System.out.println(
"Editable: "
+ course.isEditable()
);
System.out.println(
"Publicly visible: "
+ course.isPubliclyVisible()
);
}
}
Possible Output
Status: Draft
Editable: true
Publicly visible: false
Publish directly: false
Submit for review: true
Status: In Review
Editable: true
Publicly visible: false
Publish: true
Status: Published
Editable: false
Publicly visible: true
Archive: true
Status: Archived
Editable: false
Publicly visible: false
Why Keep Transition Logic in Course?
The enum knows properties of each state:
Editable?
Publicly visible?
Terminal?
The Course controls transitions:
Can this course move from current state to another?
This separation keeps domain ownership clear।
Alternative: Transition Logic Inside Enum
Possible:
public enum CourseStatus {
DRAFT,
REVIEW,
PUBLISHED,
ARCHIVED;
public boolean canTransitionTo(
CourseStatus target
) {
if (target == null) {
return false;
}
return switch (this) {
case DRAFT ->
target == REVIEW;
case REVIEW ->
target == DRAFT
|| target == PUBLISHED;
case PUBLISHED ->
target == ARCHIVED;
case ARCHIVED ->
false;
};
}
}
Then course:
public boolean changeStatus(
CourseStatus target
) {
if (
!status.canTransitionTo(
target
)
) {
return false;
}
status = target;
return true;
}
This centralizes transition table।
Generic Transition Method Trade-Off
A generic method:
changeStatus(
target
)
is flexible, but caller intent is less expressive।
Compare:
course.changeStatus(
CourseStatus.PUBLISHED
);
with:
course.publish();
publish() communicates business action better এবং additional publication validation add করা সহজ।
Use generic transition method when:
- Transition workflow truly generic
- Caller chooses target state deliberately
- Additional action-specific validation is minimal
Use named methods when domain actions matter।
Enum Constant-Specific Behavior
An enum constant can provide different behavior।
public enum DiscountType {
NONE {
@Override
public long apply(
long price
) {
return price;
}
},
TEN_PERCENT {
@Override
public long apply(
long price
) {
return price
- price
* 10
/ 100;
}
},
TWENTY_PERCENT {
@Override
public long apply(
long price
) {
return price
- price
* 20
/ 100;
}
};
public abstract long apply(
long price
);
}
Usage:
long finalPrice =
DiscountType.TEN_PERCENT
.apply(
100_000L
);
Result:
90000
This uses polymorphic enum behavior।
When Constant-Specific Behavior Is Appropriate
Good when:
- Fixed strategies are truly limited
- Each enum value has a small behavior variation
- No external dependencies required
- New values should implement the behavior
Avoid when:
- Strategies are dynamically configured
- Many dependencies are needed
- New strategies should be added without editing enum
- Business rules are large and independently evolving
In those cases, interface-based strategy classes may be stronger।
Enum and Collections
Enums can be used in regular collections:
Set<UserRole> roles;
Map<CourseStatus, Integer> counts;
List<CourseStatus> history;
Java also provides specialized collections:
EnumSet
EnumMap
These are optimized for enum keys or values।
Example:
EnumSet<CourseStatus> editableStatuses =
EnumSet.of(
CourseStatus.DRAFT,
CourseStatus.REVIEW
);
Detailed EnumSet and EnumMap usage can be learned later।
ordinal()
Every enum constant has a position:
CourseStatus.DRAFT.ordinal()
Possible result:
0
CourseStatus.REVIEW.ordinal()
Possible result:
1
But ordinal is declaration position, not a stable domain ID।
Never Persist ordinal() as a Stable Status
Suppose initially:
DRAFT,
REVIEW,
PUBLISHED
Stored values:
DRAFT → 0
REVIEW → 1
PUBLISHED → 2
Later enum changes:
DRAFT,
SCHEDULED,
REVIEW,
PUBLISHED
Now:
REVIEW → 2
PUBLISHED → 3
Old stored 2 may now be interpreted as REVIEW instead of PUBLISHED।
This silently corrupts meaning।
Prefer stable strings:
status.name()
or an explicit stable code field।
Explicit Stable Code
public enum PaymentStatus {
PENDING(
"pending"
),
PAID(
"paid"
),
FAILED(
"failed"
);
private final String code;
PaymentStatus(
String code
) {
this.code = code;
}
public String getCode() {
return code;
}
}
The code can remain stable even if enum declaration order changes।
API Contract Warning
If API returns:
PUBLISHED
from:
status.name()
then renaming enum constant:
PUBLISHED → LIVE
is a breaking API change।
Java refactoring tool may update internal code, but external clients still expect old value।
Treat serialized enum names as public contracts।
Database Storage Warning
Storing enum as text is generally safer than ordinal, but renaming still requires migration।
Example stored value:
PUBLISHED
Code changed to:
LIVE
Existing database rows no longer parse automatically।
Use deliberate migrations and stable names।
Enum vs Boolean
Weak:
private boolean published;
This supports only two states:
true
false
If domain later needs:
DRAFT
REVIEW
PUBLISHED
ARCHIVED
boolean becomes insufficient।
Use boolean when state is genuinely binary:
Email verified?
Feature enabled?
Terms accepted?
Use enum when values are multiple named alternatives।
Avoid Multiple Conflicting Booleans
Weak:
private boolean draft;
private boolean published;
private boolean archived;
Invalid combinations become possible:
draft = true
published = true
archived = true
One enum guarantees one current state:
private CourseStatus status;
Enum vs Class
Use enum when:
- All valid instances are known and fixed
- Values are named constants
- New instances should not be created dynamically
- Each value belongs to one closed type
Examples:
CourseStatus
Difficulty
UserRole
PaymentStatus
ContentType
Use a class when:
- Values are created dynamically
- Each instance has unique data
- Number of values is unbounded
- Runtime configuration determines instances
Examples:
Course
Learner
Coupon
Country
Currency amount
Do Not Use Enum for Frequently Changing Database Data
Suppose administrators can add new course categories without deployment।
Weak:
enum CourseCategory {
PROGRAMMING,
DESIGN,
BUSINESS
}
Every new category requires code change and redeployment।
A database entity may be better।
Enums are strongest for code-level closed sets।
Enum Naming Conventions
Enum type:
CourseStatus
EnrollmentStatus
Difficulty
Constants:
DRAFT
IN_REVIEW
PUBLISHED
Use uppercase snake case for constants।
Avoid vague values:
FIRST
SECOND
OTHER
unless their meaning is genuinely clear।
Null Enum State
Weak:
private CourseStatus status;
without initialization।
State may remain null।
Better:
this.status =
CourseStatus.DRAFT;
or validate constructor input:
if (status == null) {
throw new IllegalArgumentException(
"Course status is required."
);
}
A domain state should usually always be valid।
Common Mistakes
Using Strings for a Closed Set
Compiler cannot restrict valid values।
Using Public Status Setter
Allows invalid lifecycle transitions।
Calling valueOf() on Untrusted Input
Unknown text throws runtime exception।
Comparing Enum Names as Strings
status.name()
.equals(
"PUBLISHED"
)
Usually less safe than:
status
== CourseStatus.PUBLISHED
Persisting ordinal()
Declaration reordering changes meaning।
Renaming Serialized Enum Constants Casually
Can break APIs and stored data।
Using Multiple Booleans for One State Machine
Creates contradictory combinations।
Putting Service Dependencies Inside Enum
Makes enum behavior heavy and difficult to test।
Using Enum for Runtime-Configurable Data
Requires deployment for every new value।
Returning a Default Status for Unknown Input
May hide invalid external data।
Practice Exercises
Exercise 1: Create EnrollmentStatus
Values:
PENDING
ACTIVE
CANCELLED
COMPLETED
Add methods:
isActive()
isTerminal()
Exercise 2: Replace Strings
Refactor:
private String difficulty;
Valid values:
BEGINNER
INTERMEDIATE
ADVANCED
Use an enum।
Exercise 3: Safe Parsing
Add:
static Difficulty fromText(
String value
)
Requirements:
- Ignore surrounding whitespace
- Ignore case
- Return null for unknown values
Exercise 4: Course Transitions
Implement:
DRAFT → REVIEW
REVIEW → DRAFT
REVIEW → PUBLISHED
PUBLISHED → ARCHIVED
Reject every other transition।
Exercise 5: Switch Expression
Create:
static String getLearnerMessage(
EnrollmentStatus status
)
Return a different message for each status।
Exercise 6: Stable External Code
Create:
PaymentStatus
with explicit codes:
pending
paid
failed
refunded
Do not use ordinal()।
Exercise 7: Choose Enum or Class
Choose which should be an enum:
- Course difficulty
- Learner
- Payment status
- Coupon
- User role
- Country managed by administrators
- Content type
- Course created by instructors
Explain each choice।
Predict the Result
Question 1
CourseStatus status =
CourseStatus.PUBLISHED;
System.out.println(
status
== CourseStatus.PUBLISHED
);
Answer
true
Question 2
CourseStatus status =
CourseStatus.valueOf(
"published"
);
Answer
Runtime-এ:
IllegalArgumentException
valueOf() case-sensitive।
Question 3
System.out.println(
CourseStatus.PUBLISHED.name()
);
Answer
PUBLISHED
Question 4
for (
CourseStatus status
: CourseStatus.values()
) {
System.out.println(
status
);
}
What does it print?
Answer
Every declared enum constant in declaration order।
Question 5
CourseStatus status =
null;
System.out.println(
status
== CourseStatus.DRAFT
);
Answer
false
== comparison is null-safe।
Question 6
Course course =
new Course(
1L,
"Java"
);
System.out.println(
course.publish()
);
Assume course can publish only from REVIEW।
Answer
false
Initial state is DRAFT।
Knowledge Check
Question 1
What problem does an enum solve?
Question 2
Why is String weak for fixed domain states?
Question 3
Can callers create new enum instances?
Question 4
How should enum constants usually be compared?
Question 5
What does values() return?
Question 6
What does valueOf() require?
Question 7
Why is direct valueOf() unsafe for external input?
Question 8
What is the difference between name() and custom display text?
Question 9
Why should ordinal() not be persisted?
Question 10
Why are named domain methods stronger than a generic status setter?
Question 11
When should behavior live inside an enum?
Question 12
When should enum not be used?
Question 13
Why is one enum better than multiple status booleans?
Question 14
Can enum constructors be called by application code?
Question 15
What must be considered before renaming a serialized enum constant?
Knowledge Check Answers
Answer 1
A fixed closed set of valid named valuesকে type-safeভাবে model করে।
Answer 2
Any arbitrary text accepted হয় এবং compiler valid values enforce করতে পারে না।
Answer 3
না।
Only declared enum constants exist।
Answer 4
Using ==।
Answer 5
An array containing every declared constant।
Answer 6
The exact case-sensitive constant name।
Answer 7
Unknown, blank, differently cased, or null input exception তৈরি করতে পারে।
Answer 8
name() exact technical constant identifier; display text is user-facing and can differ।
Answer 9
Declaration order change হলে stored numeric meaning change হয়ে যেতে পারে।
Answer 10
They express business intent and enforce valid transitions।
Answer 11
When behavior is directly determined by the fixed enum value and remains small।
Answer 12
When instances are dynamic, administrator-configurable, or unbounded।
Answer 13
An enum guarantees exactly one valid current state and avoids conflicting boolean combinations।
Answer 14
না।
Constructors are used only by enum constant declarations।
Answer 15
API clients, database values, messages, and other external contracts may depend on the old name।
Lesson Summary
এই lesson-এ আমরা শিখেছি:
enumfixed named valuesকে type-safeভাবে model করে- String state arbitrary invalid values allow করে
- String constants restricted type তৈরি করে না
- Enum একটি real Java type
- Enum constants unique instances
- Enum comparison-এর জন্য
==safe এবং common - Enum values
switch-এ use করা যায় - Exhaustive switch নতুন values handle করতে সাহায্য করে
values()all constants return করেvalueOf()exact case-sensitive name require করে- External input direct
valueOf()-এ দেওয়া unsafe - Safe parsing normalization এবং validation require করে
- Enum fields, constructors, এবং methods রাখতে পারে
- Display label technical constant name থেকে আলাদা হতে পারে
- Enum state-specific behavior রাখতে পারে
- Domain class valid state transitions enforce করতে পারে
- Generic setter invalid lifecycle changes allow করতে পারে
- Named methods business intent communicate করে
- Constant-specific enum behavior limited strategies model করতে পারে
- Enum values collections-এ ব্যবহার করা যায়
ordinal()stable domain identifier নয়- Serialized enum names external contracts হতে পারে
- Boolean only genuine binary state-এর জন্য appropriate
- Multiple status booleans contradictory state তৈরি করতে পারে
- Enum closed code-level sets-এর জন্য strongest
- Dynamic administrator-managed values সাধারণত enum হওয়া উচিত নয়
- Null enum state avoid বা validate করা উচিত
Next Lesson
পরবর্তী lesson:
Introduction to Exceptions and Failure Handling
আমরা শিখব:
- Normal flow vs exceptional flow
- What an exception is
- Exception hierarchy
- Checked and unchecked exceptions
throwthrowstry,catch, andfinally- Stack trace
- Avoiding swallowed exceptions
- When to return a result and when to throw
- Building clear failure contracts