THE BLOG

A Crash Course in Java for Coding Camp Graduates

February 23, 2016

Congratulations! After 10-20 weeks of hard work, you’ve graduated from a well-known coding camp and are pumped to finally land that dream developer job.

But wait, what’s this!? Your dream company happens to work with a lot of Fortune 500 clients and wants you to know that most enterprisey of langauges, Java. Or maybe your dream position involves building mobile apps for Android – that’s also Java.

Chances are that your coding camp used Ruby as its primary language1, Rails as its primary web framework, and taught enough JavaScript for you to develop an irrational hatred of semicolons and almost be able to explain how closures work. But JavaScript, for better or worse, is not Java, although there are plenty of semicolons and curly braces in both languages.

This post seeks to provide a list of the most salient differences between Java and more dynamic languages like Ruby and JavaScript for recent graduates of coding camps. It can be conceived as either a crash course to what makes Java different or a handy source to refer back to while ramping up your Java abilities.

A Disclaimer

Though this page will (hopefully!) help you to quickly acquire reading knowledge of Java (which can be very useful when working through a book like Cracking the Coding Interview), in order to learn to code in Java, you actually need to, you know, code in Java. There are various websites and books (for example, Head First Java) that promise to teach you Java. Be aware, though, that recent versions of Java have added new features, such as Ruby-like iteration through collections, which only debuted in 2014’s Java SE 8. As such, I personally elected to suffer through the rather rigid and stilted tutorials from the Oracle website.

With that disclaimer out of the way, let us now proceed to the big list of differences, which, in the fashion of all lists that appear on the Internet, will be conveniently numbered.

1) Static Typing

Ruby and JavaScript are both dynamically typed. Java is statically typed. What does this mean? Quite simply:

// JavaScript
var thing = 18
thing = "coffee calligraphy"
// this is okay

// Java
int thing = 18
thing = "coffee"
// Error: java: incompatible types: java.lang.String cannot be converted to int

In Java, every variable must be declared as a certain type. Its type cannot change as the program moves forward—its type is therefore static. There are eight primitive data types (including int used above), the String data type (which is primitive-like in its immutability), many additional classes (types) available in Java’s various libraries, and an infinite number of types (classes) that you can design yourself.

2) Explicit Return Type and Argument Types

Another example of Java’s static typing is how method declarations must be written. Here are two examples:

public String numbersToWords(int x, int y) {
  /* CODE */
}

private void setName(String name) {
  /* CODE */
}

<modifier(s)> <return type> <method name> (<argument1 type> <argument1>, etc.)

The return type of a method must be explicitly identified. (If the method does not return anything, the keyword void is used instead.) Any arguments that are passed in must also be given a type.

3) Type Safety and Code Compiling

Okay, you’re probably thinking that explicitly declaring types seems like a pain – take this typical line of Java2 as an example, TypePatternClassFilter typePatternClassFilter = new TypePatternClassFilter() – surely type declaration must bring some benefit?

It does. Java code is compiled down to something called bytecode, which is platform independent and runs very fast (almost as fast as C or C++). During the compiling process, any mismatched types are caught by the compiler (in fact, the compiler will refuse to compile the code), which greatly reduces the prospect of embarrassing runtime errors occurring. This is known as type safety. (It is not foolproof due to language features like generics and typecasting, but nonetheless it will catch most type errors.)

4) One Type per Array

Another result of Java’s static typing is that all elements in an array (and, in fact, any type of collection) must be of the same type. This is in contrast to Ruby and JavaScript where mix-and-match arrays are allowed – though not necessarily encouraged.

5) Arrays are Very Limited...

“Traditional” arrays in Java have very limited functionality, at least in comparison to Ruby’s arrays. Not only are they limited to one data type, but also they are created with a fixed length (which can only be increased using a roundabout procedure) and lack methods like pop, push, and shuffle. The positive side of these limitations is that they can lead to greater memory efficiency and speed.

Here are some simple examples of array creation and access:

// creates 10-element array of integers
int[] numbers = new int[10];

// assigns first element to 16
numbers[0] = 16;

// will output 0, which is the default value for int arrays
System.out.println(numbers[9]);

// simultaneous creation and assignment of array (note the curly braces)
short[] digits  = {2, 4, 6};

// will output 4
System.out.println(digits[1]);

// will raise an ArrayIndexOutOfBoundsException
System.out.println(digits[3]);

