Getting Started with Java

Java Overview with Relocatable JDK 8

This is to enable a Java™ newcomer to get started, using either Linux™, MacOS™, Windows™, or a flavour of Unix™ — wherever Java runs. In addition, it covers how to get a relocatable JDK8 running without Administrator privileges on Windows. We avoid JDK9 since it is larger, less used, and is not a requirement for learning the Java language.

Incus Data Supplementary Material

Types, Values and Variables

PREREQUISITES — You should already…
  • have experience in some other programming language;
  • know how to use the command line (Command Prompt, PowerShell or a POSIX shell).

Introducing the Java Platform

java-logo

Java™ has been around for centuries; or so it feels to some of us. From its public re­lease in 1995, it has grown to be the most popular programming language in use, as per the TIOBE index (for several years running, no less). For some, it has become the new COBOL, arguably in no small part due to IBM®’s involvement with Java, its many donations, and the Java Platform’s con­se­quent adoption in many financial in­sti­tu­tions and multi-national enterprises.

Java is less popular on POSIX-like operating systems like Linux and flavours of Unix, but the pop­u­lar An­droid™ operating system’s Linux-based kernel does sport a Java-like API, much to the chag­rin of Sun® (bought out), and sub­se­quent­ly Oracle®, who unsuccessfully sued Google®.

Java is an umbrella term for “the world of Java-related languages, technologies and frameworks”, as you may witness on the Java Platform Standard Edition 8 Documentation page. To describe it as HUGE is an understatement; quite a burden to bear for such a tiny name, which for many people used to be slang for “good coffee from a small Indonesian island” .

Platforming

Ubiquitous references to “Java Platform” suggest that, from a developer’s perspective at least, Java is not just a language, but a whole infrastructure of related technologies. For all in­tents and purposes then: an operating system. A virtual operating system, using a virtual CPU called the Java Virtual Machine (JVM).

Virtual Machinery

Java code is translated to virtual machine code instructions (also called “bytecode”), following the JVM (Java Virtual Machine) specifications. This is equivalent to the .NET Framework’s IL (In­ter­me­di­ate Language). Other languages, other than Java, also target the JVM — noteably Scala and the hot new favourite: Kotlin, courtesy of Mother Russia.

The VM bytecode is translated on the fly to the native machine code of the host computer, using JIT compilation (Just-In-Time compilation) techniques. Although the start-up might be a tad tardy, Java programs run quite fast.

All things being equal, this means that a compiled Java program will run on any plat­form sup­port­ed by a Java Virtual Machine. At minimum, the Java Runtime Environment (JRE) is required — the Java Development Kit (JDK) part is necessary to compile Java, package programs, and create documentation.

Java programs can be compiled ahead of time, to reduce the start-up costs.

Garbage Collection Time

Java is a garbage-collected language, which means programmers only allocate memory; they are never required to release the memory. The automatic reclamation of memory is called “garbage collection”, and is based on maintaining a count of references to allocated objects; when the re­fer­ence count is 0, the garbage collection process will reclaim that memory for reuse.

It can be get a bit more complicated than that, depending on what your program does, but ge­ne­ral­ly, it “just works”, and memory leaks are the least of your concerns.

Write Once Run Anywhere… Well, Mostly, If You Try Hard

This is a very common Java refrain, and mostly valid for web development, as long as you use an Oracle-certified application server, or you write JavaFX hybrid programs. For real-world app­li­ca­tions, it depends entirely on the kind of application. In practice it turns out that, if you are care­ful, you can write most code, so that it mostly runs on most JVMs (with the right version, of course).

Most substantial Java programs, even Netbeans, have to “drop down” to the host operating system on occasion. Interfacing with native code is possible, and almost mandatory for certain types of applications.

Almost all programs supply some native executable “launcher” to better integrate with the op­er­at­ing system, but none are official, except of course, for java and javaw, which are not exactly “user friendly”.

Frameworks Galore

Sounds better than “a superlative mind-numbing collection of libraries, not even taking third-party contributions into consideration”. To help unravel this veritable heap, the libraries are col­lected in related categories, or frameworks.

Compact Profile

For Java on embedded systems, or small devices, a set of classes without GUI frameworks is available. This is enough to write typical applications not involving graphics or enterprise fea­tures. It even includes scripting and JDBC database classes.

Java SE

For larger applications, but not enterprise applications, the Java SE (Standard Edition) API adds GUI classes, with Swing arguably the most popular.

JRE Classes

This is the set of classes available by default when the Java runtime is installed on client machines. It is a superset of the Java SE classes, because it includes Java Web Start, Applets (deprecated in Java 9), and JavaFX.

JDK Classes

Apart from the Java EE (Enterprise Edition) classes, this is the biggest set, because it must not only include all the above, but also add development-related classes and tools.

Java Language Features

We will not attempt to cover even a fraction of the whole Java Platform, since our focus, at least here, is the Java pro­gram­ming language part of this massive ecosystem. Application of a pro­gram­ming language re­quires tools, structure, conventions and applications — all of which we will address, but without any IDEs (Integrated Development Environments) to blur the details.

General Features

Much of the Java syntax borrows from C++; it was designed to be easy for C++ programmers to learn Java, not because its syntax is ground-breaking or elegant. Many parts of the Java language will appear familiar to C++ programmers; some parts may look familiar even to C, C#, JavaScript, Perl and PHP programmers, because they all borrowed some features from C.

