Fundamentals 15 min read

Defensive Programming: Concepts, Core Principles, and Practical Java Examples

This article explains defensive programming as a proactive coding paradigm that anticipates and mitigates errors through input validation, error handling, assertions, and continuous testing, and demonstrates its application with detailed Java examples covering pagination, loop safety, exception management, and boundary checks.

JD Tech
JD Tech
JD Tech
Defensive Programming: Concepts, Core Principles, and Practical Java Examples

Defensive programming is a coding paradigm that anticipates and prevents potential errors and exceptions, thereby improving software robustness and stability.

The article begins with an introduction that stresses the challenges of complex runtime environments, unpredictable user input, and possible programming mistakes, and defines defensive programming as a disciplined approach to mitigate these risks.

It then outlines the core principles: assume inputs may be wrong, minimize the impact scope of errors, use assertions for internal checks, write clear and maintainable code, and adopt continuous testing to catch issues early.

Several practical cases are presented. First, input validation and cleaning are discussed, with examples of type checking, length/range verification, and sanitizing data. Next, a pagination‑parameter example shows how to validate pageSize and pageNumber , handle invalid values, compute total pages, and return a PaginationInfo object. The full Java code is:

public class PaginationService {
private static final int MAX_PAGE_SIZE = 100;
/**
* Get pagination info with parameter validation
* @param totalRecords total record count
* @param pageSize records per page
* @param pageNumber current page number
* @return PaginationInfo containing total pages, current page, etc.
*/
public PaginationInfo getPaginationInfo(int totalRecords, int pageSize, int pageNumber) {
if (pageSize <= 0 || pageSize > MAX_PAGE_SIZE) {
throw new IllegalArgumentException("pageSize must be a positive integer not exceeding " + MAX_PAGE_SIZE);
}
if (pageNumber <= 0) {
pageNumber = 1; // default to first page
}
int totalPages = (totalRecords + pageSize - 1) / pageSize;
if (pageNumber > totalPages) {
pageNumber = totalPages;
}
int startIndex = (pageNumber - 1) * pageSize;
return new PaginationInfo(totalPages, pageNumber, startIndex);
}
// PaginationInfo is a simple DTO to hold pagination data
...
}

The article also covers preventing infinite loops by validating loop parameters and ensuring termination conditions are reachable, illustrated with a Java method that generates time‑interval lists.

public List
generateList(int startMinutes, int endMinutes, int interval, int duration) {
if (interval <= 0) {
throw new IllegalArgumentException("Invalid parameters: interval must be positive integers.");
}
List
result = new ArrayList<>();
int nextStartTime = startMinutes;
while (nextStartTime <= endMinutes) {
int currentStart = nextStartTime;
int currentEnd = currentStart + duration;
result.add(currentStart + "-" + currentEnd);
nextStartTime += interval;
}
return result;
}

Exception handling is demonstrated with a file‑reading utility that catches specific exceptions, logs errors, and returns null on failure.

public static String readFile(String filePath) {
try {
byte[] encoded = Files.readAllBytes(Paths.get(filePath));
return new String(encoded);
} catch (FileNotFoundException e) {
log.info("File not found: " + filePath);
return null;
} catch (Exception e) {
log.info("Error reading file: " + e.getMessage());
return null;
}
}

Boundary‑condition checks are shown with array access validation, ensuring indices are within range before use.

public class ArrayAccess {
public static void main(String[] args) {
int[] numbers = {1,2,3,4,5};
int index = getIndexFromUser();
if (index >= 0 && index < numbers.length) {
log.info(numbers[index]);
} else {
log.info("Index out of bounds");
}
}
private static int getIndexFromUser() {
return 2; // example value
}
}

Using assertions for internal checks is discussed, with a Java example that validates birth year before calculating age.

public static int calculateAge(int birthYear) {
if (birthYear <= 0 || birthYear > Year.now().getValue()) {
throw new IllegalArgumentException("Birth year must be a positive integer less than the current year");
}
return Year.now().getValue() - birthYear;
}

The article concludes that defensive programming should be applied judiciously: over‑defense can bloat code, so developers need to prioritize critical entry points and adjust the level of protection based on context.

JavaError Handlinginput validationdefensive programmingsoftware robustness
JD Tech
Written by

JD Tech

Official JD technology sharing platform. All the cutting‑edge JD tech, innovative insights, and open‑source solutions you’re looking for, all in one place.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.