Input params are not for output
Sometimes you run across some code that makes you cringe a little bit. That happened to me today when I ran across this blog post. It’s about how the final modifier is used for method parameters. A sample of what the post is trying to convey looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public void printWords() { final List<String> words = new ArrayList<String>(); words.add("foo"); words.add("bar"); appendNewWords(words); System.out.println(words); } private void appendNewWords(List<String> words) { words.add("boo"); words.add("far"); } prints: [foo, bar, boo, far] |
The problem with that code is it treats a method input as an output parameter. Generally, that’s bad form and should be avoided. Even with a descriptive method name, you end up with code that doesn’t read well. A better example, with the input parameter removed, would look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public void printWords() { final List<String> words = new ArrayList<String>(); words.add("foo"); words.add("bar"); words.addAll(getNewWords()); System.out.println(words); } private List<String> getNewWords() { final List<String> newWords = new ArrayList<String>(); newWords.add("boo"); newWords.add("far"); return newWords; } prints: [foo, bar, boo, far] |
Perhaps you’re still dead set on passing your List object into a method and getting results back. Maybe you want to remove elements, for example. You still want to use input params for input and return an output object. In this instance, it’s nicer to pass an immutable List (Google collections) or an unmodifiable in and return results based on that versus modifying the input param, which leads to confusing code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public void printWords() { final List<String> words = new ArrayList<String>(); words.add("foo"); words.add("bar"); List<String> modifiedWords = removeFoo(Collections.unmodifiableList(words)); System.out.println(words); System.out.println(modifiedWords); } private List<String> removeFoo(final List<String> words) { final List<String> modifiedWords = new ArrayList<String>(words); modifiedWords.remove("foo"); return modifiedWords; } prints: [foo, bar] [bar] |

Agreed. I see this over and over again and have to refactor to fix. 9 times out of 10 there isn’t a problem, the 10th time is the one that makes you pull your hair out.
[Reply]