Note: I'm working on version 2 of this guide and I need your help! Please use this form to give me feedback on what you think should go in the next version. Thanks!
Java is one of the most popular programming languages around, but no one seems to enjoy using it. Well, Java is actually an alright programming language, and since Java 8 came out recently, I decided to compile a list of libraries, practices, and tools to make using Java better. "Better" is subjective, so I would recommend taking the parts that speak to you and use them, rather than trying to use all of them at once. Feel free to submit pull requests suggesting additions.
This article was originally posted on my blog.
Read this in other languages: English, 简体ä¸ć–‡
Traditionally, Java was programmed in a very verbose enterprise JavaBean style. The new style is much cleaner, more correct, and easier on the eyes.
One of the simplest things we as programmers do is pass around data. The traditional way to do this is to define a JavaBean:
public class DataHolder {
private String data;
public DataHolder() {
}
public void setData(String data) {
this.data = data;
}
public String getData() {
return this.data;
}
}
This is verbose and wasteful. Even if your IDE automatically generated this code, it's a waste. So, don't do this.
Instead, I prefer the C struct style of writing classes that merely hold data:
public class DataHolder {
public final String data;
public DataHolder(String data) {
this.data = data;
}
}
This is a reduction in number of lines of code by a half. Further, this class is immutable unless you extend it, so we can reason about it easier as we know that it can't be changed.
If you're storing objects like Map or List that can be modified easily, you should instead use ImmutableMap or ImmutableList, which is discussed in the section about immutability.
If you have a rather complicated object that you want to build a struct for, consider the Builder pattern.
You make a static inner class which will construct your object. It uses mutable state, but as soon as you call build, it will emit an immutable object.
Imagine we had a more complicated DataHolder. The builder for it might look like:
public class ComplicatedDataHolder {
public final String data;
public final int num;
// lots more fields and a constructor
public static class Builder {
private String data;
private int num;
public Builder data(String data) {
this.data = data;
return this;
}
public Builder num(int num) {
this.num = num;
return this;
}
public ComplicatedDataHolder build() {
return new ComplicatedDataHolder(data, num); // etc
}
}
}