Introduction to Java for Coders : Part 1

A guide for coders to learn Java concepts, syntax and best practices.

Rahul Singh
Abstract.ai
14 min readApr 30, 2020

--

Java Language is named after Java Coffee from Indonesia. Photo by Jessica Lewis on Unsplash

This Java blog acquaints coders with Java Programming. We introduce basic syntax and best practices to follow while programming in Java. We recommended installing Eclipse IDE & Java 1.8+ to run the code files provided. Please read the comments provided with the code for additional tips. This blog can also be found as a GitHub Repository along with complete code examples with output at this link.

This blog is part 1 of a two-part series. Read “Introduction to Java for Coders : Part 2” for detail on how to deal with Error Handling, Multi-threading, Collections, Functional Programming & File Handling in Java.

1. About Java

Java is a popular Object-Oriented Programming Language used for making Android Apps, Desktop and Web application, Games, Web servers and much more.

It works on various platforms such as Windows, Linux, MacOS etc. It has large community support and online discussion forums which help boost our productivity & solve any problems faced while programming.

Code written in Java is simpler and easier to understand. Java has huge API support which helps us make comprehensive applications. Java has in-built Garbage Collection which takes off the pain of managing pointers and memory allocation and freeing up away from the programmer’s hands, thus making it much easier to learn for beginners. Sun’s Java implementation has extensive documentation which allows you to resolve any quick doubts you have at any point during development. You can find the official documentation here.

2. Java Tools

We must learn about JDK, JRE & JVM and the differences between them before we learn about the Java Language.

Java Virtual Machine (JVM)

It provides the runtime environment in which the Java Bytecode is executed. JVMs are platform dependent as the steps needed to convert bytecode into machine code is dependent on the Operating System. It loads, verifies and then executes the code.

Java Runtime Environment (JRE)

It is the set of tools which are used to implement the runtime environment for running Java applications. It contains the JVM, set of libraries and other components used by JVM at runtime.

Java Development Kit (JDK)

It is a software development tool which is used to develop Java applications. It consists of JRE, the Java compiler (javac), the Java debugger, Java loader(java), Java documentation (javadoc) and an archiver(jar).

Java Tools (Source)

We use the JDK to make Java programs. However, to run them we only need the JRE. JVM, JRE & JDK are platform dependent, while the Java language is platform independent.

3. Hello World

The first program we would write in Java would simply output the phrase “Hello World!”.

Each executable java program is mainly written as a class which has a main() method that gets executed first whenever we run the program. The name of the Java file must be the same as the Class name. In Java, we preferably use the camel-case naming convention.

In the class definition, we first specify the package name of the class. A package is a collection of related classes which are intended to perform a similar logic, hence they are put together in the same directory.

The main method is given public access specifier so that it could be accessed by those trying to run the program and a static access modifier so that it could be run without creating an instance of the class. I recommend reading up about other access specifiers and access modifiers. The main method has void return type, thus it doesn’t return a value.

To output to the console, we use the System class and its System.out.println() method which prints the argument along with an additional newline character. The System class is one of the few classes imported by default in any java class.

In the code examples to follow, in the absence of the class declaration or main method, you should assume that the code is placed in a similar class, inside its main method.

4. Primitive Data Type

Java is a static language, which means that we must declare the variable data type before creating it.

Java supports 8 predefined data types called primitive data types:

  • int: It is a 32-bit integer value which has a minimum value of -2³¹ and a maximum value of 2³¹–1. We can also use octal or hexadecimal number systems as integers which can be specified by starting the value with “0” or “0x” respectively.
  • byte: It is an 8-bit integer value which has a minimum value of -128 and a maximum value of 127. It is useful to save memory when storing numeric codes, age etc in large arrays.
  • short: It is a 16-bit integer value which has a minimum value of -32,768 and a maximum value of 32,767.
  • long: It is a 64-bit integer value which has a minimum value of -2⁶³ and a maximum value of 2⁶³–1.
  • float: It is a 32-bit floating-point value with precision up to 6–7 decimal points.
  • double: It is a 64-bit floating-point value with precision up to 15–16 decimal points.
  • boolean: It has only two possible values, true and false. Used to store conditional results or flags.
  • char: It is a single 16-bit Unicode character.

All these values default to a 0 value or a false value. However, the Java compiler doesn’t initialize the local variables.

In PrintData, we’ve used the System.out.printf() function to output the variables. This function is called the print formatter and allows us to print a string with references to the variable arguments following it. We can note that the code for character is “%c”, boolean is “%b” and integer is “%d”.

Java allows us to Type Cast(or Convert) one type of data to another data type. Whenever we convert from a data type with shorter memory size to a data type with larger memory size, it is called as Widening type casting and no data loss takes place. However, the vice-versa is called Narrowing type casting and data loss may take place.

5. Non-Primitive Data Type

Non-Primitive Data Types are also called as Reference Data types as they themselves don’t store the data but store the pointer to the data in Stack memory. The main data is generally stored in Heap memory.

