3rd Party Libraries Every Java Programmer Should Know
Java core developer and author of Effective Java Joshua Bloch writes that we should know and use the libraries.
That advice is still good. Most Java projects are easier to maintain when you reach for a well-known library instead of writing another homegrown helper.
Here are a few libraries I keep coming back to.
Lombok
Java boilerplate adds up quickly. Lombok removes a lot of it with annotations that generate common methods at compile time.
A small immutable value object is a good example:
import lombok.Value;
@Value
class Person {
String firstName;
String lastName;
}
@Value makes the fields final, generates a constructor, and adds getters, equals, hashCode, and toString. For data objects, that saves a lot of repetitive code.
Guava
If you are about to write a convenience method for collections or strings, check Guava first.
One of the most useful parts of Guava is its collection helpers and immutable types:
import com.google.common.collect.ImmutableList;
public class PrintArgs {
public static void main(String[] args) {
ImmutableList<String> values = ImmutableList.copyOf(args);
System.out.println(values);
}
}
Guava is also useful for Splitter, Joiner, caching, preconditions, and other small utilities that show up in real applications all the time.
Apache Commons Lang
Apache Commons Lang fills a similar role for everyday string and object helpers.
If you need to make user input friendlier, StringUtils is often enough:
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
public class CapitalizeArgs {
public static void main(String[] args) {
Stream.of(args).map(StringUtils::capitalize).forEach(System.out::println);
}
}
That may look small, but it is exactly the kind of code that should not be handwritten in five different places.
JUnit
JUnit is the default testing tool for most Java codebases.
It fits naturally into both small projects and large test suites, and most IDEs understand it well.
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
public class BasicTest {
@Test
void checkBasicArithmetic() {
assertEquals(2, 1 + 1);
}
@Test
void rejectsMissingInput() {
assertThrows(IllegalArgumentException.class, () -> {
throw new IllegalArgumentException("must give a first name and a last name");
});
}
}
The main point is not the exact assertion style. It is that JUnit gives you a standard way to express behavior and regression tests.
Jackson and Gson
Jackson and Gson both solve the same basic problem: turning Java objects into JSON and back again.
I usually pick one and stick to it across the codebase.
import com.google.gson.Gson;
public class PrintPersonJson {
public static void main(String[] args) {
if (args.length < 2) {
throw new IllegalArgumentException("must give a first name and a last name");
}
Person person = new Person(args[0], args[1]);
System.out.println(new Gson().toJson(person));
}
}
The practical choice is less about the serialization call and more about standardizing on one JSON library so your application does not accumulate competing conventions.
Log4j
If a project is serious enough to run in production, System.out.println should not be the main logging strategy.
Apache Log4j provides structured logging, log levels, and a cleaner path to centralize output.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class PrintArgLength {
private static final Logger log = LogManager.getLogger(PrintArgLength.class);
public static void main(String[] args) {
if (args.length == 0) {
log.error("please supply 1 argument");
System.exit(1);
}
log.info("length of first arg: {}", args[0].length());
}
}
The benefit is not just prettier output. Logging libraries give you severity levels, formatting, and control over where messages go.
Takeaway
The real lesson from Bloch’s advice is to treat libraries as part of your design vocabulary.
Use them when they reduce boilerplate, improve readability, or make a problem standard enough that you should not solve it twice.