6) ...So Use ArrayList Instead

Luckily though, there is another option that’s available when a more flexible, dynamic, and fully-featured array is required. This is the ArrayList. There are a few different ways to create one, but the most straightforward method looks something like:

List<String>  specialWords = new ArrayList<String>();
List<Integer> magicNumbers = new ArrayList<Integer>();

Note that an ArrayList can still only contain one type (or, technically, it’s possible to use generics to allow for different subclasses of a common ancestor to be permitted, but this is an advanced topic). An ArrayList is an implementation of the List interface, which is part of the Java Collections Framework (write import java.util.*; at the top of the file to gain access to it). This means that an ArrayList can use collection-wide methods from the Collection interface, several useful manipulation methods in the Collections class, plus many specialized list/array methods within its own class.

7) Map as Equivalent to Hash or Object Literal

Lists aren’t the only collection type in the Java Collections Framework. The equivalent to a Ruby hash or a JavaScript object literal is Java’s Map interface with the most common implementation being HashMap. A HashMap, like any associative array, contains unordered key-value pairs with the requirement that each key be unique.

As is standard in Java, the data type of both the keys and values must be explicitly declared upon creation of a HashMap, and all keys and values added to it must conform to these types. Observe the syntax for map creation, setting a key to a value, and retrieving that value:

Map<String, Integer> countryData = new HashMap<String, Integer>();
countryData.put("USA", 324_118_787);
int population = countryData.get("USA");

8) Different Number Types and Their Object Wrappers

As mentioned above in #1, there are eight diffrent primitive data types in Java. Six of them represent integers and floating-point numbers of varying sizes. (The other two primitive types encode a Boolean value and a Unicode character.)

In the code fragments above, notice that Integer is the type declared for the ArrayList and HashMap samples. This is the object wrapper for the primitive data type of int, and it must be used since the data types used in collections must be descendants of the Object class. In cases such as these, Java will usually handle the conversion between an Integer object and an int primitive automatically.

9) Iteration Over Collections

When using “traditional” arrays, the code needed to iterate over the values looks equally “traditional”:

String[] words = {"World", "Monde", "Mir", "Swiat"};
for (int i = 0; i < words.length; i++) {
    System.out.println(words[i]);
}

However, if that traditional array is converted to a modern collection, iteration also looks more modern. In fact, there are two ways to iterate over a collection. The first way is called a for-each construct:

List<String> wordList = Arrays.asList(words);

for (String word : wordList) {
    System.out.println(word);
}

The second way, which is considered to be the preferred method, looks very modern indeed and was only introduced with Java SE 8 in 2014. The elements are streamed from the collection, at which point they are fed into an aggregate operation (full list found here), and this aggregate operation contains a lambda expression. It is worth pointing out that during the first 19 years of Java’s existence, none of the three bolded concepts were incorporated into the core language, so this method of iteration is very new indeed (at least for Java).

List<String> wordList = Arrays.asList(words);

wordList.stream()
        .forEach(w -> System.out.println(w));

10) Message Sending from the Class

The eagle-eyed among you might have spotted that in order to convert an array into a list, the “class” (or static) method Arrays.asList(words) needs to be used. While Ruby, JavaScript, and Java are all object-oriented languages, their overarching conceptions of message-sending differ significantly. If the same transformation from array to list were to exist in Ruby or JavaScript, there would almost assuredly be a method that could be called directly on the individual instance of the array, that is, something like, words.to_list. In Java, however, this isn’t the case.

Perhaps a more illustrative example (because it actually exists) is how collections are sorted. Taking the same array of words from #9, in Ruby the array would be sorted alphabetically with words.sort and in JavaScript with words.sort(). But in Java, the sort method is instead called on the class Arrays (not to be confused with the class Array, which has its own methods). The resulting code is Arrays.sort(words) (or Collections.sort(wordList) if sorting the list).

This pattern is widespread in Java, and will potentially frustrate Rubyists, to whom calling instance methods in such situations would seem much more natural.

11) Single Quotes for char, Double Quotes for String

As the heading advertises, use single quotes to represent a char primitive ('B'), and double quotes for a String ("Bill"). While on the topic of Java strings, note that (frustratingly) there is no string interpolation available in Java. Also, due to the immutability of the String class, whenever a string needs to be built by a complex process or frequently modified, the special StringBuilder or StringBuffer classes are better choices.

