Home



2017/10 - Java and you - The sequel to the blockbusting high-stakes, edge of your seat, trilogy.

I'm intending for this tutorial to be more of a kind of intro to Java for someone who is still somewhat new to Java. You can check many more tutorials here on Oracles page for their own Java tutorials, but this one is intended to be a quick cut through of Java to explain and show examples of the most common code you'll come across when beginning with Java.

I'm going to touch on installing Java first, then move onto some some beginner-friendly stuff first, then gradually move onto more complex Java and providing some resources towards the end of this post. I'll be assuming that you have some programming experience, but not a lot. If you have any suggestions on items to add/reorder, you can reach me at marclaffan@gmail.com.

AND SO IT BEGINS, NOT WITH A BANG BUT with the installation of Java. This is pretty straightforward, vastly more than installing C, so I'm not going to include screenshots. Just go here and download the latest stable version of Java. Once it's installed, open your environment variables (like we did in this post on C) and add a new environment variable called "JAVA_HOME" that points towards your JDK folder, and it to your main path. Open up a new command prompt windows, type "java -version" and hit enter. If you get anything other than:


java version "1.somenumberhere"

Java(TM) SE  Fancy Runtime Environment (build 1.morenumbers)

Java HotSpot For Totes Cool Developers(TM) 64-Bit Fancy Server VM (build 25.icantbelieveitsnotnumbers, mixed mode)

Then something has gone wrong. The wording and versions may change as time goes on, but if it looks roughly like this then you're golden.

Next, we'll want to type up a little program that accepts input, compile it, and finally run it. Open a text editor and type this in:

public class Test{

  public static void main(String[] args){
    System.out.println("test one");
  }
}

And save it as "Test.java". Open your command prompt at the same location and type "javac Test.java" to compile this file, then "java Test" to run it. You should see "test one" print in your console if it worked. Congrats! So what just happened? Well, we defined a class called Test, used the main method to actually run the program, and finally told the program to print "test one" to the screen. It isn't obvious right away, but we used something called a variable to create the text that was printed to the screen. This variable is a type of variable called a wrapper class (It's not reeeeeeeeeally a wrapper class, but forget that detail for now). A wrapper class is the object-equivalent to a primitive data type, which could be something like a letter, boolean or text character (e.g. 1, true or "Hello"). They represent the most basic logical concept that we can have in programming. So we have "basic" primitive data types and more "complex" wrapper classes. The raison d'etre for wrapper classes is that they allow data values to be treated like an object (They also allow autoboxing when using lists and a bunch of other stuff, but we'll get to that later). The following is a list of data types and their equivalent wrapper classes:

primitive -> Wrapper

byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
char -> Character
boolean -> Boolean

The String class (Which is what "test one" was) is not really a wrapper class because it doesn't wrap any primitive data type. Developers tend to use it as if it was a wrapper for a list of char's however, and you'll almost never see a char of Character being used in a program (It would just be inconvenient to type them up, parse them, use them in general, etc). It'll almost always be a String instead (Which is just a list of characters mashed together to make a word or sentence. Like "test one" or "fried eggs are yummy").

So now that we have a basic program working, we can start making things a bit more interactable. Open the file again and type this code into the file. Save it and run it again:

import java.util.Scanner;

public class Test{

  public static void main(String[] args){

    while(true){

      Scanner scanner = new Scanner(System.in);
      System.out.println("Please enter two numbers that you would like to calculate");
      System.out.println("(In the case of division, the first number is the dividend and the second is the divisor)");
      Integer num1 = scanner.nextInt();
      Integer num2 = scanner.nextInt();

      System.out.println("Choose the mathematical function that you want to perform on the numbers " + num1 + " and " + num2);
      System.out.println("1. Addition");
      System.out.println("2. Subtraction");
      System.out.println("3. Multiplication");
      System.out.println("4. Division");
      System.out.println("5. Quit");
      
      int num3 = scanner.nextInt();
      
      switch(num3){
        case 1:
          int additionAnswer = num1 + num2;
          System.out.println("The addition of " + num1 + " and " + num2 + " is: " + additionAnswer );
          break;
        case 2:
          int subtractionAnswer = num1 - num2;
          System.out.println("The subtraction of " + num1 + " from " + num2 + " is: " + subtractionAnswer );
          break;
        case 3:
          int multiplicationAnswer = num1 * num2;
          System.out.println("The multiplication of " + num1 + " and " + num2 + " is: " + multiplicationAnswer );
          break;
        case 4:
          int divisionAnswer = num1 / num2;
          System.out.println("The division of " + num2 + " into " + num1 + " is: " + divisionAnswer );
          break;
        case 5:
          System.out.println("Thank you for your patronage :)" );
          System.exit(0);
      }
    }
  }
}

