Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Use Precise Java Method Parameters

DZone's Guide to

Use Precise Java Method Parameters

Picking the right method parameter types means more robust and shorter code in your Java applications. Beware of implementing them without forethought.

· Java Zone
Free Resource

The single app analytics solutions to take your web and mobile apps to the next level.  Try today!  Brought to you in partnership with CA Technologies

We Java developers generally have a bad habit of using method parameters without thinking of what is actually needed and just picking whatever we are used to, what we have available, or whatever first comes into mind. Consider the following representative example:

    private static String poem(Map<Integer, String> numberToWord) {
        return new StringBuilder()
            .append("There can be only ")
            .append(numberToWord.get(1))
            .append(" of you.\n")
            .append("Hearts are better off when there are ")
            .append(numberToWord.get(2))
            .append(" of them together.\n")
            .append("These ")
            .append(numberToWord.get(3))
            .append(" red roses are a symbol of my love to you.\n")
            .toString();
    }


When we use the method above, we provide a Map that translates from a number to a String. We might, for example, provide the following map:

    Map<Integer, String> englishMap = new HashMap<>();
        englishMap.put(1, "one");
        englishMap.put(2, "two");
        englishMap.put(3, "three");


When we call our poem method with the englishMap, then the method will produce the following output:

There can be only one of you.
Hearts are better off when there are two of them together.
These three red roses are a symbol of my love to you.


That sounds good. Now suppose that your significant other is a computer nerd and you want to spice up your poem and make an impression. This is the way to go:

Map<Integer, String> nerdMap = new HashMap<>();
        nerdMap.put(1, "1");
        nerdMap.put(2, "10");
        nerdMap.put(3, "11");


If we now submit our nerdMap to the poem method, it will produce the following poem:

There can be only 1 of you.
Hearts are better off when there are 10 of them together.
These 11 red roses are a symbol of my love to you.


As with all poems, it is difficult to judge which poem is more romantic than the other, but I certainly have my own personal view.

The Problems

There are several problems with the solution above.

First of all, as an outside caller, we cannot be sure that the poem method does not change the Map we provide. After all, we provide a Map, and there is nothing preventing a receiver from doing whatever it wants with the Map, even clearing the entire map altogether. This can, of course, be avoided by wrapping the Map using the Collections.unmodifiableMap() method or providing a copy of an existing Map whereby the copy is later discarded.

Secondly, we are tied to using a Map when we only need something that translates from an integer to String. This might create unnecessary code in some cases. Think back to our nerdMap, where the values in the Map could easily be computed using the Integer::toBinaryString instead of mapping them manually.

The Solution

We should strive to provide precisely what is needed in any given situation and not more. In our example, we should modify the poem method to take a function that goes from an integer to a String. How this function is implemented on the caller side is of less importance. It can be a Map, a function, or code, or something else. Here is how it should be done in the first place:

    private static String poem(IntFunction<String> numberToWord) {
        return new StringBuilder()
            .append("There can be only ")
            .append(numberToWord.apply(1))
            .append(" of you.\n")
            .append("Hearts are better off when there are ")
            .append(numberToWord.apply(2))
            .append(" of them together.\n")
            .append("These ")
            .append(numberToWord.apply(3))
            .append(" red roses are a symbol of my love to you.\n")
            .toString();
    }


If we want to use the poem method with a Map, we simply call it like this:

    // Expose only the Map::get method
    System.out.println(poem(englishMap::get));


If we want to compute the values like we did for the nerd poem, then we can do it even more simply:

    System.out.println(poem(Integer::toBinaryString));


Heck, we can even produce a poem for a significant other suffering from a dual personality disorder like this:

    System.out.println(
        poem(
            no -> englishMap.getOrDefault(no + 1, Integer.toString(no + 1))
        )
    );


This will produce the following poem:

There can be only two of you.
Hearts are better off when there are three of them together.
These 4 red roses are a symbol of my love to you.


Be careful with your method parameters!

CA App Experience Analytics, a whole new level of visibility. Learn more. Brought to you in partnership with CA Technologies.

Topics:
java ,method parameter ,clean code ,translation ,tutorial

Published at DZone with permission of Per-Åke Minborg, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}