Hakan Eröztekin
Aug 18 · 15 min read

Java in a Nutshell || A quick review guide of important topics of Java

Properties of Java

  • Object oriented: Java is a true object oriented programming language. Except of the primitive data types, everything is a object.
  • Platform independent: Java is compiled into a platform independent byte code (unlike C and C++). The byte code is interpreted by the Java Virtual Machine (JVM) on whichever platform it’s being run on.
  • Simple: Java is a high-level programming language and is closer to the human language. Thus it’s easier to learn.
  • Interpreted: Java byte code is translated (by JVM) on the fly to native machine instructions.
  • High performance: With Just-In-Time (JIT) compilers, Java enables high performance.

Variable types

  • Local variables: Variables defined inside methods.
  • Instance variables: Variables within a class, outside any method.
  • Class variables: Static variables within a class, outside any method.
Variable types

What are JVM, JRE and JDK?

  1. When we write Java code, java compiler (javac) converts it to byte code. Javac is included in Java Development Kit (JDK).
  2. The byte code is then converted to machine-specific instructions via Java Virtual Machine (JVM).
  3. Machine-specific instructions are then run on the computer by Java Runtime Environment (JRE).
  • JVM = Execution of a Java program. Because Java is a platform-independent language, it needs a virtual machine environment (interpreter) to run, which is provided by JVM. So, JVM is used to run Java code. Whenever we run a Java program either using JRE or JDK, it goes to JVM to be executed.
  • JRE = JVM + Library Classes. JRE provides environment to run Java programs on our machines.
  • JDK = JRE + Development Tools. JDK is used to develop and run Java code. It is used by developers.

Object Creation Stages

Apple myApple = new Apple();
  • Declaration: A variable is declared with an object type and a variable name. Apple myApple;
  • Instantiation: ‘new’ keyword is used to create object. = new
  • Initialization: The call to a constructor. Apple();

Constructor Types

  • Default constructor: A constructor without any argument. Also known as no argument constructor.
  • Parametrized constructor: A constructor with parameters.

Data Types

  • Primitive data types: There are 8 of them; boolean, char, short, byte, int, long, float, double.
  • Non-primitive data types: The rest of the data types, i.e. reference/object data types.

Access Modifiers

  • default is visible to the package.
  • private is visible to the class only.
  • public is visible to the world.
  • protected is visible to the package and sub-classes.

If no access modifier is denoted, defaultis used as a default.

Non-access modifiers are static, final, abstract, synchronized and volatile.


Passing By Value

Java is a pass-by-value language. Referencing , check the below example.

Java is a pass-by-value language

Inheritance

  • Definition: Inheritance is a mechanism where one class acquires all the properties of another class.
  • Benefits: Inheritance promotes code reusability and enables method overriding so that run-timepolymorphism can be achieved. Run-time polymorphism is briefly, “call to a method is resolved at runtime” (whether it’s childs method or parents method).
  • Extra details: private methods, variables and constructors are not inherited while static field/methods are inherited (public static variables aren’t a good practice). Inheritance represents IS-A relationship, also known as parent-child relationship. One class can only extend only one other class. Multiple inheritance is not possible in Java ( about all classes inheriting from Object, it’s briefly chain of inheritances). Reason for that is, say class A and B have talk() method and C inherits both. What happens when we call c.talk() would be unresolved.

Overloading

  • Definition: If a class has more than one methods with the same name but with different type or number of arguments, it’s called overloading.
  • Benefits: It provides cleaner code. Also, it enables to call a similar method with different parameters.
  • Extra details: We can’t only change the return type of a method as this may cause confusion. Ex. sum() returns int, but overloading only with return type as double will cause confusion on which method to call.

Overriding

  • Definition: If a subclass provides a specific implementation of a method that is already provided by its parent class, it’s called overriding.
  • Overriding rules: The methods must have the same name and the same signature. Also, the two classes must have an IS-A relationship (i.e inheritance).
  • Overriding benefits: It is useful to achieve runtime polymorphism and to implement interface methods.
  • Extra details: We can’t override static methods because overriding is for instance methods (not statics, not field variables), statics are if the subclass has the same signature. We can override overloaded methods. @Override signature is not compulsory but it is a good practice to use as it provides additional checks. We can change the scope of overridden method in the subclass to a broader type like from protected to public but not vice versa.

