Java SE 8 Interview Questions and Answers - 1

From Rasim SEN - Knowledge Base/Java/Springframework/Microservices/Cloud-AWS/AI
Jump to: navigation, search

Contents

What new features were added in Java 8?

Java 8 ships with several new features but the most significant are the following:

  • Lambda Expressions − a new language feature allowing treating actions as objects
  • Method References − enable defining Lambda Expressions by referring to methods directly using their names
  • Optional − special wrapper class used for expressing optionality
  • Functional Interface – an interface with maximum one abstract method, implementation can be provided using a Lambda Expression
  • Default methods − give us the ability to add full implementations in interfaces besides abstract methods
  • Nashorn, JavaScript Engine − Java-based engine for executing and evaluating JavaScript code
  • Stream API − a special iterator class that allows processing collections of objects in a functional manner
  • Date API − an improved, immutable JodaTime-inspired Date API

Along with these new features, lots of feature enhancements are done under-the-hood, at both compiler and JVM level.

What is a method reference?

A method reference is a Java 8 construct that can be used for referencing a method without invoking it. It is used for treating methods as Lambda Expressions. They only work as syntactic sugar to reduce the verbosity of some lambdas. This way, the following code:

(o) -> o.toString();

can become:

Object::toString();

A method reference can be identified by a double colon separating a class or object name and the name of the method. It has different variations such as constructor reference:

String::new;

Static method reference:

String::valueOf;

Bound instance method reference:

str::toString;

Unbound instance method reference:

String::toString;


What is the meaning of String::valueOf expression?

It is a static method reference to the valueOf method of the String class.

What is Optional? How can it be used?

Optional is a new class in Java 8 that encapsulates an optional value i.e. a value that is either there or not. It is a wrapper around an object, and you can think of it as a container of zero or one element.

Optional has a special Optional.empty() value instead of wrapped null. Thus it can be used instead of a nullable value to get rid of NullPointerException in many cases.

You can read a dedicated article about Optional here.

The main purpose of Optional, as designed by its creators, was to be a return type of methods that previously would return null. Such methods would require you to write boilerplate code to check the return value and sometimes could forget to do a defensive check. In Java 8, an Optional return type explicitly requires you to handle null or non-null wrapped values differently.

For instance, the Stream.min() method calculates the minimum value in a stream of values. But what if the stream is empty? If it was not for Optional, the method would return null or throw an exception.

But it returns an Optional value which may be Optional.empty() (the second case). This allows us to easily handle such case:

int min1 = Arrays.stream(new int[]{1, 2, 3, 4, 5})
  .min()
  .orElse(0);
assertEquals(1, min1);
 
int min2 = Arrays.stream(new int[]{})
  .min()
  .orElse(0);
assertEquals(0, min2);

It’s worth noting that Optional is not a general purpose class like Option in Scala. It is not recommended to be used as a field value in entity classes, which is clearly indicated by it not implementing the Serializable interface.

Describe some of the functional interfaces in the standard library?

There are a lot of functional interfaces in the java.util.function package, the more common ones include but not limited to:

  • Function – it takes one argument and returns a result
  • Consumer – it takes one argument and returns no result (represents a side effect)
  • Supplier – it takes not argument and returns a result
  • Predicate – it takes one argument and returns a boolean
  • BiFunction – it takes two arguments and returns a result
  • BinaryOperator – it is similar to a BiFunction, taking two arguments and returning a result. The two arguments and the result are all of the same types
  • UnaryOperator – it is similar to a Function, taking a single argument and returning a result of the same type

What is a functional interface? What are the rules of defining a functional interface?

A functional interface is an interface with no more, no less but one single abstract method (default methods do not count).

Where an instance of such interface is required, a Lambda Expression can be used instead. More formally put: Functional interfaces provide target types for lambda expressions and method references.

The arguments and return type of such expression directly match those of the single abstract method.

For instance, the Runnable interface is a functional interface, so instead of:

Thread thread = new Thread(new Runnable() {
    public void run() {
        System.out.println("Hello World!");
    }
});

you could simply do:

Thread thread = new Thread(() -> System.out.println("Hello World!"));

Functional interfaces are usually annotated with the @FunctionalInterface annotation – which is informative and does not affect the semantics.

What is a default method and when do we use it?

A default method is a method with an implementation – which can be found in an interface.

We can use a default method to add a new functionality to an interface while maintaining backward compatibility with classes that are already implementing the interface:

public interface Vehicle {
    public void move();
    default void hoot() {
        System.out.println("peep!");
    }
}