Blocks

Braces are ubiquitous — delimiters for the venerable block structure, in lieu of begin and end keywords from other programming language bran­ches. Blocks can be compound state­ments, function body blocks, class blocks, amongst other manifestations. We can rightly say that Java is a “block-structured language”.

Every block introduces a new scope — an area of visibility with respect to some user-defined id­en­ti­fier. Since blocks can nest, scopes can nest. Identifiers defined in an outer block, are visible in nested blocks, but can be hidden by re-defining the same name.

Source Code

Source code files can be (and in our opinion, should be) UTF-8 encoded, even though that is not the default encoding anywhere in Java. This means you should add the -encoding utf8 option to the Java compiler (javac options).

The language is case-sensitive, and free format. As a result, whitespace (spaces, tabs, newlines, carriage returns, form feeds) serves no syntactical purpose, other than to separate tokens which otherwise would have been ambiguous. The burden is on the programmer to ensure readable code, and to consistently indent nested blocks.

Not even the javadoc tool defaults to UTF-8 encoding in the HTML it generates. It too re­quires ex­pli­cit switches: -encoding utf8 -docencoding utf8 -charset utf8!

Statically Typed

Types must be known at compile time. No Java syntax allows for static type inference along the lines of auto in C++, or var in C#, so redundant type names in declarative statements are still de rigueur.

Java is a strongly typed language, which has nothing to do with the force required to press keys. Java has specific rules regarding implicit and explicit type conversions (type casts) with a cast op­e­ra­tor. Object-oriented implicit narrowing (up casts) to a base class (super class), and inter­faces are supported.

Reflection is supported in Java via the java.lang.reflect API, which allows for dynamic loading for libraries, or even dynamic resolving of methods at runtime. But the language is, in spirit, still a statically typed language.

Native Code Interfaces

It is possible, though rather convoluted, to interface with native C/C++ libraries using the Java Native Interface (JNI). One unfortunate step in the process, is to create wrapper C/C++ code, even when calling API functions in the operating system libraries.

A newer, and highly recommended option, is Java Native Access (JNA), which does not require you to write interface code. This means you can call, for example, Windows Kernel32.dll API functions without writing C/C++ code.

Properties & Overloaded Operators

Neither are supported in Java, just in case you come from a C# or C++ background. In Java ye shall write yer “getters and setters” (like C++), and call functions to perform arithmetic on your custom types. Operators, after all, are basically compact notations for calling functions, most commonly, built-in functions. Function or operator: both are “called”, both take arguments (op­er­ands), both return results; the difference is notation. You lose out on notation only, not ability.

Abstraction Mechanisms

From this point, Java establishes itself as a modern object-oriented language, running on a vir­tual machine (JVM), supplied with a huge framework of packages and tools.

Defiantly Object-Oriented

Java is unashamedly object-oriented; even proudly “doing the Right Thing™”. Apart from com­ments, and some di­rec­tiv­es, everything must be inside a class structure (block). For simpler pro­grams, which do not require OOP features, several static functions can be created in the same class, in which case the class acts more like a module. You may even have several such “modules” in the same application (not to be confused with the modules introduced in Java 9).

Like C#, Java does not support multiple inheritance in line with C++, but they both can im­ple­ment multiple interfaces, which are special classes with no fields (data members). An object of a class that implements several interfaces, can be implicitly cast to any interface.

One can happily use all modern object-oriented features in Java: encapsulation, inheritance, in­ter­face in­he­ri­tan­ce, and polymorphism via virtual functions (oops: methods). By the way, we will use the term “function” when we discuss the syntax and behaviour, and “method” when we em­pha­sise the object-oriented aspects.

Generic Generics

Java was relatively late to the generics party, but this has been available since 2004, so it has seen some use. Abstractly, this involves creating template classes, from which types can be in­stan­ti­at­ed, re­plac­ing parts of the template with specifics. Methods can also be written as “generics” functions.

So, a List<String> is a type instantiated “on the fly”, so to speak, from the generic List<?> in­ter­face type. This, however, is just an abstraction — Java, unlike C++, does not really physically copy source code and replace parts of it.

NOTEGeneric is Not What it Used to Be

The term “generic”, as used in languages that have some form of template-based pro­gram­ming paradigm, has no relevance to how the term has been applied in the past. We used to talk about “generic code” and “generic functions” as good coding practice to write wide­ly-ap­pli­cab­le, and reusable code, within the framework of any language, including C. Today, you have to be cognisant of the context in which the word is used; particularly in C#, C++ and Java, all of which have generics. Thus writing a “generic function” may have a different meaning, de­pend­ing on the topic at hand.

Template-based programming is historically a mechanism to enhance performance in statically typed languages, where the alternative would be constantly converting types.

Fashionably Functional

In line with a common trend, Java also supports some aspects of functional programming, mostly by virtue of lambda expressions (anonymous functions), and the ability to return or pass methods. But functions are not “first class citizens” (a moronic term, if ever there was one), or “function objects” in Java.

Framework/Package/Namespace/Directory Scaffolds