Encapsulation

  • Definition: Encapsulation is data hiding. Methods or variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class.
  • Benefits: We prevent direct access to instance & class variables thus the class will have more control. We can make the class read-only or write-only (by not providing getter or setter). Also, encapsulated classes are easy to (unit) test.
  • Encapsulation is one of the four fundamental OOP concepts. The other three are inheritance, polymorphism, and abstraction.
  • Encapsulation rules: Declare the variables of a class as private. Provide public setter and getter methods to modify and view the variables’ values.

Abstraction

  • Definition: Abstraction is hiding details and showing only the functionality.
  • Another definition: Abstraction is providing user-level details while hiding the implementation details.
  • Example: A good analogy is a coffee machine. As a coffee user all you want is to click a button or two to get your favorite fresh coffee. You don’t want to know how coarse to grind the coffee, the ideal water temperature and what’s the ideal coffee to water ratio. All you want is to get your coffee with your buttons. All the details are hidden and you only see the functionality with buttons, this is the abstraction.
  • Example: A technical example can be user clicking “Order” button, without caring about what happens in the background when he clicks.
  • Benefits: It helps to reduce programming complexity and effort.

There are two ways to achieve abstraction; interface (100% abstraction) and abstract class (0–100% abstraction).

Interface

Reasons to use interface
  • Interface is a blueprint of a class. It has static constants and abstract methods.
  • Interface represents IS-A relationship.
  • Since all methods are abstract, none of the methods can have a body.
  • Just like the abstract class, it cannot be instantiated.
  • Since Java 8, interfaces can have default and static methods.
  • Since Java 9, interfaces can have private methods.
interface myInterface { 
// declare constant fields
// declare methods (they are abstract by default)
}
  • Multiple inheritance is not supported by Java because of ambiguity but it’s possible when the parents are interfaces.
Multiple Inheritance is possible through Interfaces
Example of multiple inheritance to show there won’t be ambiguity

Abstract class

Abstract Class Rules

A class which is declared as abstract is known as an abstract class. It can have abstract and non-abstract methods. It needs to be extended and its method implemented. It cannot be instantiated.

abstract class Bike{ // abstract class
abstract void use(); // no method body
}
class Bianchi extends Bike{
void use(){ System.out.println("Bike is on the use."); }

public static void main(String args[]){
Bike obj = new Bianchi();
obj.use();
}
}

The Big Picture: What’s the relation between Overriding, Upcasting, Overloading, Runtime Polymorphism and Interfaces?

Relation Group 1: Overloading & Compile Time Polymorphism

It’s compile time polymorphism when a call to an overloaded method is resolved at compile time. Also known as static binding and early binding.

Relation Group 2: Overriding & Runtime Polymorphism

It’s run time polymorphism when a call to an overridden method is resolved at runtime. Also known as dynamic binding and late binding.

  • StaticType x = new DynamicType(); is the format we define Java objects. StaticType is determined at compile time, DynamicType is determined at runtime. For the example Fruit f = new Apple() the type of f is Fruit at compile time, Apple at runtime. If apple overrides color() method, it’s a call to the parent’s color() method at compile time, but then changed as childs’ color() method at runtime (runtime polymorphism).
Upcasting
class A {}
class B extends A {}
//Upcasting
A a = new B();

Upcasting is a cast from a derived class to a more general base class.

Dog dog = new Dog();
Animal animal = (Animal) dog;

If the reference variable of Parent class refers to the object of Child class, it is known as upcasting.

Extra Details

Downcasting is a cast from a base class to a more specific class.

Animal animal = new Dog();
Dog dog = (Dog) animal;
  • Java permits an object of a subclass type to be treated as an object of any superclass type. This is called upcasting.
  • Upcasting is done automatically, while downcasting must be manually done by the developer.
  • Upcasting and downcasting are NOT like casting primitives from one to the other ().

Association

  • Association refers to the relationship between multiple objects.
  • Aggregation and composition are two types of association.

Aggregation

  • If a class have an entity reference, it is known as aggregation.
  • Aggregation represents HAS-A relationship.
Aggregation example
  • Aggregation benefits: Promotes code reusability. In the above example, we just simply put use of Address class just with a line of code.

Composition

  • Definition: Composition is the strong type of association.
  • Composition rule: An association is said to composition if an object owns another object and another object cannot exist without the owner object.
  • Example: Think about lego homes. A lego home can’t exist without single lego(s), but legos can exist without a lego home.

I/O

A stream

Stream is a flow of data from an input (source) to an output (destination).

Java I/O Streams
  • InputStream: Read data from a source.
  • OutputStream: Write data to a destination.
  • Extra details: stdin and stdout in C++, System.in and System.out in Java are examples of (standart) streams. byte streams are 8-bit, character streams are 16-bit unicode format used to perform I/O operations.