Usually, when a new abstract method is added to an interface, all implementing classes will break until they implement the new abstract method. In Java 8, this problem has been solved by the use of default method.

For example, Collection interface does not have forEach method declaration. Thus, adding such method would simply break the whole collections API.

Java 8 introduces default method so that Collection interface can have a default implementation of forEach method without requiring the classes implementing this interface to implement the same.


Will the following code compile?

@FunctionalInterface
public interface Function2<T, U, V> {
    public V apply(T t, U u);
 
    default void count() {
        // increment counter
    }
}


Yes. The code will compile because it follows the functional interface specification of defining only a single abstract method. The second method, count, is a default method that does not increase the abstract method count.


What is a Lambda Expression and what is it used for?

In very simple terms, a lambda expression is a function that can be referenced and passed around as an object.

Lambda expressions introduce functional style processing in Java and facilitate the writing of compact and easy-to-read code.

Because of this, lambda expressions are a natural replacement for anonymous classes as method arguments. One of their main uses is to define inline implementations of functional interfaces.

Explain the syntax and characteristics of a Lambda Expression?

A lambda expression consists of two parts: the parameter part and the expressions part separated by a forward arrow as below:

params -> expressions

Any lambda expression has the following characteristics:

  • Optional type declaration – when declaring the parameters on the left-hand side of the lambda, we don’t need to declare their types as the compiler can infer them from their values. So int param -> … and param ->… are all valid
  • Optional parentheses – when only a single parameter is declared, we don’t need to place it in parentheses. This means param -> … and (param) -> … are all valid. But when more than one parameter is declared, parentheses are required
  • Optional curly braces – when the expressions part only has a single statement, there is no need for curly braces. This means that param – > statement and param – > {statement;} are all valid. But curly braces are required when there is more than one statement
  • Optional return statement – when the expression returns a value and it is wrapped inside curly braces, then we don’t need a return statement. That means (a, b) – > {return a+b;} and (a, b) – > {a+b;} are both valid

What is Nashorn in Java8?

Nashorn is the new Javascript processing engine for the Java platform that shipped with Java 8. Until JDK 7, the Java platform used Mozilla Rhino for the same purpose. as a Javascript processing engine.

Nashorn provides better compliance with the ECMA normalized JavaScript specification and better runtime performance than its predecessor.

What is jjs?

In Java 8, jjs is the new executable or command line tool used to execute Javascript code at the console.

What is the difference between intermediate and terminal operations?

Stream operations are combined into pipelines to process streams. All operations are either intermediate or terminal.

Intermediate operations are those operations that return Stream itself allowing for further operations on a stream.

These operations are always lazy, i.e. they do not process the stream at the call site, an intermediate operation can only process data when there is a terminal operation. Some of the intermediate operations are filter, map and flatMap.

Terminal operations terminate the pipeline and initiate stream processing. The stream is passed through all intermediate operations during terminal operation call. Terminal operations include forEach, reduce, Collect and sum.

To drive this point home, let us look at an example with side effects:

public static void main(String[] args) {
    System.out.println("Stream without terminal operation");
     
    Arrays.stream(new int[] { 1, 2, 3 }).map(i -> {
        System.out.println("doubling " + i);
        return i * 2;
    });
  
    System.out.println("Stream with terminal operation");
        Arrays.stream(new int[] { 1, 2, 3 }).map(i -> {
            System.out.println("doubling " + i);
            return i * 2;
    }).sum();
}

The output will be as follows:

Stream without terminal operation
Stream with terminal operation
doubling 1
doubling 2
doubling 3

As you can see, the intermediate operations are only triggered when a terminal operation exists.

==What is the difference between map and flatMap stream operation? There is a difference in signature between map and flatMap. Generally speaking, a map operation wraps its return value inside its ordinal type while flatMap does not.

For example, in Optional, a map operation would return Optional<String> type while flatMap would return String type.

So after mapping, one needs to unwrap (read “flatten”) the object to retrieve the value whereas, after flat mapping, there is no such need as the object is already flattened. The same concept is applied to mapping and flat mapping in Stream.

Both map and flatMap are intermediate stream operations that receive a function and apply this function to all elements of a stream.

The difference is that for the map, this function returns a value, but for flatMap, this function returns a stream. The flatMap operation “flattens” the streams into one.

Here’s an example where we take a map of users’ names and lists of phones and “flatten” it down to a list of phones of all the users using flatMap:

