Java

Introduction

Two basic questions to begin the discussion, (1) What is Java and (2) where is it used? Java is a platform, it has a (1) programming language (2) set of built-in libraries and (3) a virtual runtime environment or JVM; it’s short for Java Virtual Machine, some people also call it JRE which is short for Java Runtime Environment.

The Language

The Java language is not so old, as far as programming languages go. James Gosling worked on it in the early part of the 90s and released it in 1995. It is barely 22 years old at the time of this writing. Whereas the C language is almost 47 years old, C was released sometime in 1969.

If you have background in other languages such as JavaScript, C++ or C#, Java may look familiar because all of them share some semblance with the C language. By the way, Java is in no way related to JavaScript. JavaScript is not a derivative of Java nor was it inspired by Java. Java is related to JavaScript the same way as car is related to carpet. They just have common letters in their names.

Java is a high-level language. It provides a fair amount of abstraction above the physical machine that it runs on. But you can dive down and perform some decent low level operation on the bit level if you want to. It is also a general-purpose language. It wasn’t designed just to program web applications or anything specific. It is not a domain specific language the way Sinatra (Ruby) or Express (NodeJS) is. You can build pretty much anything you can imagine.

Java Virtual Machine

Java is a compiled language. Like other languages such as C or C++, you will write your programming instructions in a source file using a somewhat English-like language. This source file will be compiled into an object file. An object file contains a set of instructions that a machine can understand and execute. In Java, an object file or executable file is called byte code. The byte code is what a Java Virtual Machine, or JVM, can execute.

Byte codes, however, cannot be executed directly by the operating system (OS). They do not contain the same instructions nor are they structured like the regular EXE files or other forms of portable executable. The OS does not know what to do with byte code. They should be executed within a virtual machine. The Java runtime engine (JRE) is such a machine.

Java is portable at the byte code level. You can write and compile your program in one OS, say Windows and run it on another OS without requiring any modification. Sun Microsystem, the former custodian of the Java technology, came up with the WORA slogan during the early days of Java, it stood for Write Once Run Anywhere.

java work cycle

The basic idea is to write the program source in a file that has a .java extension. A compilation process happens which results in a byte code (.class file).  The byte code is executed within a Java runtime engine (JRE). A JRE is also known as a Java virtual machine (JVM).   Each operating system has their own version of the virtual machine but what runs on one virtual machine, will run on all.

Editions

You can use Java to build applications for a variety of architectures. Java comes in several editions. The Java SE (Java Standard Edition) which is the topic of this book, can be used to build Desktop applications. Java Enterprise Edition (Jave EE) can be used to build web applications, web services, high availability back-end processes, etc. Java Mobile Edition (Java ME) can be used to build apps for mobile or embedded devices. Although for mobile devices like Android phones/tablets, you might want to consider the Android SDK. By the way, the native language for the Android platform is Java.

Version history

Version Name Code Name Release Date
JDK 1.0 Oak January 1996
JDK 1.1 (none) February 1997
J2SE 1.2 Playground December 1998
J2SE 1.3 Kestrel May 2000
J2SE 1.4 Merlin February 2002
J2SE 5.0 Tiger September 2004
Java SE 6 Mustang December 2006
Java SE 7 Dolphin July 2011
Java SE 8 March 2014
Java SE 9 September, 21st 2017
Java SE 10 March, 20th 2018

NOTE: JDK 11 is on early access at the time I was revising this doc, so it’s not yet included here.

Setup

The JDK is available for macOS, Windows and Linux. There are pre-compiled binary installer for each of these platforms and you can get it from the Oracle download page for Java.

If you’re on macOS, double click the dmg installer and follow the prompts. It takes care of everything, including the system path and classpath.

If you are on Windows, double click the installer and follow the prompts. You will need to update your Environment settings so that the the JAVA_HOME/bin folder is included in the system path. You will also need to include a CLASSPATH definition in your Environment Settings.

If you are on Linux, specifically Ubuntu, you may have installed your JDK in the past using a PPA from the webupd8 team; well, at the time of this writing, the webupd8 team hasn’t released anything for JDK 11, in fact, even the JDK 10 isn’t out yet. So, for the time being, you may have to install the new JDK using either tarballs or RPM. The following example shows the terminal command on how to install Java 9 on the Ubuntu, or any of its derivatives.

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java9-installer
sudo update-alternatives --config java

Hello World

All programs in Java have to be written inside a class construct, there’s a long-winded, but good explanation for that, however, I don’t think it’s best to deal with that reason this early because it will get in the way and it’s not that important — at least for now. So, let’s accept it that it’s just the way it is and we need to get used to it early on. A class construct looks something like this