One might argue that part of Java’s success is due to its enormous API, which many of a certain per­su­a­sion may appreciate. Java Platform, Enterprise Edition (Java EE) adds even more libraries for fault-tolerant, multi-tier software running on an application server, i.e. web applications.

The Java language itself provides syntax and structure, but has no built-in functions. It does have a number of primitive types, which are not really object-oriented, but they can be “wrapped” in corresponding classes. Learning Java implies also learning several core classes, or basically, most of the Java Platform Standard Edition (SE) classes. Some classes are application-specific, and which to learn depends on your needs.

Libraries are packaged; Java’s equivalent of namespaces, which manifests as nested di­rec­to­ry structures — which you may forget only at your peril.

Build Tools & Launchers

Because of Java’s intricate use of class path lookups, and the preponderance of nested directory structures for packages, many Java-specific build tools are available. Arguably the three most popular are: Apache Ant (with Apache Ivy), Apache Maven, and Gradle (based on Groovy, and used to build Android™).

Unless you have no choice, or really like XML, or only use an IDE, we suggest you use Gra­dle; it has the smallest learning curve, does not use XML, and is concise. Maven, however, is prob­ab­ly more common in open-source projects. Of course, nothing prevents you from using a tra­di­tion­al Make tool, like GNU Make.

The closest a Java program gets to being an executable, is by packing it with the jar tool in a struc­tur­ed Zip file with a .jar extension. Even then, invoking the Java runtime to execute your Java program can involve complicated class path incantations, especially for larger programs with many library dependencies. Most programs provide some sort of “wrapper” script or pro­gram to “launch” such Java .jar files more conveniently. One open-source option is Launch4j, which can wrap your application as a light-weight .exe.

Get Your Java On

Once you have some high-level perspective on the exhilarating Java experience awaiting you, it is time to get yourself a Java Software Development Kit (JDK) for your platform.

JDK SE on Windows

The obvious and official method is to download the Java SE Development Kit 8 and install it. For Windows, you can choose the 32-bit, or 64-bit, JDK. After installation, you can find the location of the JDK with the following Command Prompt command:

for %F in (javac.exe) do @echo. %~$PATH:F

In Windows 10, you can also try: ‘where javac’.

The base directory (e.g. C:\Program Files\Java\jdk1.8.0_152) can be copied anywhere, since that is the complete JDK. You can even uninstall the JDK afterwards, set your JAVA_HOME and PATH environment variables to where you copied the JDK, and you are good to go.

Alternatively, you have several options, including jdkPortable, but it is mostly for use by other portable applications. You might use it to download and install (copy, really) the JDK SE for you, which by default will go into a ‹base\CommonFiles\JDK64 directory. This directory, again, contains the complete JDK.

If you want to do it the hard way, check out these instructions on Stack Overflow. This ba­si­cal­ly in­volv­es ex­tract­ing the JDK installer .exe with 7-Zip, finding the tools.zip file inside, which you extract somewhere, and then running a Command Prompt command in that directory, to convert .pack files to .jar files:

for /r %F in (*.pack) do .\bin\unpack200 -r "%F" "%~dF%~pF%~nF.jar"

The process is similar for JDK 9, if you feel so inclined, except the tools.zip is easier to find, and there are fewer files to unpack. It is significantly bigger though.

If you place the following batch file in the JDK base directory, it will set the JAVA_HOME and PATH environment variables automatically. It is designed to be called from within a current Command Prompt session, or more likely, from the accompanying rxjdk-cmd.cmd batch file.

rxjdk-env.cmdRelocatable JDK Environment
@echo off & setlocal enableextensions
:: Set PATH for Java JDK and utilities. It only sets the environment.
:: Use `rxjdk-cmd.cmd` to open a new Command Prompt, with the settings
:: from this file. Can be run in an existing Command Prompt session.
::
:: LICENCE: MIT — https://opensource.org/licenses/MIT
endlocal

:: If `rxJDK_BASE` already exists, simply terminate, otherwise we will
:: keep on prefixing (potentially) the same directory to `PATH`.
if defined rxJDK_BASE goto EXIT

:: Get this batch file's directory, and strip trailing backslash.
set rxJDK_BASE=%~dp0
set rxJDK_BASE=%rxJDK_BASE:~0,-1%

:: Prefix to current `PATH` environment variable.
set PATH=%rxJDK_BASE%\bin;%rxJDK_BASE%\jre\bin;%PATH%

:: Set `JAVA_HOME`s. You can add more settings here.
set "JAVA_HOME=%rxJDK_BASE%"
set "JAVA8_HOME=%rxJDK_BASE%"
set "JRE_HOME=%rxJDK_BASE%\jre"
set "JDK_HOME=%rxJDK_BASE%"
set "JDK8_HOME=%rxJDK_BASE%"

:: Change the prompt to remind us that we're in the relocatable JDK
:: environment.
set PROMPT=[rxJDK8] $p$_$g$s

:EXIT
endlocal

This batch file, also to be placed in the base JDK directory, will call the above rxjdk-env.cmd batch file to set the environment, and then launch a new Command Prompt window with these settings. Doing this allows the batch file to set the title of the new Command Prompt window to rxJDK8, and change the prompt without affecting an existing session, and it can be double-clicked from a File Manager.