Map<String, List<String>> people = new HashMap<>();
people.put("John", Arrays.asList("555-1123", "555-3389"));
people.put("Mary", Arrays.asList("555-2243", "555-5264"));
people.put("Steve", Arrays.asList("555-6654", "555-3242"));
 
List<String> phones = people.values().stream()
  .flatMap(Collection::stream)
    .collect(Collectors.toList());



Java SE 8 New Features?

  • Lambda Expressions
  • Functional Interfaces
  • Stream API
  • Date and Time API
  • Interface Default Methods and Static Methods
  • Spliterator
  • Method and Constructor References
  • Collections API Enhancements
  • Concurrency Utils Enhancements
  • Fork/Join Framework Enhancements
  • Internal Iteration
  • Parallel Array and Parallel Collection Operations
  • Optional
  • Type Annotations and Repeatable Annotations
  • Method Parameter Reflection
  • Base64 Encoding and Decoding
  • IO and NIO2 Enhancements
  • Nashorn JavaScript Engine
  • javac Enhancements
  • JVM Changes
  • Java 8 Compact Profiles: compact1,compact2,compact3
  • JDBC 4.2
  • JAXP 1.6
  • Java DB 10.10
  • Networking
  • Security Changes


Advantages of Java SE 8 New Features?

we can get the following benefits from Java SE 8 New Features:

  • More Concise and Readable code
  • More Reusable code
  • More Testable and Maintainable Code
  • Highly Concurrent and Highly Scalable Code
  • Write Parallel Code
  • Write Database Like Operations
  • Better Performance Applications
  • More Productive code

What is Lambda Expression?

Lambda Expression is an anonymous function which accepts a set of input parameters and returns results.

Lambda Expression is a block of code without any name, with or without parameters and with or without results. This block of code is executed on demand.

What are the three parts of a Lambda Expression? What is the type of Lambda Expression?

A Lambda Expression contains 3 parts:

  • Parameter List

A Lambda Expression can contain zero or one or more parameters. It is optional.

  • Lambda Arrow Operator

“->” is known as Lambda Arrow operator. It separates parameters list and body.

  • Lambda Expression Body

What is the type of the following Lambda Expression?

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

This Lambda Expression does not have parameters and does return any results. So it’s type is “java.lang.Runnable” Functional Interface.

What is a Functional Interface? What is SAM Interface?

A Functional Interface is an interface, which contains one and only one abstract method. Functional Interface is also know as SAM Interface because it contains only one abstract method.

SAM Interface stands for Single Abstract Method Interface. Java SE 8 API has defined many Functional Interfaces.

Is is possible to define our own Functional Interface? What is @FunctionalInterface? What are the rules to define a Functional Interface?

Yes, it is possible to define our own Functional Interfaces. We use Java SE 8’s @FunctionalInterface annotation to mark an interface as Functional Interface.


We need to follow these rules to define a Functional Interface:

  • Define an interface with one and only one abstract method.
  • We cannot define more than one abstract method.
  • Use @FunctionalInterface annotation in interface definition.
  • We can define any number of other methods like Default methods, Static methods.
  • If we override java.lang.Object class’s method as an abstract method, which does not count as an abstract method.

Is @FunctionalInterface annotation mandatory to define a Functional Interface? What is the use of @FunctionalInterface annotation? Why do we need Functional Interfaces in Java?

It is not mandatory to define a Functional Interface with @FunctionalInterface annotation. If we don’t want, We can omit this annotation. However, if we use it in Functional Interface definition, Java Compiler forces to use one and only one abstract method inside that interface.

Why do we need Functional Interfaces? -The type of a Java SE 8’s Lambda Expression is a Functional Interface. Whereever we use Lambda Expressions that means we are using Functional Interfaces.

When do we go for Java 8 Stream API? Why do we need to use Java 8 Stream API in our projects?

When our Java project wants to perform the following operations, it’s better to use Java 8 Stream API to get lot of benefits:

  • When we want perform Database like Operations. For instance, we want perform groupby operation, orderby operation etc.
  • When want to Perform operations Lazily.
  • When we want to write Functional Style programming.
  • When we want to perform Parallel Operations.
  • When want to use Internal Iteration
  • When we want to perform Pipelining operations.
  • When we want to achieve better performance.

Explain Differences between Collection API and Stream API?

COLLECTION APISTREAM API
It’s available since Java 1.2It is introduced in Java SE8
It is used to store Data(A set of Objects).It is used to compute data(Computation on a set of Objects).
We can use both Spliterator and Iterator to iterate elements. We can use forEach to performs an action for each element of this stream.We can’t use Spliterator or Iterator to iterate elements.
It is used to store limited number of Elements.It is used to store either Limited or Infinite Number of Elements.
Typically, it uses External Iteration concept to iterate Elements such as Iterator.Stream API uses External Iteration to iterate Elements, using forEach methods.
Collection Object is constructed Eagerly.Stream Object is constructed Lazily.
We add elements to Collection object only after it is computed completely.We can add elements to Stream Object without any prior computation. That means Stream objects are computed on-demand.
We can iterate and consume elements from a Collection Object at any number of times.We can iterate and consume elements from a Stream Object only once.

What is Spliterator in Java SE 8?Differences between Iterator and Spliterator in Java SE 8?

Spliterator stands for Splitable Iterator. It is newly introduced by Oracle Corporation as part Java SE 8. Like Iterator and ListIterator, It is also one of the Iterator interface.


SPLITERATOR ITERATOR
It is introduced in Java SE 8. It is available since Java 1.2.
Splitable Iterator Non-Splitable Iterator
It is used in Stream API. It is used for Collection API.
It uses Internal Iteration concept to iterate Streams. It uses External Iteration concept to iterate Collections.
We can use Spliterator to iterate Streams in Parallel and Sequential order. We can use Iterator to iterate Collections only in Sequential order.
We can get Spliterator by calling spliterator() method on Stream Object. We can get Iterator by calling iterator() method on Collection Object.
Important Method: tryAdvance() Important Methods: next(), hasNext()

What is Optional in Java 8? What is the use of Optional?Advantages of Java 8 Optional?

Optional:Optional is a final Class introduced as part of Java SE 8. It is defined in java.util package.

It is used to represent optional values that is either exist or not exist. It can contain either one value or zero value. If it contains a value, we can get it. Otherwise, we get nothing.

It is a bounded collection that is it contains at most one element only. It is an alternative to “null” value.

Main Advantage of Optional is:

  • It is used to avoid null checks.
  • It is used to avoid “NullPointerException”.

What is Type Inference? Is Type Inference available in older versions like Java 7 and Before 7 or it is available only in Java SE 8?

Type Inference means determining the Type by compiler at compile-time.

It is not new feature in Java SE 8. It is available in Java 7 and before Java 7 too.

Before Java 7: Let us explore Java arrays. Define a String of Array with values as shown below:

String str[] = { "Java 7", "Java 8", "Java 9" };

Here we have assigned some String values at right side, but not defined it’s type. Java Compiler automatically infers it’s type and creates a String of Array.

Java 7: Oracle Corporation has introduced “Diamond Operator” new feature in Java SE 7 to avoid unnecessary Type definition in Generics.

Map<String,List<Customer>> customerInfoByCity = new HashMap<>();

Here we have not defined Type information at right side, simply defined Java SE 7’s Diamond Operator “”.

Java SE 8: Oracle Corporation has enhanced this Type Inference concept a lot in Java SE 8. We use this concept to define Lambda Expressions, Functions, Method References etc.

<soource> ToIntBiFunction<Integer,Integer> add = (a,b) -> a + b; </source>


Here Java Compiler observes the type definition available at left-side and determines the type of Lambda Expression parameters a and b as Integers.


Differences between Functional Programming and Object-Oriented Programming?

FUNCTIONAL PROGRAMMING OOP
Does not exist State Exists State
Uses Immutable data Uses Mutable data
It follows Declarative Programming Model It follows Imperative Programming Model
Stateless Programming ModelStateful Programming Model
Main Fcous on: “What you are doing” Main focus on “How you are doing”
Good for Parallel (Concurrency) Programming Poor for Parallel (Concurrency) Programming
Good for BigData processing and analysis NOT Good for BigData processing and analysis
Supports pure Encapsulation It breaks Encapsulation concept
Functions with No-Side Effects Methods with Side Effects
Functions are first-class citizens Objects are first-class citizens
Primary Manipulation Unit is “Function” Primary Manipulation Unit is Objects(Instances of Classes)
Flow Controls: Function calls, Function Calls with Recursion Flow Controls: Loops, Conditional Statements
It uses “Recursion” concept to iterate Collection Data. It uses “Loop” concept to iterate Collection Data. For example:-For-each loop in Java
Order of execution is less importance.Order of execution is must and very important.
Supports both “Abstraction over Data” and “Abstraction over Behavior”. Supports only “Abstraction over Data”.
We use FP when we have few Things with more operations. We use OOP when we have few Operations with more Things. For example: Things are classes and Operations are Methods in Java.

Explain issues of Old Java Date API? What are the advantages of Java 8’s Date and Time API over Old Date API and Joda Time API?

Java’s OLD Java Date API means Date API available before Java SE 8 that is Date, Calendar, SimpleDateFormat etc.

Java’s Old Date API has the following Issues or Drawbacks compare to Java 8’s Date and Time API and Joda Time API.

  • Most of the API is deprecated.
  • Less Readability.
  • java.util.Date is Mutable and not Thread-Safe.
  • java.text.SimpleDateFormat is not Thread-Safe.
  • Less Performance.

Java SE 8’s Date and Time API has the following Advantages compare to Java’s OLD Date API.

  • Very simple to use.
  • Human Readable Syntax that is More Readability.
  • All API is Thread-Safe.
  • Better Performance.

Why do we need new Date and Time API in Java SE 8?Explain how Java SE 8 Data and Time API solves issues of Old Java Date API?

We need Java 8’s Date and Time API to develop Highly Performance, Thread-Safe and Highly Scalable Java Applications.

Java 8’s Date and Time API solves all Java’s Old Date API issues by following Immutability and Thread-Safety principles.

What is Multiple Inheritance? How Java 8 supports Multiple Inheritance?

Multiple Inheritance means a class can inherit or extend characteristics and features from more than one parent class.

In Java 7 or Earlier, Multiple Inheritance is not possible because Java follows “A class should extend one and only one class or abstract class” Rule. However, it’s possible to provide Multiple Implementation Inheritance using Interface because Java follows “A class can extend any number of Interfaces” Rule.

However, Java 8 supports “Implementing Methods in Interfaces” by introducing new features: Default methods in Interface. Because of this feature, Java 8 supports Multiple Inheritance with some limitations.

What is Diamond Problem in Inheritance? How Java 8 Solves this problem?

A Diamond Problem is a Multiple Inheritance problem. In Java, It occurs when a Class extends more than one Interface which have same method implementation (Default method).

diamond_problem-450x310.png

This above diagram shows Diamond Problem. To avoid this problem, Java 7 and Earlier versions does not support methods implementation in interface and also doesn’t support Multiple Inheritance. Java 8 has introduced new feature: Default methods to support Multiple Inheritance with some limitations.

Sample Java SE 8 Code to show this Diamond Problem:

public interface A{   
  default void display() { //code goes here }
}
public interface B extends A{ }
public interface C extends A{ }
public class D implements B,C{ }

In the above code snippet, class D gives compiltime errors because Java Compiler will get bit confusion about which display() has to provide in class D. Class D inherits display() method from both interfaces B and C. To solve this problem, Java SE 8 has given the following remedy:

public interface A{   
  default void display() { //code goes here }
}
public interface B extends A{ }
public interface C extends A{ }
public class D implements B,C{
  void display() { 
    B.super.display();       
  }
}

This B.super.display(); will solve this Diamond Problem.


What is stream pipelining in Java 8?

Stream pipelining is the concept of chaining operations together. This is done by splitting the operations that can happen on a stream into two categories: intermediate operations and terminal operations.

Each intermediate operation returns an instance of Stream itself when it runs, an arbitrary number of intermediate operations can, therefore, be set up to process data forming a processing pipeline.

There must then be a terminal operation which returns a final value and terminates the pipeline.


What is the difference between intermediate and terminal operations?

A Stream supports several operations and these operations are divided into intermediate and terminal operations.

  • The distinction between this operations is that an intermediate operation is lazy while a terminal operation is not.
  • When you invoke an intermediate operation on a stream, the operation is not executed immediately. It is executed only when a terminal operation is invoked on that stream.
  • In a way, an intermediate operation is memorized and is recalled' as soon as a terminal operation is invoked.
  • You can chain multiple intermediate operations and none of them will do anything until you invoke a terminal operation.
  • At that time, all of the intermediate operations that you invoked earlier will be invoked along with the terminal operation.

All intermediate operations return Stream (can be chained), while terminal operations don't.

Intermediate Operations are:

filter(Predicate<T>)
map(Function<T>)
flatmap(Function<T>)
sorted(Comparator<T>)
peek(Consumer<T>)
distinct()
limit(long n)
skip(long n)

Terminal operations produces a non-stream (cannot be chained) result such as primitive value, a collection or no value at all.

Terminal Operations are:

forEach
toArray
reduce
collect
min
max
count
anyMatch
allMatch
noneMatch
findFirst    
findAny


Last 5 are short-circuiting terminal operations.