Primitive data types are predefined in Java whereas we can create custom Non-primitive data types of our own. Reference data types may also contain certain methods to operate on the data. These can also be initialized as null. The size of all Non-Primitive data types stored in stack memory is the same because they all store an address pointer.

The Non-Primitive Data Types available are:

String

It is a class which stores a sequence of characters(char). String objects are immutable and also have many helper functions to perform operations on the string data.

Array

Arrays are a data structure which stores homogeneous objects or the objects of the same type together in an ordered manner. Array objects can be accessed by their index.

Class

A class in Java is used to implement the Object-Oriented Paradigm. It is basically a blueprint of the object and defines some data and methods and the relation between them. It can also be used to create our own custom data types in Java.

For every primitive data type in Java, we have a special Wrapper Class which helps us perform additional operations through predefined methods. These classes have the same name as the primitive data type with their first alphabet capitalized. The only exception is Character class for char.

Interface

An Interface is like a contract which enforces that certain methods be defined in the Class implementing that interface. It allows us to establish a standard protocol of usage while creating and using classes. It specifies what a class must do but doesn’t provide us with the exact implementation.

We will learn more about Arrays, Classes and Interfaces in later topics.

6. Conditionals

Whenever we compare two values or evaluate expressions or check conditions, Java stores the result as booleans, i.e. true or false. This allows us to establish control flow by producing different outcomes depending upon these boolean results. Java uses three different types of conditional statements:

If-Else

It allows us to check for various conditions using else if clause.

Syntax

if(condition1){
statements;
}else if(condition2){
statements;
}else{
statements;
}

Once a true condition is met, we stop checking for further conditions and if no condition is true we execute the else code block.

The Scanner class is used to scan any stream for inputs and allows us to access it through method functions. We used the System.in stream to check for inputs. We must always be vigilant to close the scanner after use otherwise it will lead to resource leakage as it will not be collected by the Java Garbage collector.

Switch

Switch statement provides a more intuitive approach to check for conditions.

Syntax

switch(variable){
case value1: //statements
break;
case value2: //statements
break;
default: //statements
}

Whenever the value of the variable matches that given in the respective case, execution begins and all the subsequent lines below it are run. It won’t check for the condition again. However, this leads to unwanted output. We can control this behaviour by putting the break statement after each case. If the variable matches no case, then the statements following the default tag are run.

Ternary Operator

It is a re-factored if-else statement. It helps us to write one-line if-else statements.

Syntax

variable = condition ? value1 : value2;

If the given condition is true, then value1 is assigned to the variable, otherwise, value2 is assigned.

7. Loops

Loops are generally used to execute a block of code multiple times. It helps to reduce the amount of written code required to run the logic and also allows us to repeat code when we don’t know how many times it is to be repeated.

We introduce the four basic loops in Java i.e. For loop, Enhanced-For loop, While loop & Do-While loop.

Each of these loops has a different syntax and it is advised to use each for different use cases however any loop implementation could is possible using any of these loops. They could also be used interchangeably but it is not advised to do so.

For Loop

for(initialization; condition; increment/decrement){
statements;
}

This loop is used to execute a block of code a known set of time when we know the starting and ending conditions of the loop. Initialization is run only once at the beginning of the loop and then the condition is checked. If found to be true, the following code block is executed. After that the increment/decrement operation is performed and then the condition is checked again. This task is repeated until the condition becomes false.

Enhanced For Loop

for(DataType var:list){
doSomething(var);
}

This loop is a simpler variant of the classic for loop and it enables us to easily iterate over list elements. We can traverse over List elements easily through this enhanced for loop. The variable var refers to each element of list sequentially and allows us to perform the desired operations on them.

While Loop

while(condition){
statements;
}

It is used to execute a block of code repeatedly when we are not sure about how many iterations need to be done. At the beginning of the loop, the condition is evaluated and if found to be true, the following code block is evaluated. This action is repeated while the condition remains true. The loop terminates when the condition becomes false.

Do-While Loop

do{
statements;
} while(condition);

This loop is used whenever we want the loop to be executed at least once. The body of a do-while loop gets executed at least one time and then the condition in while is checked. This block gets executed again if the expression in while is evaluated to be true and it keeps on repeating until the condition becomes false.

8. Lists

Lists are used to store data of the same logic and the same data type together. It is a collection of closely related data. Arrays are a reference data type and can be based upon any data type.

We can create arrays by using a square bracket ([]) after the declaration of the data type. Such arrays have limited functionality because we can only modify their values, but no new elements can be added or removed. We can access elements by the array name followed by the index of the element in square brackets. Putting in an index value greater than array size throws an error.

We can use the ArrayList class provided by Java to create mutable lists. This class provides us with the ability to add/remove elements to the list but it comes at the cost of added time complexity. Many other classes such as Vector & Stack also implement the List interface and can be used whenever suitable. Vector is similar to ArrayList but all its methods are synchronised hence thread-safe.

The ArrayList and Iterator Class use Generics to make it possible to create a list and iterator of any desired data type. We specify the data type here in <> as ArrayList<String> to create a list of strings. We can also create a list of our own custom classes. We would learn more about Generics in later topics.

9. Methods