class Hello { // (1) (2) (3)

} // (4)

(1) The class definition is started with the keyword class. Like many programming languages, Java has a list of special words that have special meaning to its compiler. The class keyword is one of these special words (also known as reserved words)

(2) A class must have a name or an identifier. This name is something that you, the programmer, should come up with. This class was given the name “Hello”

(3) Right after the class name, follows an opening curly brance. This marks the opening of the class definition

(4) Lastly, is the closing curly brace. This marks the end of the class definition. It is important to remember that all curly braces comes in pairs. Where there is an opening brace, there should be a corresponding closing brace

To print out the string “Hello World” into the screen, we need to use a statement that can actually do the printing to the screen. There are quite a few statements that can accomplish this task, but the simplest would be the println statement. In code, it looks like this

System.out.println("Hello World");

It is quite tempting to try and understand the structure of this innocently looking statement, but that will lead us to discussions of the standard Java library, the System class and its nested classes — we’re not yet ready for that. The only things we want to take away from the example are the following;

The last hoop we need to jump before we can put this small example together is the business of Java functions . An executable statement, like println, cannot be simply written inside a class — not just anywhere at least. In the following code example, the println statement is in the wrong place. So, that code won’t work

class Hello {
  // THIS WILL NOT WORK
  System.out.println("Hello World");
}

A statement like println, has to be written inside a function. A function is a named collection of statements and it looks something like this

int doSomething() { // (1) (2) (3)
  // STATEMENT
  // STATEMENT n ...
} // (4)

(1) The word int in this line is a return type. A function has to return something, in this case it is returning an int (integer)

(2) A function, like a class, needs a name. The programmer has to come up with this name, in this example, the name is doSomething. Unlike a class name, a function name has to be appended by open and close parens

(3) Right after the parens, comes the beginning of the block which is marked by an opening french brace

(4) Remember that braces comes in pairs

Java folks don’t use the term “functions”, they call it “methods”. You should get into the habit of calling them that as well

Okay. Finally, we can put the example together. Listing 4-1 shows the full code for the Hello example.

Listing 4-1 Hello.java

class Hello { 
  public static void main(String []args) {
    System.out.println("Hello World);
  }
}

In listing 4-1, the println statement is inside a method called main. For now, ignore the other words you see in this method e.g.t public, static and void, you can even ignore the words inside the parens (String []args). We will discuss their details soon enough. What’s important to know are the following;

In order for you to follow this exercise, you will need to do the following

