Did you know? Programmers convert coffee to code.

If you like my articles, sponsor me a coffee.

Why use FindBugs in all your Java projects

FindBugs is a good tool to find hidden problems in your code you would not find with the compiler tool. Some people use the results for blaming co-developers for the findings.

However you should use FindBugs even if you are just starting programming because if you look at the findings, you can learn a bunch of new and useful things.

Let’s see some examples of what we can learn from FindBugs.

BigDecimal addition method

Few know that the add method of the BigDecimal class adds together two values and returns a new BigDecimal containing the result of the addition.

So if you execute

BigDecimal first = new BigDecimal(5);
BigDecimal second = new BigDecimal(7);

first.add(second);

System.out.println(first);

then the result in variable first is 5 and not the expected 12.

If you install and configure FindBugs, you will get a message of type “Scariest” for the call of the add method:

Return value of java.math.BigDecimal.add(BigDecimal) ignored in …

If you click the bug beside the LoC then you get the explanation what this bug means.

So if you want to update the code, you should write

first = first.add(second);

and the result of the print statement will be 12.

Infinite loops

Sometimes it happens. You write infinite loops accidentally. Sometimes it is not an accident. For example in a TCP server where you communicate through a socket and do not want to handle the connection closing. Or you have a thread for a game and want it to run forever.

But this is bad practice. For the game you have to have a state where it ends. For socket communication you have to care about when it is done. So infinite loops are bad, you should care about them with FindBugs.

Using equals the wrong way

Sometimes you want to check that all your values are OK so they can be used to make some logic. If you deal with Objects, equals is the right method to use. However you can end up comparing two different types (maybe enums) and you do not even see this.

Your comparison seems OK, the Java compiler does not complain and you wonder why your block of code never executes.

And do not forget: if you do not override the equals method, Objects own equals method is called. And that is only a reference-comparison:

public boolean equals(Object obj) {
    return (this == obj);
}

Comparison with == or !=

If you compare enums, you should use == and != for comparison. equals is OK too, however it does reference comparison:

public final boolean equals(Object other) {
    return this==other;
}

However if you use == or != for Strings, you get a warning from FindBugs:

Comparison of String objects using == or !=

This is nice, because it can happen, that two Strings containing the same value are not the same when using ==.

Encoding and localization

Not properly looking at encoding of files and localization when converting Strings is not a scary bug. It is just of concern you should look at if you deal with String manipulation over various Java implementations, installed in various countries. In that case it can happen that your application does not work as you (and your customers) expect.

Found reliance on default encoding

means that you should care about how you for example read a file. Because the byte to String or String to byte conversion can vary based on the Java-implementation for the running platform. So if you want to read a file you know is UTF-8, you should read it like:

BufferedReader in = new BufferedReader(
           new InputStreamReader(
                      new FileInputStream(new File("PATH_TO_FILE")), "UTF8"));

Use of non-localized String.toUpperCase() or String.toLowerCase()

means that you can get a problem if your application uses international characters (Hebrew, Arabic and so). For this case you should use for example

myString.toLowerCase(Locale.CHINESE);

Reading unwritten fields

If you are using DI (Dependency Injection) in your application it can happen that you miss one injection and then dereference (use) the field.

FindBugs is kind to tell you this. However the tool is aware that there can be other injection mechanisms not known and the message tells you that you can ignore this error if you use some unknown injection method:

The program is dereferencing a field that does not seem to ever have a non-null value written to it. Unless the field is initialized via some mechanism not seen by the analysis, dereferencing this value will generate a null pointer exception.

But it is really seldom that applications use an unknown DI solution (if you have a custom developed one try to get rid of it and use some currently available), so this warning shows a potential NullPointerException.

Null for nonnull parameters

This exception comes if you call a method with null as parameter, however your method does not check the parameter for null — so the method does throw a NullPointerException if it uses the null parameter.

For this I encourage every co-developer to have unit tests for every method parameter passing a null value. This works without FindBugs however FindBugs does not need to run the tests to see this scary method call. Beside this most of the time releases are made without executing the tests, so this bug can be show up in production environments if you only rely on unit tests.

Conclusion

FindBugs is a nice tool to use in your Java projects. I recommend it for every project — even if you create a simple pet-project: use it. It is not just because of finding bugs, you can learn a bunch from the warnings.

For experienced developers: create katas based on the often re-occurring findings and try to avoid them in the future.

Naturally there are other tools — and for other languages too. See a list at Wikipedia for more information.

GHajba
 

Senior developer, consultant, author, mentor, apprentice.

I love to share my knowledge and insights what I achieve through my daily work which is not trivial — at least not for me.

Click Here to Leave a Comment Below 1 comments
%d bloggers like this: