← 개발일지

Converting JS Functions to Java: 3 Patterns to Get Right


Converting JS Functions to Java: 3 Patterns to Get Right

Porting logic from JavaScript to Java happens more often than you'd expect — pulling frontend validation to the server, migrating a Node.js service to Spring, or translating a legacy script into a proper backend method. The control flow usually looks straightforward, but the type system differences between the two languages create a handful of spots where bugs hide quietly.

Here are the three patterns that trip people up most often, and how to handle each one.


Pattern 1: String Comparison — Replace == with .equals()

In JavaScript, comparing strings with == works as expected:

if (prodTpCd == '2011') { ... }

In Java, the same syntax compiles fine but compares references, not values. String literals often pass by accident due to the String Pool, but any string coming from a method return, API input, or object construction will be a different instance — and == will return false.

// Wrong — reference comparison
if (prodTpCd == "2011") { ... }

// Correct — value comparison
if ("2011".equals(prodTpCd)) { ... }

Why put the constant first? It's NPE protection. If prodTpCd is null, "2011".equals(null) safely returns false. Flip it, and prodTpCd.equals("2011") throws a NullPointerException immediately.


Pattern 2: Array Membership — Replace includes() with List.contains()

JavaScript's Array.prototype.includes() maps directly to Collection.contains() in Java.

You'll occasionally see this dual-check pattern in JS code:

cdList.includes(parseInt(prodTpCd)) || cdList.includes(prodTpCd)

This exists because JavaScript is loosely typed — prodTpCd might arrive as a string or a number depending on the source. The code hedges against both.

In Java, once you declare the parameter as String, the ambiguity disappears. One check is enough:

private static final List<String> CD_LIST = List.of("2006", "2007", "2019");

if (CD_LIST.contains(prodTpCd)) { ... }

Fixing the type at the method signature eliminates an entire class of defensive workarounds.


Pattern 3: Shared Lists — Replace Global Variables with static final

JavaScript typically manages shared lists as module-level or global variables:

const cdList = [2001, 2002, 2003]; // declared somewhere above

In Java, the idiomatic equivalent is a private static final constant on the class:

// Java 8
private static final List<String> CD_LIST = Arrays.asList("2001", "2002", "2003");

// Java 9+ — fully immutable
private static final List<String> CD_LIST = List.of("2001", "2002", "2003");

Prefer List.of() over Arrays.asList(). Both are fixed-size, but List.of() is truly immutable — calling add() or set() throws UnsupportedOperationException. It makes your intent explicit: this list is a constant, not a mutable collection.


Before and After

Before (JavaScript)

function getAuthMid(prodTpCd, taxtTpCd) {
    let mid = '';
    if (prodTpCd == '2011') {
        mid = 'MID_A';
    } else if (cdList.includes(parseInt(prodTpCd)) || cdList.includes(prodTpCd)) {
        if (taxtTpCd == '1002' && (prodTpCd == "2006" || prodTpCd == "2007")) {
            mid = 'MID_B';
        } else {
            mid = 'MID_C';
        }
    } else if (taxtTpCd == '1002') {
        mid = 'MID_D';
    } else {
        mid = 'MID_E';
    }
    return mid;
}

After (Java)

private static final List<String> CD_LIST = List.of("2006", "2007", "2019");

public String getAuthMid(String prodTpCd, String taxtTpCd) {
    String mid;

    if ("2011".equals(prodTpCd)) {
        mid = "MID_A";
    } else if (CD_LIST.contains(prodTpCd)) {
        if ("1002".equals(taxtTpCd)
                && ("2006".equals(prodTpCd) || "2007".equals(prodTpCd))) {
            mid = "MID_B";
        } else {
            mid = "MID_C";
        }
    } else if ("1002".equals(taxtTpCd)) {
        mid = "MID_D";
    } else {
        mid = "MID_E";
    }

    return mid;
}

The logic is identical. The difference is that the Java version won't silently misbehave at runtime.


Summary

| What to change | JavaScript | Java | |---|---|---| | String comparison | a == 'value' | "value".equals(a) | | List membership | arr.includes(x) | list.contains(x) | | Type hedging | includes(parseInt(x)) \|\| includes(x) | Fix parameter to String, use contains(x) | | Shared list | Module/global variable | private static final List<String> |

Most JS-to-Java conversion bugs come from the type system difference, not the logic. Get string comparison and collection APIs right, and the rest of the conversion is mechanical.