Prelude to Java
Introduction
When I began my first Java project, I had a week to prepare. I got my hands dirty learning Java as fast as possible. This was me a week later:

The fundamental problem of learning something new is unknown unknowns. When you don’t know what you should know, things can get difficult.
In what follows, I introduce some unknown unknowns I wish I knew as I began my Javadventures. Maybe, as result of this, some hapless future Java learner can be more prepared than I was when I started.
The topics I will address are as follows:
- Java is not a scripting language
- Types
- Interfaces
- Annotations
- Generics
- Use an IDE
Java is not a scripting language

“Scripting language” is not well defined, but whatever it is, Java ain’t it. If you want to write a one line “hello, world” Java script… use Javascript. (Not a coincidence, by the way.)
An example of a scripting language is Ruby. You can print “hello, world” from a terse, one-line file. You can even do it in a short line of Bash:
echo 'print "hello, world"' > hi.rb; ruby hi.rbJava is not so simple. But we’ll do it anyways. For posterity.
First, download the SDK from Oracle. Choose Java SE (the SE stands for Standard Edition). Next, write a file called Hi.java:
class Hi {
public static void main(String[] args) {
System.out.println("hello, world");
}
}- Public means the
mainmethod is accessible anywhere. - Static means the
mainmethod is a class method. - Void means the
mainmethod does not return a value.
Next, compile it. Run javac Hi.java (the ‘c’ stands for ‘compiler’). It generates class files from java files. In our case, the Hi.java file contains a single class: Hi . Thus, javac will generate Hi.class.
Once we have our class file, we can use the java command to execute it. Run java Hi and greet the world. Such friendly. Much programmer.
Types
Types are a way to identify objects you’re working with. For example, Pizza is the type of myPizza in the follow code:
Pizza myPizza = new Pizza("pepperoni");This implies the existence of a Pizza class, which could look as follows:
public class Pizza {
private String topping; public Pizza(String topping) {
this.topping = topping;
}
}
In String topping, String is the type of the parameter topping.
Explicitly typed languages like Java can perform robust type checking at compile time to determine if your code is coherent. It will not catch all problems, but it does increase reliability at runtime when compared to languages that lack type-checking compilation steps.
Interfaces
Java interfaces specify some or all of the behavior of an object. For example, we could define a PizzaMaker interface that specifies a bakePizza behavior:
interface PizzaMaker { Pizza bakePizza(Pizza pizza);}
Notice that this does not define how the bakePizza function is implemented. That is a job for the class implementing this interface. What the PizzaMaker interface does is state that something claiming to implement PizzaMaker must implement some function called bakePizza. For example, we could have a Chef class that implements PizzaMaker:
public class Chef implements PizzaMaker { @Override
public Pizza bakePizza(Pizza pizza) {
[implementation code goes here]
} }
(@Override is an annotation. We will discuss them later.)
If Chef did not define a bakePizza function, while still claiming to implement PizzaMaker, the compiler would error (or your IDE would notice the problem and warn you).
Interfaces seemed cumbersome to me at first, but I have since come to appreciate the rigidity and specificity they provide.
Here’s an example of the utility of interfaces. Let’s say we have a PizzaRestaurantManager object that is responsible for daily dinner preparations. On Saturdays a famous pizza chef bakes pizzas for the guests, while on every other day a bus boy just throws some frozen pizzas in the oven. Maybe on first approach you’d write a prepareDinner function that looked something like this:
class PizzaRestaurantManager { public void prepareDinner(
DayOfWeek day,
Chef chef,
BusBoy busBoy
) {
if (day == DayOfWeek.Saturday) {
chef.bakePizza();
} else {
busBoy.bakePizza();
}
} }
This code works, but it is violating the O and I in SOLID. You can refactor this code, leveraging interfaces to simplify the code. Let’s use the PizzaMaker interface we defined earlier, and have both the Chef class and BusBoy class implement it. We can then refactor the code as follows:
class PizzaRestaurantManager {
public void prepareDinner(PizzaMaker pizzaMaker) {
pizzaMaker.bakePizza();
} }
When you use this code, you can pass in Chef, or BusBoy, or any PizzaMaker-implementing class.
(As an aside, it should be noted that you cannot pass in a non-PizzaMaker object, even if it has a bakePizza method defined on it. The compiler will not allow it.)
Annotations
Java annotations are syntactic metadata. Sounds cool, right?