Serialization & Deserialization

  • Definition: Serialization is the conversion of an object to a series of bytes. The byte stream can then be deserialized — converted into a replica of the original object ().
  • Benefit: The object can be easily saved to persistent storage or streamed across a communication link.
  • Extra details: In Java, the serialization mechanism is built into the platform, but you need to implement the Serializable interface to make an object serializable.

Exceptions

An exception (or exceptional event) is a problem that arises during the execution of a program. When an Exception occurs the normal flow of the program is disrupted and the program/Application terminates abnormally, which is not recommended, therefore, these exceptions are to be handled.

Some of these exceptions are caused by user error, others by programmer error, and others by physical resources that have failed in some manner.

  • Checked exceptions: A checked exception is an exception that is checked (notified) by the compiler at compilation-times, also known as compile time exceptions. These exceptions cannot simply be ignored, the programmer should take care of (handle) these exceptions.
  • Unchecked exceptions: An unchecked exception is an exception that occurs at the time of execution, also known as runtime exceptions. These include programming bugs, such as logic errors or improper use of an API. Runtime exceptions are ignored at the time of compilation.

Try/Catch and Finally

  • With the help of try/catch block we are able to catch exceptions.
  • A try/catch block is placed around the code that might generate an exception.
  • Code within a try/catch block is referred to as protected code.
try {
// Protected code
} catch (ExceptionName e1) {
// Catch block
}
  • Definition: Finally block always executes, irrespective of occurrence of an Exception.
  • Rule: It’s placed after try or catch block.
  • Benefit: Using a finally block allows you to run any cleanup-type statements that you want to execute, no matter what happens in the protected code.
try{
// Protected code
}catch(IOException | SQLException e){//multiple exception syntax
// Catch block
}finally{
// The finally block always executes.
}

Inner Class

  • Definition: Inner class is a class inside a class.
  • Inner classes can be defined inside another class (nested inner class) or another classes’ method (method local inner class).
class OuterClass {
class NestedInnerClass {
}
}
Nested Class Types
  • Anonymous inner class is a nameless inner class. An inner class declared without a class name is known as an anonymous inner class.
  • In case of anonymous inner classes, we declare and instantiate them at the same time. Generally, they are used whenever you need to override the method of a class or an interface.
AnonymousInnerClass anonInner = new AnonymousInnerClass() {
public void my_method() {
// ...
}
};
Example Anonymous Inner Class
  • Nested Inner classes vs Anonymous Inner Classes: If we’re going to use a method only once, there’s no need to write it as a seperate class. Also we can prevent inner class to be used elsewhere. On the other hand, we can use nested inner class if we’re going to use it in other places ().

Java 8 Features

Functional Interface

  • Functional interfaces are also called Single Abstract Method interfaces (SAM Interfaces). As name suggest, they permit exactly one abstract method inside them. Java 8 comes with @FunctionalInterface annotation to ensure the restrictions of functional interfaces are applied. Also, since default methods are not abstract you’re free to add default methods to your functional interface as many as you like. With default methods we can define default implementation of a method in an interface, so classes that extend the interface can directly use the method without providing any extra implementation information. Details are provided in the Default methods section.
Functional Interface Example

Lambda Expressions

  • Definition: A lambda expression (or function) is just an anonymous function, i.e., a function with no name and without being bounded to an identifier.
  • Syntax: (parameters) -> expression, (parameters) -> { statements; }, () -> expression
  • Benefits: Lambdas provide more brief and readable code. It eliminates the need of creating anonymous classes. The comparison will be provided after the examples.
Lambda Example
  • Anonymous class vs Lambda expression: Lambdas eliminate the need of writing anonymous classes. Below is the comparison of the codes():
Anonymous Inner Class vs Lambda Expression

Default methods

Java 8 allows you to add non-abstract methods in interfaces. These methods must be declared default methods. Default methods were introduces in java 8 to enable the functionality of lambda expression. Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

Default Methods Example

If a class willingly wants to customize the behavior of move() method then it can provide it’s own custom implementation and override the method.

Streams API

A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result.

Intermediate Operations

  1. map: The map method is used to map the items in the collection to other objects according to the Function passed as argument.
  2. filter: The filter method is used to select elements as per the Predicate passed as argument.
  3. sorted: The sorted method is used to sort the stream.
Intermediate Operations on Streams

Terminal Operations

  1. collect: The collect method is used to return the result of the intermediate operations performed on the stream.
  2. forEach: The forEach method is used to iterate through every element of the stream.
  3. reduce: The reduce method is used to reduce the elements of a stream to a single value.
    The reduce method takes a BinaryOperator as a parameter.

Optional

  • To prevent NullPointerExceptionand too many null checks, Optional class is introduced.
  • Optional class has multiple methods to manage null’s. empty() method creates an empty optional. ofNullable(myVariable) method returns non-empty optional if a value (myVariale) is present, empty optional if the value is absent. of() converts a variable to an optional, does not accept null values.
Java Optional Class Methods

Collections

A Java collection framework provides an architecture to store and manipulate a group of objects.

Java Collection Hierarchy (java.util)

Iterable

  • The Iterable interface is the root interface for all the collection classes.
  • Contains only one abstract method: Iterator<T> iterator()

Collection

  • The Collection interface extends the Iterable interface and therefore all the subclasses of Collection interface also implement the Iterable interface.
Methods of Collection interface

List

  • List is ordered.
  • We can store duplicates.
List Interface Implementations

ArrayList

  • ArrayList is ordered and non-synchronized.
  • Uses a dynamic array to store duplicate elements and different data types.
  • Elements can be randomly accessed.
ArrayList Example

LinkedList

  • LinkedList is ordered and non-synchronized.
  • It uses a doubly linked list.
  • Data manipulation is fast (no shifting required).
LinkedList Example

Vector

  • Vector uses a dynamic array to store the data elements.
  • It is similar to ArrayList. However, It is synchronized and contains many methods that are not the part of Collection framework.

Stack

  • The stack is the subclass of Vector.
  • It implements the LIFO (last-in-first-out) data structure, stack.
  • The stack contains all of the methods of Vector class and also provides its methods like push(), pop() and peek() which defines its properties.
Stack Example

Queue

  • Queue interface maintains the FIFO (first-in-first-out) order.
  • It is similar to an ordered list.
  • The implementations are PriorityQueue, Deque, and ArrayDeque.

PriorityQueue

  • Processes elements with respect to their priorities
  • PriorityQueue doesn’t allow null values to be stored in the queue.
  • PriorityQueue iterator does not traverse in any particular order, for ordered purpose we should use poll() method ().
PriorityQueue Example

ArrayDeque

  • Implements the Deque(double ended queue) interface.
  • Unlike queue, we can add or delete the elements from both ends.
  • ArrayDeque is faster than ArrayList and Stack and has no capacity restrictions.
ArrayDeque Example

Set

  • Unordered set of elements, duplicates not allowed
  • We can store at most one null value in Set
  • Set is implemented by HashSet, LinkedHashSet, and TreeSet.

HashSet

  • Uses hash table for storage
  • Hashing is used to store elements
  • Each element is unique
HashSet Example

LinkedHashSet

  • Represents LinkedList implementation of Set Interface.
  • Insertion order is maintained and null elements are permitted.
  • Each element is unique.
LinkedHashSet Example

SortedSet Interface

  • Elements are sorted in the increasing (ascending) order.
  • Can be instantiated as SortedSet<datatype> set = new TreeSet();

TreeSet

  • Java TreeSet class implements the Set interface that uses a tree for storage.
  • Like HashSet, TreeSet also contains unique elements. However, the access and retrieval time of TreeSet is quite fast.
  • The elements in TreeSet stored in ascending order.
TreeSet Example

DateTime API changes

A big part of developer community has been complaining about Date and Calendar classes. Reasons were many such as hard to understand, hard to use and not flexible. Date class has even become obsolete and java docs suggest to use Calendar class instead of Date class. And on top of all, Date comparison is buggy and I have also faced such issue in past.

Date class has even become obsolete. The new classes intended to replace Date class are LocalDate, LocalTime and LocalDateTime.

  • LocalDate class represents a date. There is no representation of a time or time-zone.
  • LocalTime class represents a time. There is no representation of a date or time-zone.
  • LocalDateTime class represents a date-time. There is no representation of a time-zone.
  • For representing the specific timestamp ant any moment, the class needs to be used is Instant. The Instant class represents an instant in time to an accuracy of nanoseconds.
  • Duration class is a whole new concept brought first time in java language. It represents the time difference between two time stamps.

Singleton Design Pattern

A singleton is a class that allows only a single instance of itself to be created and gives access to that created instance. It contains static variables that can accommodate unique and private instances of itself. It is used in scenarios when a user wants to restrict instantiation of a class to only one object.


Hakan Eröztekin

Written by

Founder, Full Stack Java Engineer, AI Enthusiast www.hakaneroztekin.com

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade