Fundamentals 11 min read

How Generics + Functional Programming Make Java Code Look More Sophisticated

The article demonstrates how combining Java generics with functional programming—using lambda‑based callbacks and generic pagination utilities—can transform repetitive data‑access code into a concise, reusable structure, while also discussing the benefits, trade‑offs, and potential debugging challenges of this approach.

Programmer XiaoFu
Programmer XiaoFu
Programmer XiaoFu
How Generics + Functional Programming Make Java Code Look More Sophisticated

Introduction

Today we walk step by step to experience the elegance of generics and functional programming in Java.

Case Study: Structured Pagination Code

Two methods— queryBook and queryPencil —show a typical pagination pattern: create a PageData object, query the total count, return early if zero, otherwise fetch the detail list and populate the result.

public PageData queryBook(BookRequest request) {
    // 1. create pagination object
    PageData pageData = new PageData();

    // 2. calculate record count
    int count = bookMapper.queryBookCount(request);

    // 3. if zero, return empty page
    if (count == 0) {
        pageData.setCount(0);
        return pageData;
    }

    // 4. otherwise fetch details
    List<BookDO> bookList = bookMapper.queryBookList(request);

    // 5. set count and result
    pageData.setCount(count);
    pageData.setResult(bookList);
    return pageData;
}
public PageData queryPencil(PencilRequest request) {
    PageData pageData = new PageData();
    int count = pencilMapper.queryPencilCount(request);
    if (count == 0) {
        pageData.setCount(0);
        return pageData;
    }
    List<PencilDO> pencilList = pencilMapper.queryPencilList(request);
    pageData.setCount(count);
    pageData.setResult(pencilList);
    return pageData;
}

The two snippets are structurally and semantically identical: both query a count first and then, if the count is non‑zero, retrieve the list.

IDE does not flag these as duplicate code because the duplicated “skeleton” is hard to extract into a reusable method.

Why Generics + Functional Programming Helps

By abstracting the variable parts (the count query and the list query) into functional parameters, we can collapse the repeated skeleton into a single generic method.

Generic Wrapper Example

A typical generic response class is shown below:

public class ServiceResult<T> {
    private Boolean success;
    private String errorCode;
    private String errorMsg;
    private T content;
    // getters and setters omitted
}

Functional Interface Example

Using Guava’s ListenableFuture we can pass a lambda as a method argument:

public static <V> ListenableFuture<V> invokeWithFuture(Callable<V> callable) {
    return gPool.submit(callable);
}
@Test
public void invokeWithFuture() throws Execution {
    ListenableFuture<String> result = AsyncInvoke.invokeWithFuture(() -> "hello");
    System.out.println(result.get());
}

Generic Pagination Utility

The following generic method accepts two Callable arguments: one to obtain the total count and another to obtain the detail list.

@SneakyThrows
public static <T> PageData buildPageData(
        Callable<Integer> countFunction,
        Callable<List<T>> listFunction) {
    PageData pageData = new PageData();

    int count = countFunction.call();
    if (count == 0) {
        pageData.setCount(0);
        return pageData;
    }

    List<T> resultList = listFunction.call();
    pageData.setCount(count);
    pageData.setResult(resultList);
    return pageData;
}
static class PageData<T> {
    private int count;
    private T result;
}
@Test
public void testBuildPageData() {
    buildPageData(() -> 1, () -> Arrays.asList("1"));
}

Async Callback Example Using Generics

An interface CallbackTask<R> defines the contract for asynchronous execution.

public interface CallbackTask<R> {
    R execute();
    default void onSuccess(R r) {}
    default void onFailure(Throwable t) {}
}

The implementation uses CompletableFuture to run the task and invoke the appropriate callbacks.

private static <R> CompletableFuture<R> doInvoker(CallbackTask<R> executeTask) {
    return CompletableFuture.supplyAsync(() -> {
        try {
            return executeTask.execute();
        } catch (Exception e) {
            throw new BizException(ASYNC_INVOKER_ERROR.getErrorCode(), e.getMessage());
        }
    }, gPool).whenComplete((result, throwable) -> {
        if (throwable == null) {
            executeTask.onSuccess(result);
        }
    }).exceptionally(throwable -> {
        executeTask.onFailure(throwable);
        return null;
    });
}
CompletableFuture<Integer> result = AsyncInvoke.doInvoker(new CallbackTask<Integer>() {
    public Integer execute() {
        int result = 1 + 1;
        return result;
    }
    public void onSuccess(Integer integer) {
        System.out.println("on success result: " + integer);
    }
    public void onFailure(Throwable t) {
        System.out.println("error " + t.getMessage());
    }
});

Benefits and Drawbacks

Generics provide universality and reduce boilerplate.

Functional programming allows passing code blocks as parameters, increasing flexibility.

Both together lower code duplication and make the skeleton reusable.

However, they can make debugging harder, have a learning curve, and may reduce readability for developers unfamiliar with the style.

Final Thoughts

Generics and functional programming are syntactic sugar in Java; the real value lies in abstracting concrete scenarios and then implementing them with appropriate tools. The article encourages focusing on abstraction rather than the sugar itself.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaGenericsPaginationFunctional ProgrammingAsyncCode Reuse
Programmer XiaoFu
Written by

Programmer XiaoFu

xiaofucode.com – a programmer learning guide driven by the pursuit of profit

0 followers
Reader feedback

How this landed with the community

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.