Okay, well maybe there are cooler things, but anyways, they look like this:
@OverrideThe @ sign is what designates an annotation. Annotations can inform the compiler to perform additional actions, like checking for non-nullity: @NonNull String string;. They can generate code on your behalf @Getter(lazy=true) private final String firstName;. They can augment behavior during runtime as well, such as handle requests: @Controller class APIController {...}.
Custom annotations are used widely by frameworks and packages. The first two annotations used in the above paragraph came from project Lombok, and the last one came from the Spring framework. Java SE 8 also has many annotations out of the box.
A great resource for learning more about annotations is the Java tutorial on annotations.
Generics
A generic is a type variable. Let’s imagine we want a list of waiters for our pizza restaurant, and the ability to add a new waiter to the list. We could implement a specific List interface:
public interface WaiterList { boolean add(Waiter waiter); }
Or we could implement a more generic interface that can hold a list of any type, not just Waiter:
public interface List<E> { boolean add(E e);}
The list is a generic type, more specifically, a generic interface. The <> wraps the type parameter section, inside of which is the type parameter E. (There can be multiple type parameters, e.g., Pair <A, B>.) The add function takes an object of type E, represented by the parameter e, and adds it to the list.
The generic list interface allows us to reuse it across multiple types. To use it, we replace E with the type we want a list of:
Waiter waiter1 = new Waiter("Alice");
Waiter waiter2 = new Waiter("Bob");List<Waiter> waiters = new ArrayList();waiters.add(waiter1);
waiters.add(waiter2);
Generics DRY up code, increasing maintainability and reliability.
A great resource for learning more about generics is the Java tutorial on generics.
Use an IDE
Old me was a Vim-loving, dynamic language programmer that associated mouse usage with losing. Oh, you want me to use this IDE?

Well, not all languages are alike. Different languages warrant different development environments.
I think some of my Java confusions stemmed from my Vim-loving resistance to IDEs. I didn’t want to learn some bloated editor just to type a line of Java. So, instead, I drowned for a day in bloated Vim plugins just to type a line of Java.
In the languages I knew prior to Java, inline method documentation that is triple the length of methods themselves, and million method classes were code smells. In Java, it’s not (or else the whole language smells). An IDE will help you navigate it all.
Java is manifestly typed and nominally typed. Big words aside, it means everything is typed, i.e., explicit typing. Java typing is so explicit it’s rated R. Everything, everywhere is typed.
The downside of explicit typing is you have the misfortune of one day writing something like this:
Map<String, Pair<Int, List<Optional<Set<Double>>>>> map;The upside of explicit typing is the mythic power IDEs have as a result. The Java programmer inside joke is that IDEs write the code, you just watch it and occasionally press tab and enter and stuff. When all types are known, good IDEs can deduce your next action, intelligently refactor code, and rename fundamental objects throughout your entire codebase easily. So let it write your code and perform jaw-dropping refactors.
Use an IDE. Just do it.

Conclusion
As a parting gift, here’s something you will likely use in your future Javadventures: Arrays.asList().
Recall that List is an interface. ArrayList is a class that implements List. A helper class for ArrayList is Arrays. A helpful method in it is asList. It is a generic method:
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}The T... notation denotes a vararg called a. The diamond notation <> in ArrayList<> represents type inference. Java will infer the type so it does not need to be specified (the type inferred is T).
You can use Arrays.asList to create lists of variable size:
List<Waiter> waiters = Arrays.asList(waiter1, waiter2, waiter3); I hope you enjoyed this prelude to Java, and I wish you luck in your future Javadventures!