12) Packages and Classes

Now comes the fun part...learning a bit about everything fits together in Java. A program written in Java will generally be grouped together in a package of files, each of which contains exactly one class (or interface – see #15 below). For accuracy’s sake, it should be noted that there are also situations, for example, when building out a graph data structure in which a Vertex class might be “embedded” within the Graph class, where there can be “inner classes” contained within the larger class.

Access to the classes within the packages and the methods contained within the package’s classes is controlled by the four access-control modifiers that can preface classes and methods.

Delving into how to set up a class’s fields (instance variables), constructor methods, instance methods, constants, and so on is beyond the scope of this post. For more details, see the Oracle tutorial, your favorite book, or your favorite online learning platform.

13) public static void main(String[] args)

When experimenting with Java for the first time (perhaps by hacking through some elementary coding challenges as I did), one quickly notices the lack of a built-in global scope of the kind that Ruby and JavaScript possess. The solution, which soon works its way into your fingers in the same manner that a memorable piano passage or guitar riff does, is to write public static void main(String[] args) within a class and place all the code to be executed in the global scope in it.

Note that executable code can also be placed within threads, which can be started from the public static void main(String[] args) block or another thread. In fact, Java’s ability to handle concurrent programming and its support for high-level concurrency APIs is one of the big advantages it holds over Ruby when dealing with very large collections of data.

14) Use The Keyword static for Class Methods, Class Variables, and Constants

It’s an oversimplification to claim that static methods and static variables in Java are exactly the same as class methods and class variables in Ruby. However, it is true that fields and methods that include the static keyword in Java very often fulfill the same role as class methods and class variables do in Ruby.

Also, when the static keyword teams up the final keyword, they can be used to declare class constants.

To provide an example of typical usage: say we have a Country class and want to be able to keep track of the number of Country objects we’ve created and have a handy method to determine which country is most populous. Also, let’s assume for the sake of this contrived example that having a conversion factor between square miles and square kilometers would be helpful. All of these things are class-level concerns and require use of the static keyword:

import Java.util.List;

class Country {
  // fields (instance variables)

  // constructors, getter and setters, instance methods, etc.

  // this variable would be incremented within the constructor method(s)
  private static short numberOfCountries = 0;

  public static String determineLargest(List<Country> countries) {
    /* BORING CODE */
  }

  static final double SQ_MILES_TO_KM = 2.58999;
}

15) Important Concepts without Clear Equivalents: Interfaces, Generics, and Abstract Classes

Up until this point, there have been enough clear similarities (or dissimilarities) amongst Ruby, JavaScript, and Java to explore the language differences in a comparative fashion. Here is where the paths diverge.

But not quite yet. Java classes, similar to Ruby classes, can inherit from exactly one superclass. The “formula” is <modifier(s)> class SubClass extends SuperClass. In other words, inheritance is very similar. But the conceptual distance between Ruby modules and Java interfaces is quite large. A Ruby module will freely mix in methods into classes, whereas a Java interface is best thought of as a “contract” that precisely lays out what methods must be defined in classes that implement it. However, if a Java interface contains only static and default methods, the functionality is similar to that of a Ruby module. Confused? Check out the interface tutorial for an extended discussion.

Mentioned in passing while talking about the Java Collections Framework, generics (introduced in 2004 with the release of Java 5) allow types to be specified as parameters. This results in enhanced type safety and obviates the need for something called typecasting. If you return to the code samples in points #6 and #7 above, you’ll see generics featuring inside angle brackets: List<String> and Map<String, Integer>. Again, as this is a somewhat advanced topic, check the tutorial or whatever learning resource you prefer for more details on generics, including the concept of wildcards.

Finally, abstract classes deserve a passing mention. They’re similar to interfaces, but more flexible in what kind of fields and methods can be included. Just like interfaces, they can’t be instantiated, but they can be fruitfully subclassed. More info can be found here.

Conclusion

The 15 list items above are meant to provide a quick orientation to Java for those who already know Ruby and/or JavaScript fairly well. While this “crash course” is not in itself sufficient to actually code efficiently and effectively in Java, my sincere hope is that it will help readers transition more quickly into the world of Java and understand the major differences between Java and its more dynamic counterparts.

If you have any suggestions for how to improve this post or just want to say “hi” or “thank you,” please use the contact links found at the very bottom of this page.

Happy Java-ing!

* * * * *