Refactoring Java Methods to Simulate Input/Output Parameters

The article explains how Java’s lack of true input‑output parameters can be worked around by refactoring the complex splitLineString method using techniques such as parameter objects, single‑element arrays, mutable tuples, custom holder classes, return objects, ThreadLocal variables, or instance fields, ultimately recommending a generic holder class as the most balanced solution.

Amap Tech
Amap Tech
Amap Tech
Refactoring Java Methods to Simulate Input/Output Parameters

Introduction

Java does not provide a direct input/output (inout) parameter mechanism. To achieve similar functionality, developers need to rely on alternative techniques such as method parameters, parameter objects, single‑element arrays, tuples, holder classes, return objects, thread‑local variables, or class member variables.

Problem Statement

The original splitLineString method contains a nested loop that makes the code hard to read and maintain. Moreover, the method modifies the index and coordinate variables locally, which prevents the caller from seeing the updated values.

Refactoring Techniques

Use method parameters to pass and update values.

Introduce a parameter object (e.g., InoutParameter) to group related inout values.

Use a single‑element array as a mutable holder for primitive values.

Leverage Apache Commons MutablePair or MutableTriple as tuple containers.

Create a custom generic ObjectHolder<T> class for mutable references.

Return a custom result object ( ReturnResult) that contains all needed outputs.

Employ ThreadLocal variables for thread‑confined mutable state.

Encapsulate mutable state in instance fields of a dedicated algorithm class.

Code Examples

/**
 * Geometry helper class
 */
public final class GeometryHelper {
    // constants ...
    public static LineString[] splitLineString(LineString lineString, double[] segmentLengths) {
        // original logic ...
        int index = 1;
        Coordinate[] coordinates = lineString.getCoordinates();
        Coordinate coordinate = coordinates[0];
        // ...
    }
}

Below are concise excerpts for each technique (the full source contains many similar blocks):

// 1. Parameter object
private static class InoutParameter {
    private int index;
    private Coordinate coordinate;
    // getters & setters
}
// 2. Single‑element array
int[] indexHolder = new int[]{1};
Coordinate[] coordinateHolder = new Coordinate[]{coordinates[0]};
// 3. Tuple (Apache Commons)
MutablePair<Integer, Coordinate> mutablePair = MutablePair.of(1, coordinates[0]);
// 4. Generic holder
public class ObjectHolder<T> { private T value; /* getter/setter */ }
ObjectHolder<Integer> indexHolder = new ObjectHolder<>(1);
ObjectHolder<Coordinate> coordinateHolder = new ObjectHolder<>(coordinates[0]);
// 5. Return object
@Getter @Setter @AllArgsConstructor
private static class ReturnResult {
    private int index;
    private Coordinate coordinate;
    private LineString lineString;
}
// 6. ThreadLocal
private static final ThreadLocal<Integer> INDEX_HOLDER = new ThreadLocal<>();
private static final ThreadLocal<Coordinate> COORDINATE_HOLDER = new ThreadLocal<>();
// 7. Algorithm class with fields
public class SplitLineStringAlgorithm {
    private int index;
    private Coordinate coordinate;
    public LineString[] splitLineString(LineString lineString, double[] segmentLengths) {
        // use instance fields as mutable state
    }
}

Analysis and Recommendations

The article evaluates each approach:

Parameter objects and custom holder classes provide clear semantics and type safety.

Single‑element arrays and tuples are concise but can reduce readability, especially when the number of parameters grows.

ThreadLocal solves thread‑safety but adds complexity and should be avoided unless necessary.

Using class member fields simplifies state sharing but makes the code non‑thread‑safe.

Overall, the author recommends the holder class approach (section 3.4) as the most balanced solution for the presented case.

Quote

When you’re passing primitives into a method, you get a distinct copy of the primitive. When you’re passing a reference into a method, you get a copy of the reference.

Closing Remarks

The article concludes with a philosophical note from Zhuangzi and a promotional announcement for an upcoming “Smart Mobility” online conference hosted by Alibaba Gaode Maps.

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.

JavaprogrammingrefactoringInputOutputParametersMethodExtraction
Amap Tech
Written by

Amap Tech

Official Amap technology account showcasing all of Amap's technical innovations.

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.