The other advantage is that any settings you make to the Console will persist in the Windows Registry using the title of the Console window. We suggest you set your font to Consolas for good Unicode (UTF-8) coverage. If you are not using Windows 10 with recent updates, you should change the PROMPT setting, and everywhere else we use ESC up to the next m.

rxjdk-cmd.cmdRelocatable JDK Command Prompt
@echo off & setlocal enableextensions
:: Opens new Command Prompt window with a portable Java JDK 8 (64-bit)
:: environment, with `PATH` set, so that `java`, `javac`, etc. can be
:: run from the command line, from any directory. If not on Windows 10,
:: change the `PROMPT` setting below to your liking.
::
:: LICENCE: MIT — https://opensource.org/licenses/MIT
setlocal enabledelayedexpansion

:: The following batch file only sets the environment and PATH.
call rxjdk-env.cmd

:: Open a new command prompt window, with appropriate title.
set ESC=
set MSG= Portable JDK Environment
set PROMPT=$e[36;40;7m$srxJDK8$s$e[0m $e[33;1m$p$e[0m$_$g$s$e[0m
start "rxJDK8" /D %rxJDK_BASE%\..\ cmd.exe /K ^
  echo.^&echo %ESC%[38;5;220m%MSG%%ESC%[0m ^&^
  %rxJDK_BASE%\startup.cmd

goto :EXIT

:EXIT
endlocal

ImportantHard-Coded ESC

The ESC variable is followed by a hard-coded ASCII escape character (code 27), but it will not display in HTML. It will copy though, otherwise just enter it yourself, assuming you know how to do that in your editor.

For easy customisation, the above rxjdk-cmd.cmd batch loads a startup.cmd file, where you can add further customisation. An example is shown below, but you can modify it to your liking, may­be even change the working directory to your workspace. The chcp… command sets UTF-8 encoding for the Command Prompt, so you probably want to leave that as is.

startup.cmdRelocatable JDK Customised Startup
@echo off & setlocal enableextensions
:: custom startup loaded from `rxjdk-cmd.cmd`.
::
doskey aliases=doskey /macros
doskey alias=doskey $*
doskey jc=javac -Xlint -Xdiags:verbose -encoding utf8 $*
doskey ja=java %rxJRE_OPTS% $*
doskey jw=javaw %rxJRE_OPTS% $*
doskey jv=cvtjava $*
doskey jd=javadoc -encoding utf8 -docencoding utf8 -charset utf8 $*
doskey ls=dir /b $*
doskey rm=del $*
doskey which=for %%F in ($1) do @echo.%%~$PATH:F
chcp 65001 2>&1 >nul
:EXIT
endlocal

The doskey command is useful to create aliases for often-used commands. You can check the lo­ca­tion of any executable (but you must specify the full name) with the which alias. It searches in directories listed in the PATH environment variable, and you can thus check if it finds the correct executable. Otherwise, try Windows 10’s ‘whereexecutable›’ command.

Now all you need is an editor, and you can effectively write any Java SE program you like. Other tools simply make certain processes easier as programs get bigger, but to learn Java, this is all you need. And you can always add more tools later.

JDK SE On Linux & MacOS

On Linux and MacOS, you may want to try SDKMAN!, which can download and manage a JDK for you. It can also download and manage other Java-related tools and environments. Alternatively, you can install the official versions, or use your package manager.

Ubuntu and Debian

On Ubuntu-based systems and Debian, you can use the webupd8.org PPA repository. The com­mands are as follows, assuming you have already updated your system:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer

You will be requested to confirm your acceptance of Oracle’s binary licence agreement before the installation will continue. An oracle-java9-installer package is also available, if you lean that way. Just for safety, you can install the following package, which will set your new JDK 8 as the default:

sudo apt install oracle-java8-set-default

Generally, this should not be necessary on Ubuntu, since it is installed by default, but it will not hurt if you run the above command. You can verify that javac is on your PATH with:

javac -version

Now you have a working Java Platform 8 Software Development Kit. If you want, you can in­ves­ti­gate jEnv, but that is only necessary if you are going to run different versions of the JDK.

MacOS Sierra & High Sierra

If you are on MacOS and not already using Homebrew, you are doing yourself a dis­ser­vice. Home­brew can also be used to in­stall a Java JDK. By default, it installs the latest available, via Casks which you enable in Homebrew as follows:

brew tap caskroom/cask
brew update

To enable brew cask to install a JDK other than the latest version, run this command:

brew tap caskroom/versions
brew cask search "java*"

The search will now show java8 as an option. You can install that JDK 8 with:

brew cask install java8

Java’s SDKs are installed on MacOS under /Library/Java/JavaVirtualMachines, and you may have several versions installed without a problem. Just set your JAVA_HOME to the appropriate directory, e.g.:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk‹version›.jdk/Contents/Home

If you only use one version, you can put that in your .bash_profile or .bashrc file. To see which versions are installed, you can run:

/usr/libexec/java_home -V

You could also manage your different JDK versions with jEnv, which you can install via Homebrew with:

brew install jenv

You can check StackOverflow for more ideas, and you can run the following command to get the Java view of your environment, under any operating system:

java -XshowSettings:properties -version

Minimal Test Program

Once you have a working JDK on your PATH, you can test it out by writing a minimal program. Here we will painstakingly describe the process to create a new (simple) Java program. This process will suffice until we graduate to larger programs containing several classes and files.

Program Directory

As good practice would dictate, the first step is to create a directory for your program. For simple programs this may seem overkill, but it is better to be consistent. Following tradition, we shall create a HelloWorld directory, in an arbitrary location, e.g. C:\Course, or $HOME/Course (POSIX), and make it the current directory.

Windows:
mkdir C:\Course 2>&1 >nul & cd C:\Course 
mkdir HelloWorld & cd HelloWorld

The redirection of output to the NUL: device is to (hopefully) suppress error messages if the di­rec­to­ry already exists. Even if it does display a message (one cannot always redirect all Micro­soft’s commands’ output), it should not be of any concern, just untidy.

POSIX:
mkdir $HOME/Course 2>&1 >/dev/null; cd $HOME/Course 
mkdir HelloWorld; cd HelloWorld

To save on typing, you can use tilde (~) as alias for $HOME in interactive POSIX shells.

Create / Edit Source Code

Using any editor, though we use gvim (or vim if you want) in the example command lines below, we must create a Java source file, with the .java extension. The name of the file is important — it must exactly match the public class name in the file, so we must think ahead.

gvim Hello.java

In this Hello.java source file, we can now enter the following, then save it. The @file and @brief parts represent our documentation convention; you do not have to do that in real Java code.

Hello.javaMinimal Java Test Example Console Program

Note that our code formatting style differs from popular styles in two major ways:

You are welcome to use your own style, and may even be required to adhere to a particular style by your employers or customers. Whatever style you prefer, just ensure it is consistent, and cri­ti­cal­ly considered (”liking” a style is an emotion, not a reason).

Compilation & Execution

Once saved, the source code must be compiled. This is done with the javac tool. Always. Re­gard­less of IDE, or any other environment. That button you click in the IDE, just runs javac for you.

javac -Xlint -Xdiags:verbose -encoding utf8 Hello.java

If there are no errors, the result will be a Hello.class file in the same directory. You could have added a ‘-ddirectory›’ option to place the result in another location, if you wanted.

Since the Hello.class file is not a native executable, we need the JRE java tool (or javaw) to or­ches­trate the class loading, bytecode JITing, and final execution:

java Hello
java Hello "Jacqui Coosner"

If your program contained Javadoc-formatted documentation comments (which our example does not), you could generate the API documentation in HTML format to some ‹dir›ectory:

javadoc -encoding utf8 -docencoding utf8 -charset utf8 -d ‹dir› Hello.java

We shall revisit Javadoc documentation in the Template example below.

Basic Java

Once you can create .java source files in a project directory, you have to consider the basic structure of source files, and which keywords to avoid in names (identifiers) you create. You can refer to the Java Quick Reference and Glossary page at any time, but here we represent the main starting points.

Keywords and Reserved Words

Java has a number of keywords which cannot be used for purposes other than intended. In ad­di­tion, the language specifies a number of reserved words, which have no purpose (yet), but should not be used for user-defined identifiers.

SyntaxJava Key/Reserved Words

abstract
assert
boolean
break
byte
case
catch
char
class
const
continue
default
do
double
else
enum
extends
false
final
finally
float
for
goto
if
implements
import
instanceof
int
interface
long
native
new
null
package
private
protected
public
return
short
static
strictfp
super
switch
synchronized
this
throw
throws
transient
true
try
void
volatile
while

Note that technically, null, true and false are literals, while const and goto are reserved; so is a single underscore (_) character (since Java 9).

Java 9 adds a few more contextual, or restricted keywords, which are only keywords in certain places in the structure of a program. You should treat them as keywords anyway in new pro­grams, even Java 8 programs, to ensure a smooth eventual migration to JDK 9.

SyntaxJava 9 Restricted Keywords

exports
module
open
opens
provides
requires
to
uses
transitive
with

Primitive Types and Wrappers

Primitive types are not class types. Variables of a primitive types to the actual primitive value, and not a reference to the object, which is the case for all other types.

SyntaxPrimitive Types

char
boolean
byte
short
int
long
float
double

Wrapper classes for the primitive types allow one to box a primitive type as a class type, which means it can be nullable.

Syntax ­ Primitive Wrapper Types

Character
Boolean
Byte
Short
Integer
Long
Float
Double

Structure & Organisation

If you are new to Java, do not sweat the details here… this is about a structural pattern you can reuse; not about syntax. Without all the comments and useful constants, the structure is simple:

PatternSimple Java Console Applications

importsopt
public classmain-class{
public static void main (String[] args) {
statementsopt
}
fieldsopt
methodsopt
constructorsopt
static-initialiseropt
}

  • imports namespace directives to avoid fully-qualified names.
  • main-class at most one public class per file.
  • statements program flow and behaviour.
  • fields either static (shared) or “instance” variables (data members) at class level.
  • methods either static (shared) or “instance” member functions.
  • static-initialiser may initialise only static ‹fields›.

As you can see, most of the members are optional. The only requirement is main, and the fact that the ‹main-class› must be in a file called: ‹main-class.java. Because of the fact that the file name and class name must match, only one public class per .java file is allowed. Where you put the curly braces is a style, Java does not care — we just tend to use traditional styling in formal syntax and patterns.

In single-class programs, or generally in the class that contains main, we have no ‹constructors›, and only staticfields› and staticmethods›; and sometimes, a <static initialiser›. More ad­vanced, is the ability to create nested classes.

The order of the members is not important — arrange the members as you feel is easiest to read and understand; just be consistent.

Practical Learning Java Template

To get closer to real-world Java programming, but still keep control, we present here a struc­ture for creating simple Java programs, which will scale to larger programs — until you start using IDEs or build tools to manage your projects.

Workspace and Projects

Although the terms workspace, solution and project are often seen in IDEs, these are not formal Java concepts — just practical terms. For our purposes, the Java workspace is C:\Course\work on Windows, or $HOME/Course/work on POSIX-like systems, but you can choose any location you like. Every new program, or project, will get a subdirectory under the workspace directory.

Inside a project directory, you should have a src (source) directory, a doc (documentation) dir­ec­tory, and a bin (binaries) directory. Once you start using packages (this is a Java “thing”), the src and bin directories will have further subdirectories that reflect the package naming.

The first step is to choose a name for your project; let us say: Template. Assuming your chosen workspace directory exists, and that it is the current working directory, the following commands will create the project directory and subdirectories:

mkdir Template
cd Template
mkdir src
mkdir bin

You can create the doc directory as well, but the javadoc tool will create it automatically once we start using it.

Build Scripts

We could use one of the several build tools available, but initially they would just add com­plex­ity, and will not help you understand a Java program’s infrastructure. To make it easy for you to control and understand the build process, we present two build scripts: build.cmd for Windows, and build for POSIX-like shells.

NOTEJava Archive Executables

Once programs grow beyond a few classes, and you start using third-party libraries, you should package your application in an executable .jar file; otherwise it becomes what we call “a royal mess”. Although this is not necessary for small programs such as the Template here, the scripts do create .jar files. You execute .jar files with the normal java program, adding the -jar switch: ‘javajre-options-jarjar-file› ‹prg-args›’.

These build scripts also create “launcher” shell scripts (a batch file on Windows) to run your Java program from the .jar file. They are also created in the ./bin directory, and should always stay in the same directory as the corresponding .jar file.

build.cmdWindows Java Build Script
@echo off & setlocal enableextensions
::
:: Windows Command Prompt batch file template to build Java projects.
:: Set your main class in `JC_MAIN`. Uncomment the `javadoc` line, if
:: you also want the script to create your Javadoc documentation.
::
:: Add or remove `javac` options to/from `JC_OPTS`. For `javadoc`, do
:: the same for `JD_OPTS`.
::
setlocal
set JC_MAIN=Template
set JC_OPTS=-Xlint -Xdiags:verbose -encoding utf8 -cp . -d ..\bin
set JD_OPTS=-encoding utf8 -docencoding utf8 -charset utf8
pushd .\src
javac %JC_OPTS% %JC_MAIN%.java
if "%ERRORLEVEL%" neq "0" (
   popd
   goto EXIT
)
:: Create an executable `.jar` file (with automatic manifest).
cd ..\bin
jar cvfe %JC_MAIN%.jar %JC_MAIN% *.class

:: Create Javadoc documentation. Un/comment the next line as needed.
cd ..\src
javadoc %JD_OPTS% -d ..\doc *.java

popd
:: Create a simple “launcher” batch file for the project. You can set
:: the values of `JRE_OPTS` as you see fit, from the examples here.
if not EXIST bin\%JC_MAIN%.cmd (
   echo @echo off ^& setlocal enableextensions > bin\%JC_MAIN%.cmd
   echo set JRE_OPTS=-Duser.country=ZA -Duser.language=en_ZA ^
      >> bin\%JC_MAIN%.cmd
   echo set JRE_OPTS=%%JRE_OPTS%% -Duser.timezone=Africa/Johannesburg ^
      >> bin\%JC_MAIN%.cmd
   echo set JRE_OPTS=%%JRE_OPTS%% -cp %%~dp0;. ^
      >> bin\%JC_MAIN%.cmd
   echo java %%JRE_OPTS%% -jar %%~dp0%JC_MAIN%.jar %%* ^
      >> bin\%JC_MAIN%.cmd
)
:EXIT
endlocal

Place a copy of this batch file in your project directory. If you are satisfied with the options set, you only have to modify the JC_MAIN value, and set it to the name of the class file containing main (without the .java extension), for every new project. You run the script simply by executing: build on the command line. The equivalent script for POSIX shells (bash), is shown below:

buildPOSIX Shell Java Build Script

For your convenience, you should run: chmod a+x build on this script, so you can execute it simply with: ./build.

Template.javaJava Template for Console Applications
/** Template class for simple console applications.
 * <p>
 * This can provide the structure for other console applications. The
 * static constructor sets the encoding of output to
 * <a href="https://en.wikipedia.org/wiki/UTF-8">UTF-8</a> on all
 * systems. This will also work for Windows™, as long as you have set
 * the codepage: <code>chcp 65001</code> in your Command Prompt — Java
 * provides no standard way to do that, and we do not want to get
 * involved with JNI/JNA at this stage. UTF-8 is the default in most
 * POSIX-like shells.</p>
*/
import static java.lang.System.out;

public class Template {


// EVERY JAVA PROGRAM IS REQUIRED TO HAVE A PUBLIC STATIC MAIN FUNCTION
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
/** Startup prints useful information.
 * <p>
 * This program does not do much, except for printing out some useful
 * system information, that is often needed in real programs. It will
 * write out any arguments passed to the program.</p>
 * <p>
 * If you are running in a terminal, or have managed to set the Windows
 * Console to interpret ANSI/VT100 escape sequences, you can clear the
 * screen (for example) with:
 * <code>System.out.print("\033[2J\033[0;0H");</code></p>
 *
 * More at <a href="https://en.wikipedia.org/wiki/ANSI_escape_code"
 * >WikiPedia - ANSI escape code</a>.
 *
 * @param args Arguments are written out, if any were passed.
*/
public static void main (String[] args) {

   out.print("\n ENVIRONMENT INFO ");
   for (int i = 0; i < 50; ++i) out.print('-');

   String w = "\n %-15s: %s";
   final String OS = osNAME + " - " + osVER;

   out.format(w, "OS Platform",     OS      );
   out.format(w, "User Home",       userHOME);
   out.format(w, "Work Directory",  appCWD  );
   out.format(w, "Application Dir", appDIR  );
   out.format(w, "Java Runtime",    javaHOME);

   if (args.length > 0)
      for (int i = 0; i < args.length; ++i)
         out.format("\n Argument #%02d   : %s", i+1, args[i]);
   out.println();

   System.exit(0);
   }


// STATIC FIELDS AND CONSTANTS (FINALS) THAT ARE INITIALISED AT STARTUP
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
/** Application's current working directory at startup. */
public final static String appCWD = System.getProperty("user.dir");
/** User home directory; works correctly in JRE 8. */
public final static String userHOME = System.getProperty("user.home");
/** JRE location; can be overridden with <code>JAVA_HOME</code>." */
public final static String javaHOME = System.getProperty("java.home");
/** Operating system name, as the JRE sees it. */
public final static String osNAME = System.getProperty("os.name");
/** Operating system version, as the JRE sees it. */
public final static String osVER = System.getProperty("os.version");

/** Will be <code>true</code> if running on Windows™. */
public final static boolean isWINOS = osNAME.startsWith("Windows");
/** Will be <code>true</code> if not running on Windows™. */
public final static boolean isPOSIX = !isWINOS;

/** Location of the <strong>application</strong> directory. */
public static String appDIR = null; //←set below.


// OPTIONAL STATIC CONSTRUCTOR USED HERE TO INITIALISE THE APPLICATION
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
static {
   try {
      appDIR = new java.io.File(
         Template.class.getProtectionDomain()
         . getCodeSource().getLocation().toURI().getPath()
         ).toString();//←get executable path.
      if (appDIR.endsWith(".jar"))
         appDIR = appDIR.substring(
            0, appDIR.lastIndexOf(java.io.File.separatorChar));

      System.setOut(
         new java.io.PrintStream(
            new java.io.FileOutputStream(java.io.FileDescriptor.out),
            true, "UTF-8")
         );//←set UTF-8 encoding on `out`.
      }
   catch (Exception ex) {
      // optional:
      // throw new ExceptionInInitializerError(ex);
      }
   }

}//class

Once you have saved the file in ‹workspace/Template/src, and assuming Template is your work­ing directory where you saved the build scripts, you can compile the program on Win­dows by simply running build, and in POSIX shells, with: ./build. You can execute the program on Win­dows with: bin\Template, and POSIX with: bin/Template. In either case, you can pass the program arguments, enclosing arguments that contain spaces in double quotes. Here is an example run on Ubuntu Linux 16.04:

bin/Template ABC "DEF GHI"
 ENVIRONMENT INFO --------------------------------------------------
 OS Platform    : Linux - 4.4.0-104-generic
 User Home      : /home/brx
 Work Directory : /home/brx/Work/java/Template
 Application Dir: /home/brx/Work/java/Template/bin
 Java Runtime   : /usr/lib/jvm/java-8-oracle/jre
 Argument #01   : ABC
 Argument #02   : DEF GHI

And on Windows 10 (unfortunately, Java does not provide the build version number, which would have been very useful):

bin\Template ABC "DEF GHI"
 ENVIRONMENT INFO --------------------------------------------------
 OS Platform    : Windows 10 - 10.0
 User Home      : C:\Users\brx
 Work Directory : D:\Work\proj\java\Template
 Application Dir: D:\Work\proj\java\Template\bin
 Java Runtime   : D:\Work\rxjdk8u152\jre
 Argument #01   : ABC
 Argument #02   : DEF GHI

We could not resist adding Javadoc documentation, since you really should do that as soon as possible, even if it is not complex or verbose.

Note that it is generally not a good idea to use static constructors, but it will suffice until we have enough knowledge to consider other options.

Java Archive Executables Summary

This is just a summary of how to create simple executable .jar files, in case you want to roll your own build scripts.

cd bin
jar cvfe Template.jar Template *.class
cd ..
java -jar bin/Template ABC "DEF GHI"

The last line executes the Template class from the Template.jar file. The .jar file can be any name; it did not have to be Template.jar; but it is important that you provide the start class name (the one containing main), which in this case, is Template.

Incus Data Java Launcher

It is very frustrating that the Windows 10 Console supports VT100/ANSI escape sequences, but none of java.exe, python.exe or perl.exe command-line programs enable that mode in the Console. Nor do the Windows Console developers allow one a setting to enable Vir­tual Ter­mi­nal mode in the Console settings, nor an environment variable, nor a Registry setting. The Com­mand Prompt enables it for itself, but the moment you run console programs, Command Prompt reverts the setting first (and re-enables it again when the program exits).

This means that, unless a program performs some non-portable low-level calls to SetConsoleCP and SetConsoleMode in the Windows API, you cannot write even rudimentary por­table programs that use terminal escape sequences — unless you use a third-party library, or ma­nu­al­ly use JNI/JNA for Java. This is really tedious and quite unacceptable.

For java.exe then, we wrote a C replacement, called cvtjava.exe, which sets the 65001 code page (Windows Console UTF-8), and enables the Console Virtual Terminal mode. It can be called just like java.exe, except that it will show the following screen when called with no arguments, or with a --help switch. All the output colour is effected only with ANSI escape sequences — even clearing the screen is now portable.

cvtjava --help - Help Output
cvtjava --help - Help Output

Using the Virtual Terminal Java Launcher

The output of cvtjava --help should explain it, but we will reiterate the information here. We stress that all work is performed by Oracle’s java.exe; cvtjava.exe is only a “wrapper” for it. It does not depend on any particular version of Java, as long as you have an original java.exe on your PATH, whether it is the standard JRE one, or a JDK one.

As Replacement for java.exe

You must ensure that cvtjave.exe is on your PATH. We always have C:\bin first in our PATH, for utilities exactly like this. Everywhere you are instructed to run java, you can then just run cvtjava, which will call java.exe. Any arguments are simply passed to java.exe.

You can go one step further, by copying or renaming cvtjava.exe to java.exe. The only caveat is that you must make sure it will be found first (must be in a directory listed before the original java.exe in your PATH environment variable). Our java.exe will find the official one, call it, and pass all arguments to it. This makes it a 100% replacement — except you will have UTF-8 and Virtual Terminal processing enabled, for all .jar or .class programs executed.

As Executable Jar File Launcher

Assume you have an executable Jar file, e.g., Template.jar. You can then make a copy of our cvtjava.exe to the same directory as the .jar file: Template.exe. When named this way, our launcher will see that there is a .jar file with the same name, and instruct java.exe to execute the file (with a ‘--jarjarfile›’ argument).

JRE Settings in Environment Variable

Any JRE settings you want to automatically pass to the original java.exe, you can place in an en­vi­ron­ment variable called: rxJRE_OPTS. This will automatically be expanded as first argument(s) to java.exe. The arguments are not validated in any way, and if the syntax is incorrect, the error messages will come from java.exe, not our launcher.

UTF-8 and Fonts

The Console will handle UTF-8 fine, but your font may not have the appropriate glyphs. Unless you have some other preference that works for you, we suggest you use Consolas. The launcher could set that automatically, but that might frustrate users who like their own fonts. Maybe later we can add an option to do that, maybe with an .ini file, which could then also set the colour template. In the meantime, you can use our conpal.exe program to set the palette to one of seven (07) schemes, the default (0) being the new Windows 10 Console colour scheme.

Java Test Program

If you want to test the cvtjava.exe launcher, you can replace the main function in Template.java with the following version:

This will bring a bit of colour to your life, and will work the same in POSIX-like shells where UTF-8 is enabled — the default on modern systems, and Linux and MacOS in particular:

cvtjava -jar bin\Template.jar ABC "DEF GHI" - Output
cvtjava -jar bin\Template.jar ABC "DEF GHI" - Output

You can copy cvtjava.exe to bin\Template.exe and then run: ‘bin\Templateargs›’, and even make a Windows shortcut to it, if you want — that is one advantage of an .exe launcher. All the normal java commands work, so you can try:

cvtjava -cp bin;. Template ‹args›
cvtjava -cp bin\Template.jar;. Template ‹args›
cvtjava -XshowSettings
cvtjava -help

For each of the above commands, replace cvtjava with java to prove that they work the same way. The only difference will be that you see no colours and the display is not cleared when running the example, because the escape sequences are not processed.

If you prefer a library solution, Jansi is simple, portable and will work on versions of Windows older than 10. A library that uses Jansi, but also offers line input, is JLine, which is use­ful for controllable input in console ap­pli­ca­tions. Neither sets code page 65001 for UTF-8, which must still be done manually.

Summary

From this point, we will assume that you have a Java 8 SDK at hand, and have been able to com­pile and run the two example applications presented above. Do not continue until you are com­plete­ly com­for­tab­le with creating directories for your projects, creating and editing Java source files, com­pil­ing your pro­grams, and running your programs. The basic structure of a Java source file is simple, but do try to remember it.

From a syntactical point of view, you only have to know the following:

Do not at this point worry about the numerous classes and packages available. The first order of business is to learn the syntax and structure of Java programs. Along the way, as a matter of practicality, several general-purpose classes will be introduced.

Incus Data Supplementary Material

Types, Values and Variables

2017-12-27: Edited. [jjc]
2017-12-23: Incus Launcher. Reorganisation. [brx]
2017-12-20: Created. [brx]