A method runs a block of code whenever called. It helps reduce code redundancy. In Java, methods are defined inside classes.

Syntax

access-specifier access-modifier return-type method-name(parameter-list, data-type... var-name){
statements;
}

Each method in a class must have a unique name. Access specifiers decide from where we can access the method. Non-access modifiers add certain characteristics to the method. These specifiers and modifiers can also be used for member data variables. For more details on different access specifiers and non-access modifiers, go to these links[1,2].

For a given return-type, every function must return a value of that type except for void which requires no return value.

Parameters can be a single parameter or several comma-separated parameters. It allows Java to know what type of data to expect for the method. If we expect a list of elements but with unknown size, we can use variable arguments to accept such data. This is shown as var-name in the given syntax. However, remember that the variable argument must be the last argument inside the function.

Static methods can be accessed without creating an object instance of the class, however, to access non-static methods we must use the class object using the dot (.) operator. We’ve been doing the same for all predefined Java classes till now.

10. Object-Oriented Programming

Object-Oriented Programming is at the heart of Java. OOP uses objects which have certain data/attributes called the state of the object and certain member functions called the actions performed by the object. The object entities sometimes correspond to things in the real-world and the relations between them. For example, all humans have name, age & sex and we perform actions such as eating, walking and sleeping. Like humans, each object might have different attributes or a different state, but each can perform the same functions. A class provides the attributes and available actions for an object. It serves as a blueprint for each object instance. We can call Homosapiens as the class and each human as its object.

4 basic pillars of OOP are Inheritance, Encapsulation, Polymorphism and Abstraction. Inheritance is deriving properties from a superclass, just like all humans are mammals. Encapsulation means bundling of the data and functions that operate on them. Polymorphism allows us to perform different operations using the same interface, just like humans walk for movement while whales swim for movement. Abstraction means hiding the implementation details and only showing the relevant and simple interface.

A class is created in Java using the class keyword. All classes which don’t inherit any class, inherit the predefined Object Class by default. It is best practice to keep all state variables with private access and implement public getter and setter functions to access them as it allows us to define certain checks on data manipulation and avoid unwanted changes. In the Animal Class, we checked if age was valid or not, and only then allow any changes.

Enumeration is a data type used for denoting fixed constants. We generally use enumerations when we don’t expect the value to change and are fixed. They are created similar to a class, using the keyword enum. Here we use enums to specify the different eating habits of animals which are known to be fixed. Some other uses of enums could be to store the months of the year, days of the week and sex of a person.

The Tiger Class inherits from the Animal class and adds extra states and actions such as roar. This action is unique to the Tiger and hence a subclass was made. This helps reduce code redundancy in the Tiger Class. The eatFood() method performs different actions depending upon whether a string argument is entered or not. In this way, we can implement polymorphism in Classes.

Each class has a Constructor which is defined as a function with its name equal to the class name and no return type. It gets executed whenever a new class object is created. We can also have various implementations of the Constructor, similar to the eatFood() method depending upon the type of argument. Also, note that we have to call the constructor of the parent class before the constructor of the child class is executed. Java provides a default constructor which excepts no argument and initialises all states with a 0 or a null value. If we create a custom constructor for a class, then Java doesn’t create any default constructor.

Abstract Class

An abstract class is declared with the abstract keyword in Java. We usually specify abstract member functions inside an abstract class which are not implemented. An abstract class cannot be instantiated and it must be inherited in another subclass where all its abstract methods are implemented. It is possible to have abstract or non-abstract methods in an abstract class along with data members. These classes help deploy common functionality across all the inheriting classes.

Abstract class denotes an IS-A relationship between itself and the inheriting classes.

Device class acts like a template for all devices to be made and ensures that all devices implement a switchOn() and a switchOff() method.

MediaPlayer inherits Device class and provides its own implementation of all its abstract methods.

An instance of the MediaPlayer class can also be accessed by a variable of its Parent Class type. This is useful when we want to access objects of all classes inheriting the abstract class using a single variable. When we call the abstract methods from this variable, they would behave differently for different classes. This is called as runtime polymorphism.

Interface

An interface represents what actions must be done by an object. It represents a blueprint for a class. It is used as a contract between developers while using different Classes on how certain objects must behave. It is practically helpful in establishing common method names across similar classes and establishing a common usage protocol. Interfaces help achieve abstraction in Java.

An interface can contain any number of methods. We cannot create its instances. All the methods inside an interface are abstract and must be implemented. It is only possible to have static final variables in an interface. We can provide a default implementation for a method in interface by using the default keyword. If we don’t override this method in the implementing class, then the default method is run.

Interfaces help us in tackling the lack of multiple inheritance in Java. A class can implement more than one interfaces. However, interface mustn't be confused with a class. It doesn’t reflect an IS-A relationship between the implementing class and the interface, rather it reflects a feature of the class/how a class works.

Just like with abstract classes, we can use a variable of the interface type to access different implementing classes thus allowing runtime polymorphism.

More to follow in part 2.

--

--

Rahul Singh
Abstract.ai

I teach machines, and sometimes humans. Android Developer. Final year student at Delhi College of Engineering