  1. Create the source file and name it “Hello.java”
  2. Open the source file using a programmer’s editor and copy the contents of listing 4-1 into it
  3. Compile the source file using the Java compiler
  4. Run the resulting byte code by passing it as an argument to the JRE

To compile the source file, run the following command

javac Hello.java

To run the resulting byte code, use the following command

java Hello

If you followed everything to the letter, you should see the “Hello World” message printed on the screen.

Program Elements

When you are learning a foreign language, you probably started the parts of its speech, what kinds rules governs them, how you can put things together and how are they punctuated etc. When learning a programming language, we will have similar concerns. We need to learn what are the parts, how they are organized and put together.

Statements

They are the equivalent of sentences in the English language. These are executable statements in Java. Statements are terminated by a semicolon. In our earlier example, you have seen System.out.println(“Hello World”); - such is an example of a statement. Not all statements are as simple as that, some statements may contain multiple expressions joined by multiple operators

Comments

Comments are ignored by the compiler. It’s a good way to document program code and it can benefit other people who reads your code. It can even benefit you. Comments allows us to dump our thought processes and intentions at the time of writing the code. There are three ways to comment codes

// THIS IS A COMMENT

A single line comment, sometimes called an inline comment. The compiler will ignore everything to the right of the two forward slashes until the end of the line

/*
Statement here Another statement */ This is the C-style comment. It is called that because it came primarily from the C language. You can use this multi-line style to comment multiple lines of statements

/**
   Statement here
   Another statement
*/

This is almost the same as the C-style multiline comment. This type of comment though, can be used to generate Java API style documentation

White space

Java is tokenized language, it doesn’t care about white or blank space, you can write your code like this

class Hello { public static void main (String [] args) { System.out.println("Hello\n");}}

Or like this

class Hello { 
public static void main (String [] args) {
System.out.println("Hello\n");
}
}

The compiler doesn’t care. So, write your codes for the benefit of humans who may be unlucky enough to maintain our programs. Forget the compiler, it doesn’t care anyway about spaces anyway. Use white spaces to beautify the code and make it extremely readable, something like this

class Hello { 
  public static void main (String [] args) {
    System.out.println("Hello\n");
  }
}

Blocks

Oftentimes, you may need to write a bunch of statements and you will need to group them together. Blocks allow us to do just that. The lexical symbol for blocks are a pair of curly braces. Blocks are used by classes, interfaces and methods. Occasionally, they are also used to define static and instance blocks, these last two are as common in use as the first three, but you may need them from time to time.

Variables

A variable is something that we use to manipulate data, or more precisely a value. Values are things that you can store, manipulate, print or push or pull from the network. For us to be able to work with values, we need to put them inside variables.

String name;

The above statement declares a variable named “name”, supposedly to hold the value of a person’s name. In Java, when we declare a variable we must tell the compiler what kind of value it is expected to hold. In this case, it’s a String value.

name = "John Doe";

The statement above defines the “name” variable, we assigned it the literal String value “John Doe”. The assignment of value was facilitated by the equal sign (assignment operator). The declaration and definition of variables could be done as a two-step process, as you have seen above, but it doesn’t have to be. The declaration and definition can be written in a single statement.

String name = "John Doe";
int age = 35;
String email = "jdoe@gmail.com"

The concept of variable as they relate to values might be easier to grasp if you visualize the variables as some sort of a named location and the location is a box, the contents of which, holds the value

variable rep

Operators

Operators are easy to grasp because what they do will look immediately obvious. They behave like how you would expect them to. There are various kinds of operators in Java, some you can use for arithmetic, some are used for testing equalities (or inequalities) and some are even used for low level data manipulation

assignment arithmetic unary equality and relational conditional bitwise and bit shift

Methods

Methods aka functions are a collection of executable statements. Java programmers don’t refer to these as functions so you better get used to calling them methods. Anyway, these collections of statements are packaged as one unit and whenever you need to execute those collection statements, you only need to invoke the name of the method. Methods may or may not return values, they may or may not also accept arguments.

Listing 12Listing 12-3.1

public static void main (String []args) {
}

The method as shown in Listing 12Listing 12-3-1 accepts arguments, an array of Strings to be specific

Listing 12-3.2

int getSum(int a, int b) {
    int result = a + b;
    return result;
}

The method shown in Listing 12-3-2 accepts two integer arguments and returns an integer result

Classes

The class is top level structure in Java, there is no higher organizing entity . It is a collection of variable and method declarations. When classes are instantiated, objects are created as a result, this is the reason why classes are sometimes called object factories

Listing

class Person {
   String fname;
   String lname;
}

Person p1 = new Person()  ;

Listing 12-3.2 defines a new data structure called Person by declaring a class with the same name. It has two properties, “lname” and “fname”, for last name and first name respectively. An object named “p1” is created from the definition of the Person class

Keywords

These are special words, they have specific meaning to the compiler and as such, you will not be able to use them as an identifier. There are several reserved words in the Java language. You cannot use these words in your program because they have been, well, reserved. They mean something special when the compiler sees them in your program.  Best not to use them as class, method or variable name.

keywords description
byte, short, int, long, float, double, char, boolean, void These are primitive types of Java. Though void is not listed as one of the primitive types, it is actually part of the Java type system
while, do, for if, else, switch, case, default, break, continue These words are used to alter program flow, some of them are used for branching and some are use for looping
class, interface, enum these are used to create custom data types or user defined typed
public, private, protected, package, import access modifiers and package management
extends, implements use for class and interface extensions — inheritance
try, catch, finally, throw, throws Java’s exception handling keywords
this, super keywords to manage object instances from within objects
new used to create objects (instances of a class)
return used from within methods to return a value to the caller
abstract, final affects polymorphism
transient, volatile, synchronized affects threading codes in Java
native used in methods, when a method is marked as native it means it will be implemented using JNI (Java Native Interface)
static used for memory management. When methods or variables are marked as static, it means it belongs to the type (class) rather than the instance (object). Classes can also be declared static
instanceof used for testing an object if it of a specified type
assert used to declare an expected boolean condition in a program. This is used for testing pathways in your code
strictfp restricts floating-point calculations to ensure portability
var a new type keyword which was introduced in Java 10. You can use this to declare local variables. When var is used, there is no more need for any other type information. This is Java’s attempt for type inference

It’s not important for you to remember all the keywords, but in time, for sure, you will commit quite a few of them in memory. What’s important to remember is that you cannot use keywords as identifiers. We’ll discuss identifiers in the next section.

Identifiers

Identifiers are programmer defined names. There are a couple of things we need to name in Java e.g. classes, variables, methods, interfaces and enums. There are some rules we need to keep in mind when naming identifiers. These are

  1. It can’t be a reserved word
  2. It can’t start with a number, it’s alphanumeric but the first character can’t be a number
  3. It can’t contain special characters, but you can use the dollar symbol and the underscore. It’s best to stay away from the dollar symbol though, Java uses that to name generated byte codes from inner classes

These are the hard rules, the soft rules are entirely up to your (or your company’s) coding guidelines. Some examples of these soft rules are

  1. if you’re going to follow Hungarian notation, be consistent with it. If you will follow Pascal casing, be consistent with it, don’t mix and match
  2. make the names of the identifiers descriptive
  3. keep the length of the identifier reasonable, you really don’t want to type (and read) a 100-char variable name

Variables and Data types

A programming language like Java relies on its ability to create, store and edit values, these values needs to be manipulated arithmetically or by some other means. Java allows us to work these values by storing them in variables, so put simply, a variable is a named storage for values or data. A variable is created using a twostep process, first, you need to declare a variable, like so

int num;

In the statement above, “num” is the variable and “int” is what we call a type. A type determines the variable’s size in memory and what kinds of operations you can do with them. In our example above, you can add, multiply, divide or subtract from “num” because Java defined the arithmetic operators to work numeric types like “int”.

The next step after declaring a variable is to define it. Defining a variable assigns a value to it.

num = 10;

In the statement above, the integer literal “10” is on the right-hand side of the equal sign which effectively assigns its value to the variable “num”.

Alternatively, we can declare and define a variable on the same line, like so.

int num = 10;

After a variable has been declared and defined, you can change its value at any later time.

int num = 10;
num = 20;

Primitive Types

Java has 2 kinds of data types, primitive and Reference. The primitive types are the ones that are built into the language, Java has 8 of those.

What you cannot do however, is to assign a value to “num” that isn’t an “int”, like so.

int num = 10;
num = "Hello";

We cannot assign the String “Hello” to num, because we’ve already declared it as an “int” type. Java, being a strongly typed language, does not allow type coercions like this.

Type Size in bits Sample literal values
byte 8 -128 to 127
short 16 -32,768 to 32,767
int 32 2,147,483,648 to 2,147,483,647
long 64 -9,223,372,036,854,775,808 to 9,223,372,036,854,807
float 32 1.23e100f, -1.23e-100f, .3f, 3.14F
double 64 1.23456e300d, -1.23456e-300d, 1e1d
char 16 0 - 65535 or \u0000 - \uFFFF
boolean 1 true, false

Java is a statically typed language; this is why we need to declare the types of variables before we can use them in our program.

Reference Types

A reference type value is anything that is not a primitive. Reference types values are created by instantiating classes, which means, reference type values are objects. Some examples of reference types are String and java.util.Date. When you create a class or an interface, you are creating a new reference type.

Creating a reference type value is not that much different from creating a primitive type value, it also involves the two-step process of declaring the variable and then defining it, for example.

Date date;
date = new Date\(\); 

In the statement above, the variable name is “date” and the type is “Date”, more specifically, it’s “java.util.Date” which is one of the classes in the Java platform that comes with the installation of the JDK. The date object is created by using the “new” keyword plus the name of the class (Date) with parens. The name of the class plus parens is called a constructor method. This will be discussed in the section titled “Classes and Objects”. When this statement finishes, the “date” variable will contain a reference to the location of a newly created Date object.

Constructors are not always empty, sometimes, you can pass values inside the parens, see the example below.

String hello = new String(“Hello”);

The statement above creates a new String by passing a series of characters enclosed in double quotes to the String constructor. Strings values are very common in programming and are quite indispensable, but despite that, Java did not make it a part of the primitive types - String is a reference type. Another way to create String objects is shown below.

String world = “World”;

In the statement above, we did not need to call the constructor of String to create a new object, we simply assigned a String literal the char variables “World”.


Revision history

version date description
1 July 19, 2012 First draft. It was encoded in Latex, and released as PDF
1.1 April 7, 2013 Moved to markeddown format
1.3 May 2, 2015 Used as material for LeanPub, Java Lessons
2 October 1, 2017 Revised for use in Apress book (Learn Android Studio 3)
3 June 4, 2018 Rewritten. Removed the detailed discussions, it will now follow the format of Cliff’s notes