Holey moley that's a lot of new code. We've introduced quite a few new concepts here, so let's take this apart piece by piece shal we?

import java.util.Scanner;

This line is an import. An import is used when the developer wants to add additional basic functionality to their program, functionality that they don't get by default. For example primitives, classes, and a bunch of other things you'll get by default when you run your program. Java doesn't import everything for you since you really don't need everything for each program/file that you make. If you did import everything, it would unnecessarily slow your whole program down. in our case, we imported the Scanner class that we use later on.

while(true){

This lovely line creates what's called a loop in Java (Specifically a "while" loop). A loop is always followed by curly braces ( { }) and everything inside those braces will be repeated as long as a condition remains true. This particular while loop uses a "true" boolean data value as its argument, so we're essentially telling it to run forever. We could have set it to false (So it never runs at all) or extract the value into a variable reference and put a condition later on in the program that causes the reference to change to false, which would then sets the while loops argument to false (Which would end the loop). You'll see how we actually end this program later on.

There are several other types of loop too, such as for loops, for-each loops and do-while loops that all have their place in Java. 

Scanner scanner = new Scanner(System.in);

This line instantiates (creates) a new scanner object and assigns it to a reference, passing System.in as its argument. The Scanner class is used to takes input from the user when scanner.nextInt(); (Or nextChar(), nextLong(), nextFloat(), nextDouble, etc) is called, pausing the program until the user input a value.

Integer num1 = scanner.nextInt();

This line creates a reference to an Integer, then assigns the next int value that the user enters. We aren't instantiating anything here (If you see the keyword "new" anywhere, something is being created/instantiated) because the scanner class has already captured the input from the user for us. And remember how I mentioned autoboxing before? Java is taking this input value, an int, then automatically boxing it up into an Integer for you. For free!

switch(num3){
        case 1: ...  break;

This is called a switch statement. A switch statement accepts an argument that it applies conditional logic on. The conditional logic consists of a series of case labels, and if a case label matches the value accepted by the switch statement, then that label and all case labels below it will have their functionality used. This concept is known as "fall-through" but it often isn't the desired functionality, which is why you almost always see break labels accompanying case labels. A break label (You guessed it) "breaks" out of the current loop. Try removing one of the break labels, then executing conditions for that case label. You should see weird things happening, like the program showing you both the addition and subtraction when you ony asked for the addition. Wha happens if no case labels matches the parameter to the switch statement? Well nothing, unless to use the default label at the end of the case labels to define what should happen if such a situation arises.

System.exit(0);

This is how we're ending our program. Technically we aren't breaking out of the while loop at all, we're just telling the program to stop itself completely. We could use break to stop the loop instead too!

 

So that was a bit of a crash-course in a lot of the basics in Java. We still have plenty of ground to cover though, so let's GIT GOIN'!

Exceptions

You've probably thought that this program could easily be broken if you were going to sell it to Facebook tomorrow morning. Just think; You've set up your laptop in front of Mark Zuckerberg and he's promised to pay you millions for your new start-up "Calculator Inc". You compile the program, run it, and turn your laptop around to face Mr. Facebook. He looks at the command prompt in front of him for a moment before typing "I am Mark Zuckerberg, kneel before me Windows" and "Muhahahaha!", then hitting the enter key. But oh no! Your program crashes faster than bitcoin will in 2022 (It better or so help me god...). So what went wrong?

The scanner object accepts an int, but Mark Zuckerbillionaire entered a list of characters! You can't store data values in the wrong reference type. If you try to type "String s = 1;" or "boolean b = 15", it won't work because the reference wasn't meant to hold that data format. This is known as a strong typesystem, meaning that Java is strongly-typed (As opposed to loosely typed, that will allow you to store whatever you want in a generic variable. There are trade-offs to both these approaches).

The scanner class reads, and expects, an int. Since Mark entered text, the program tried to put characters into the reference for Integers and the program blew up. We can't force users to input the correct data, as sometimes they just won't know any better. Instead, we'll be using Exceptions to fix up a few problems with this program. You might have also noticed that when the user selects an option, they could also enter a number that falls outside the range covered by our case labels. We'll cover this too:

import java.util.Scanner;
import java.io.IOException;

public class Test{

  public static void main(String[] args){

    while(true){
      System.out.println("");
      Scanner scanner = new Scanner(System.in);
      System.out.println("Please enter two numbers that you would like to calculate.");
      System.out.println("(In the case of division, the first number is the dividend and the second is the divisor)");
      
      Integer num1 = 0;
      Integer num2 = 0;

     
      try{
        num1 = scanner.nextInt();
        num2 = scanner.nextInt();
      }
      catch(Exception e){
        System.out.println("Please enter a number, no other kind of digit.");
        continue;
      }

      System.out.println("Choose the mathematical function that you want to perform on the numbers " + num1 + " and " + num2);
      System.out.println("1. Addition");
      System.out.println("2. Subtraction");
      System.out.println("3. Multiplication");
      System.out.println("4. Division");
      System.out.println("5. Quit");
      
      int num3 = 0;

      try{
        num3 = scanner.nextInt();
        if(num3 < 1 || num3 > 5){
          throw new IOException();
        } 
      }
      catch(IOException e){
        System.out.println("Please enter a number between 1 and 5.");
        continue;
      }

      catch(Exception e){
        System.out.println("Please enter a number, no other kind of digit.");
        continue;
      }

      
      switch(num3){
        case 1:
          int additionAnswer = num1 + num2;
          System.out.println("The addition of " + num1 + " and " + num2 + " is: " + additionAnswer );
          break;
        case 2:
          int subtractionAnswer = num1 - num2;
          System.out.println("The subtraction of " + num1 + " from " + num2 + " is: " + subtractionAnswer );
          break;
        case 3:
          int multiplicationAnswer = num1 * num2;
          System.out.println("The multiplication of " + num1 + " and " + num2 + " is: " + multiplicationAnswer );
          break;
        case 4:
          int divisionAnswer = num1 / num2;
          System.out.println("The division of " + num2 + " into " + num1 + " is: " + divisionAnswer );
          break;
        case 5:
          System.out.println("Thank you for your patronage :)" );
          System.exit(0);
      }
    }
  }
}

The bolded parts of the program are the parts we've changed. We first need to import an exception class that isn't covered by the java.lang (Default) package that comes with every Java program (We also added an empty println statement to make the output more legible). We extracted the user input from their original references and now assign the input in something called a try catch block. A try catch block attempts to execute, often risky, lines of code in a block that is marked as a try block. If anything bad happens (Like an exception is thrown), it won't immediately crash the program as long as we have attached a catch block that covers that particular type of exception (I'll cover how exception types work in the objects section). If we don't cover the exception, the program will fail as it normally would. We can also throw our own exceptions as seen with "throw new IOException();". We know when we don't want some kind of situation/behavior state to occur. In our case, we want the user to know that they need to choose a valid option. So we throw an IOException, which we later catch, and use it to inform the user that they need to enter a number within a specific range. One last thing worth mention is that you should catch more specific errors earlier/higher up in your catch blocks. If your exception is caught in a catch block that is meant to cover all of the general exceptions that aren't covered by our more specific catch blocks, then we will end up responding incorrectly to our exceptions. If this doesn't make sense now, then don't worry, it will soon.

Objects

Objects are the basis of object-oriented programming languages. For the purpose of this introduction, they are best described as tangible concepts that can sometimes be realted to real-world objects. Consider the following:

 

 

(I'm actually writing this and saving it as I go along, so you're gonna have to be patient while I finish and clean stuff up. Last updated 21st June 2018, with a good chunk of basics covered. You can pretty much ignore everything below this line, aside from the frameworks and Books sections)

Topics: Object visibility, inheritance, basic data type manipulation, basic and advanced data structures and collections, exceptions, operators (modulus), this, keywords, objects, loops, control flow, local/class/instance variables, arguments and references, constructors vs factories,interfaces, abstract classes, inner classes, anonymous classes, streams and serialization,

Frameworks 

If you're thinking about working with Java in industry, you'll likely be using something like REST, SOAP, Play or Spring. There are plenty of opportunities that do not use these frameworks (Android development for example), but the majority use at least one of them in some way. Unfortunately I'm not going to go into detail on these frameworks in this post as doing so would betray my original intentions for its content, but I mention them to let you know what else you could be studying and upskilling in when learning Java.

Books

Head First Java should be your go-to book for learning Java if it's your first attempt at learning how to program software. I have a review of Head FIrst Java here if you'd like to check it out, but if it doesn't sound like your kind of book, I've also seen people recommend Thinking In Java as a good introductory book too. More advanced Java books (For when you actually have a job that involves Java) would include Effective Java (Review here), Java Concurrency in Practice, and Java 8 In Action if you're working with mroe modern Java. I cannot recommend the "For Dummies" series of books for any programming language, as I've never seen one that I liked enough to completely finish. They just seem to be walls and walls of text that never really goes anywhere... in other words, they're not ideal if you want to stick out a learning plan! They work well if you want a massive reference book, but honestly don't even try to learn much from them. There are far better ways to learn Java and those books feel like they belong in the nineties.