Fundamentals 25 min read

Mastering In‑Out Parameters in Java: 5 Refactoring Techniques Explained

This article explores why Java lacks native input‑output parameters, examines common pitfalls when extracting methods, and presents five practical refactoring solutions—including parameter objects, single‑value arrays, tuple classes, holder objects, and return‑value strategies—complete with code samples and usage guidelines.

Alibaba Cloud Developer
Alibaba Cloud Developer
Alibaba Cloud Developer
Mastering In‑Out Parameters in Java: 5 Refactoring Techniques Explained

Introduction

Java does not provide a direct input‑output (InOut) parameter mechanism, so developers must use alternative techniques to achieve the same effect. The article begins with a quote from Kent Beck emphasizing good habits and refactoring, then outlines a real‑world problem of splitting a line string into segments.

Problem Statement

The task is to divide a line string (a series of latitude‑longitude coordinates) into segments of specified lengths without spherical distance calculations.

Original Implementation and Issues

The original splitLineString method contains nested loops, making the logic complex and hard to maintain. Extracting the inner loop into a separate method can improve readability but introduces scope problems for variables like index and coordinate, which are modified only on the method’s local copy.

When you pass primitives to a method you get a copy; when you pass an object reference you get a copy of the reference.

Refactoring Techniques

1. Parameter Object : Encapsulate multiple parameters into a dedicated class (e.g., InoutParameter) to pass by reference and modify its fields.

2. Single‑Value Array : Use a one‑element array to hold mutable values such as int[] indexHolder and Coordinate[] coordinateHolder.

3. Tuple Class : Leverage Apache Commons‑Lang3 tuples ( MutablePair, ImmutableTriple) to bundle related values without creating a custom class.

4. Return Object : Define a result class ( ReturnResult) that carries the updated index, coordinate, and generated LineString back to the caller.

5. Class Field : Store mutable state in thread‑local variables or instance fields (e.g., ThreadLocal<Integer> INDEX_HOLDER) to share across method calls.

Code Samples

/**
 * Geometry helper class
 */
public final class GeometryHelper {
    private static final int DIGIT_SCALE = 8;
    private static final double ZOOM_SCALE = 10000000000L;
    private static final GeometryFactory GEOMETRY_FACTORY = new GeometryFactory(new PrecisionModel(PrecisionModel.FLOATING));
    // ... original constants omitted

    public static LineString[] splitLineString(LineString lineString, double[] segmentLengthes) {
        // original calculation omitted
        Coordinate[] coordinates = lineString.getCoordinates();
        InoutParameter inout = new InoutParameter(1, coordinates[0]);
        int length = targetLengthes.length;
        LineString[] lineStrings = new LineString[length];
        for (int i = 0; i < length - 1; i++) {
            lineStrings[i] = combineLineString(coordinates, inout, targetLengthes[i]);
        }
        lineStrings[length - 1] = buildLineString(coordinates, inout.getIndex(), inout.getCoordinate());
        return lineStrings;
    }

    private static LineString combineLineString(Coordinate[] coordinates, InoutParameter inout, long targetLength) {
        int index = inout.getIndex();
        Coordinate coordinate = inout.getCoordinate();
        // ... add coordinates logic omitted
        inout.setIndex(index);
        inout.setCoordinate(coordinate);
        return buildLineString(coordinateList);
    }

    // Additional implementations (single‑value array, tuple, return object, thread‑local, etc.) follow the same pattern.
}

@Getter @Setter @NoArgsConstructor @AllArgsConstructor
private static class InoutParameter {
    private int index;
    private Coordinate coordinate;
}

Comparative Evaluation

Each technique has trade‑offs: parameter objects improve readability but add a class; single‑value arrays are concise but obscure intent; tuples avoid boilerplate but can become unwieldy with many elements; return objects cleanly convey multiple results; thread‑local variables solve concurrency issues but increase complexity.

Conclusion

The most suitable approach for the presented case is the holder class ( InoutParameter) because it balances clarity and maintainability without excessive boilerplate.

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.

Design PatternsJavaMethod ExtractionInOut Parameters
Alibaba Cloud Developer
Written by

Alibaba Cloud Developer

Alibaba's official tech channel, featuring all of its technology 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.