Core Java and Java 8 Concepts


In this post, you will see some important Core Java/Java 8 concepts related to Collections, Exception Handling, Multi-threading, Concurrency etc.

Comparable Vs Comparator

Comparable Comparator
Comparable provides a single sorting sequence. In other words, Sorting of  collection is based on a single property of a class such as ID, ItemName or quantity etc. The Comparator provides multiple sorting sequences. In other words, sorting of collection can based of multiple properties such as ID, ItemName, and quantity etc.
Comparable affects the original class, i.e., the actual class is modified. Comparator doesn’t affect the original class, i.e., the actual class is not modified.
Comparable provides compareTo() method to sort elements. Comparator provides compare() method to sort elements.
Comparable is from  java.lang package. A Comparator is from java.util package.
Sorting list of Objects-Comparable type can be done using Collections.sort(List) method. Sorting list of Objects-Comparator type by Collections.sort(List, Comparator) method.

JVM Architecture

Different types of Class Loaders?

  • Bootstrap class Loader
  • Extensions class Loader
  • System class Loader

Boostrap class loader loads the classes from jdk/jre/lib/rt.jar. Extension class loader loads the classes from jdk/lib/ext folder jars. System class loader loads the classes from CLASSPATH.

Difference between ClassNotFoundException and NoClassDefFoundError

  • ClassNotFoundException is an Exception, while NoClassDefFoundError is an Error.
  • ClassNotFoundException occurs when CLASSPATH does not get updated with required JAR files while NoClassDefFoundError occurs when required class definition is not present at runtime.

Example for NoClassDefFoundError :

class Shape {
  public void draw() {
     System.out.println("Drawing Shape!");
  }
}

public class DrawingApp {
  public void draw() {
     System.out.println("Drawing Shape!");
  }
  public static void main(String[] args) {
     Shape shape = new Shape();
     shape.draw();
  }
}

After compilation, Shape.class and DrawApp.class are generated, If Shape.class is deleted and DrawApp is run then NoClassDefFoundError is thrown.

Difference between ConcurrentHashMap and SynchronizedMap

  • ConcurrentHashMap is designed for concurrency and improves performance while Collections.synchronizedMap(map) which is non-synchronized by sort can be synchronized by applying a wrapper using Collections.synchronizedMap(map).
  • ConcurrentHashMap doesn’t support null keys or null values while synchronized HashMap supports one null key.
  • Locking in SynchronizedMap is at object level, so read/write operations performance is slower.
  • Locking in ConcurrentHashMap is at a much finer granularity at a hashmap bucket level.

Differences betwen equals() and hashcode() methods

equals() and hashCode() are methods present in Object class and hashCode method should not be used to check if two object references are same. Reason: hashCode just returns int value for an Object, even two different objects can have same hashCode integer. The value returned by hashCode() is the object’s hash code, which is the object’s memory address in hexadecimal. equals() checks if the two object references are same. If two objects are equal then their hashCode must be the same, but the reverse is not true.

O(1) vs O(n) vs O(log n)

These are measures of time complexity of running a piece of code.

O(1) – if execution time is constant, it requires the same amount of time regardless of the size. Example:  array – accessing any element int i = a[0];

O(n) – if execution time is directly proportional to the size.  Example: Linear search for an element has a time complexity of O(n).

O(log n) – if execution time is proportional to the logarithm of the input size. Example: Performing Binary Search on array of elements

Changes to HashMap in Java8

  • In case of Hash collision entry objects are stored as a node in a LinkedList and equals() method is used to compare keys. That comparison to find the correct key with in a linked-list is a linear operation so in a worst case scenario the complexity becomes O(n).
  • To address this issue, Java 8 hash elements use Balanced Tree instead of LinkedList after a certain threshold is reached. Which means HashMap starts with storing Entry objects in linked list but after the number of items in a hash becomes larger than a certain threshold, the hash will change from using a LinkedList to a Balanced Tree, which will improve the worst case performance from O(n) to O(log n).

Fail Fast Vs Fail Safe Iterators

Fail-Fast Iterators Fail-Safe Iterators
Fail-Fast iterators doesn’t allow  modifications of a collection while iterating over it. Fail-Safe iterators allow modifications of a collection while iterating over it.
Concurrent Modification Exception is thrown if a collection is modified while iterating over it. These iterators don’t throw any exceptions if a collection is modified while iterating over it.
They use original collection to traverse over the elements of the collection. They use copy of the original collection to traverse over the elements of the collection.
These iterators don’t require extra memory. These iterators require extra memory to clone the collection.
Ex : Iterators returned by ArrayList, Vector, HashMap. Ex : Iterator returned by CopyOnWriteArrayList, ConcurrentHashMap.

Difference between map() and flatmap() in Java8

Lets suppose we are applying map and flatmap on stream of streams. Example given below

Stream<List<Character>> stream = Stream.of({'a','b'},{'c','d'})

with map:  For input Stream of two lists {‘a’,’b’} and {‘c’,’d’}, output will be {{‘a’,’b’},{‘c’,’d’}} .Here two lists are placed inside a list, so the output will be list containing lists

With flat map: For input Stream of two lists {‘a’,’b’} and {‘c’,’d’}, output will be {{a,b,c,d}} .Here two lists are flattened and only the values are placed in list, so the output will be list containing only elements

What are Functional interfaces how we can define them?

Functional interfaces are interfaces which have only one single abstract method in it. Example:  Runnable Interface since it has only single abstract method, run().

From Java8, we can use @FunctionalInterface to define a functional interface. Although this annotation is optional, once it is used then declaring more than one abstract method will throw compile time error.

Rules of Method Overloading and Method Overriding

There are specific rules while we implement method overloading and overriding in Java with regards to increasing/decreasing visibility of methods of parent class in child class and throwing Checked Exceptions in child class. Complete rules are posted in this below link

https://malliktalksjava.com/2020/05/29/rules-of-method-overloading-and-overriding/

Exception Handling flow having return statements in try/catch/finally blocks

  • Once try block encounters a return statement, the flow immediately transfers to finally block. Let say,it prints “print statement from finally”.
  • Upon the completion of finally block execution, control goes back to the return statement in the try block and returns “returning from try block”.
  • If finally block has a return statement, then the return statements from try/catch blocks will be overridden.

Exception Handling flow while exceptions thrown in catch/finally blocks

  • If the catch block completes normally, then the finally block is executed. Then there is a choice:
  • If the finally block completes normally, then the try statement completes normally. If the finally block completes abruptly for any reason, then the try statement completes abruptly for the same reason.
  • If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:
    If the finally block completes normally, then the try statement completes abruptly for reason R.
    If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

FixedThreadPool vs CachedThreadPool vs ScheduledThreadPool

  • newCachedThreadPool(): creates an expandable thread pool executor. New threads are created as needed, and previously constructed threads are reused when they are available. Idle threads are kept in the pool for one minute. This executor is suitable for applications that launch many short-lived concurrent tasks.
  • newFixedThreadPool(int n): creates an executor with a fixed number of threads in the pool. This executor ensures that there are no more than n concurrent threads at any time. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread becomes available. If any thread terminates due to failure during execution, it will be replaced by a new one. The threads in the pool will exist until it is explicitly shutdown. Use this executor if you and to limit the maximum number of concurrent threads.
  • newScheduledThreadPool(int corePoolSize): creates an executor that can schedule tasks to execute after a given delay, or to execute periodically. Consider using this executor if you want to schedule tasks to execute concurrently.

What is ThreadLocal?

ThreadLocal class provides thread-local variables. It enables you to create variables that can only be read and write by the same thread. If two threads are executing the same code and that code has a reference to a ThreadLocal variable then the two threads can’t see the local variables of each other.

Diffence Volatile vs AtomicInteger?

volatile keyword is used on variables to solve the visibility problem in multi-threaded environment.  AtomicInteger is used if we perform compound operations(incrementing(i++) decrementing(i–)) on variables.

volatile is used on boolean flags, AtomicInteger is used for counters.

 

Differences between yield, join, & sleep

yield() method pauses the currently executing thread temporarily for giving a chance to the remaining waiting threads of the same priority to execute. If there is no waiting thread or all the waiting threads have a lower priority then the same thread will continue its execution. The yielded thread when it will get the chance for execution is decided by the thread scheduler whose behavior is vendor dependent.

join() If any executing thread t1 calls join() on t2 i.e; t2.join() immediately t1 will enter into waiting state until t2 completes its execution.

sleep() Based on our requirement we can make a thread to be in sleeping state for a specified period of time

Differences between Runnable and Callable

  • Runnable object does not return a result whereas a Callable object returns a result.
  • Runnable object cannot throw a checked exception wheras a Callable object can throw an exception.
  • The Runnable interface has been around since Java 1.0 whereas Callable was only introduced in Java 1.5.
class ThreadA implements Runnable {
@Override
public void run() { }
}

public class ThreadB implements Callable<String> {
@Override
public String call() throws Exception {
return "Thread B ran Successfully";
}
}

What is Semaphore in concurrency?

Semaphore is used to restrict the entry to a service to a fixed number of threads at a given time. This is generally used on slow services to make it available for fixed number of requests.

Semaphore semaphore = new Semphore(no_of_permits);

In run() method of a thread, we can use semaphore.acquire() before accessing the slow service and semaphore.release() after to ensure fixed number (defined as no_of_permits) of threads are eligible to access it.

Difference between CyclicBarrier and CountDownLatch?

Both CyclicBarrier and CountDownLatch are used in Multi threading scenario where one Thread waits for one or more Thread to complete their job before it continues processing but main difference between two is that, you can not reuse same CountDownLatch instance once count reaches to zero and latch is open, on the other hand, CyclicBarrier can be reused by resetting Barrier, Once barrier is broken.

  • Initialization of countdownlatch is CountDownLatch latch = new CountDownLatch(4);
  • Method used to countdown (generally used inside run method of thread at a specific point) is latch.countDown()
  • Method used to await a specific thread till countdown number completes is latch.await()
  • Phaser can be used either to perform functionality of both CyclicBarrier and CountDownLatch

References:
https://docs.oracle.com/en/java/javase/
https://stackoverflow.com/
https://dzone.com/

Rules of method overloading and overriding


In this post we will see the rules which needs to adhered while implementing method overriding and overloading with regards to increasing/decreasing visibility of methods of parent class in child class and throwing Checked Exceptions in child class.

Method Overriding rules

For terminology, original method is known as overridden method and new method is known as overriding method. Below rules must be followed to override a methods in Java :

  • Overriding method cannot throw checked exception which is higher in hierarchy than the checked Exception thrown by overridden method. For example if overridden method throws IOException which is checked Exception, than overriding method can not throw java.lang.Exception because it comes higher in type hierarchy.
    "Exception 'Exception' is not compatible with throws clause in" 
    
    **** Overriding method can have Runtime Exceptions declared even if Overridden method does not throw any type of Exceptions.
  • Overriding method can not reduce access of overridden method. It means if overridden method is defined as public than overriding method can not be protected or package private. Similarly if original method is protected then overriding method cannot be package-private. You can see what happens if you violate this rule in Java,
     "You cannot reduce visibility of inherited method of a class".
  • Overriding method can increase access of overridden method. This is opposite of earlier rule.
    ****According to this if overridden method is declared as protected then overriding method can be protected or public
  • private, static, final methods can not be overridden.
    "Cannot override the final method from Parent"
  • Return type of overriding method must be same as overridden method. Changing return type of method in child class will throw compile time error
    "return type is incompatible with parent class method"
    

Method Overloading rules

Here is the list of rules which must be followed to overload a method:

  • First rule to overload a method is to change method signature. method signature is made of number of arguments, type of arguments and order of arguments if they are of different types.  One can change any of these or combinations of them to overload a method in Java.
  • Return type of method is not part of method signature, hence changing the return type alone will not overload a method in Java.  In fact, it will result in compile time error.

String.join() Example – Java 8


Java 8 has String.join() method where first parameter is separator and then you can pass either multiple strings or some instance of Iterable having instances of strings as second parameter. Here is the sample program:

package in.mallikatalksjava.java8;
import java.time.ZoneId;

public class StringJoinDemo {
   public static void main(String[] args) {
	String joined = String.join("", "mallik", "talks", "java",".in");
	System.out.println(joined);
		
	String directory = String.join("/", "C:", "java", "programs");
	System.out.println(directory);

	String ids = String.join(", ", ZoneId.getAvailableZoneIds());
	System.out.println(ids);
	}
}

Output:
malliktalksjava.in
C:/java/programs
Asia/Aden, America/Cuiaba, Etc/GMT+9, Etc/GMT+8, Africa/Nairobi, America/Marigot, Asia/Aqtau ....etc.

How to convert a JKS Keystore to a PKCS12 (.p12) format


To convert a JKS (.jks) keystore to a PKCS12 (.p12) keystore, run the following command:

Note: This command is supported on JDK / JRE keytool versions 1.6 and greater.

keytool -importkeystore -srckeystore <jks_file_name.jks> -destkeystore <pk12_file_name.p12> -srcstoretype JKS -deststoretype PKCS12 -deststorepass <password>

To verify the content of .p12 (e.g. pk12_file_name.p12), run the following command:
keytool -list -v -keystore <“pk12_file_name.p12”> -storetype <password>

Create Web service using wsgen in command line


Generally bottom up approach, where the service implementation is done first and wsdl will be generated next, is not a suggested way of implementing a web service. In some cases where the service implementation class is already exists in the application and wants to expose it as web service then it is acceptable to go with bottom up approach.

In this post, I would like to show how the web service can be developed in bottom up approach using the wsgen command.

The wsgen tool reads an existing web service implementation class and generates the required JAX–WS portable artifacts for web service development and deployment. The wsgen tool can be used for bottoms-up approach, where you are starting from a service endpoint implementation rather than a wsdl. The generated JAX-WS artifacts can be used by both service and client implementations.

Below is the sample service class created – HellowWorldService.java

package in.malliktalksjava.service;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService(name=”HellowWorldService”,
targetNamespace=”http://malliktalksjava.in&#8221;,
wsdlLocation=”http://localhost:8085/HellowWorldService?wsdl&#8221;)
public class HellowWorldService{

@WebMethod
public void printHelloMessage(){
System.out.println(“Printing hello message”);
};

@WebMethod
public String getThankyouMessage(){
System.out.println(“Printing thank you message”);

return null;
};

}

Compile the java classes using below command:

javac -d . in/malliktalksjava/service/*.java

Once the compilation is successful, use the below wsgen command to generate the artifacts:

wsgen -verbose -keep -cp . in.malliktalksjava.service.HellowWorldService

Once click on the enter button, below are the artifacts generated in jaxws folder:

in\malliktalksjava\service\jaxws\GetThankyouMessage.java
in\malliktalksjava\service\jaxws\GetThankyouMessageResponse.java
in\malliktalksjava\service\jaxws\PrintHelloMessage.java
in\malliktalksjava\service\jaxws\PrintHelloMessageResponse.java

If it is required to generate the wsdl file along with the artifacts, we need to use the below command:

wsgen -verbose -keep -cp . -wsdl in.malliktalksjava.service.HellowWorldService

Below are the list of options available in wsgen command:

wsgenoptions

 

Differences between wsimport and wsgen


wsimport:

  • The wsimport tool reads a WSDL and generates all the required artifacts for web service development, deployment, and invocation.
  • It supports the top-down approach to developing JAX-WS Web services, where you are starting from a wsdl.
  • wsimport tool generated JAX-WS portable artifacts include Service Endpoint Interface (SEI), Service, Exception class mapped from wsdl:fault (if any), JAXB generated value types (mapped java classes from schema types) etc. These artifacts can be packaged in a WAR file with the WSDL and schema documents along with the endpoint implementation to be deployed.

Ex Command :

wsimport http://localhost:8090/MyJaxWSService?wsdl

wsgen:
The wsgen tool reads an existing web service implementation class and generates the required JAX–WS portable artifacts for web service development and deployment. The wsgen tool can be used for bottoms-up approach, where you are starting from a service endpoint implementation rather than a wsdl.

Ex Command :

wsgen -verbose -keep -cp . in.malliktalksjava.service.HellowWorldService
  • wsgen and wsimport generate request and response wrapper bean classes and the JAXB classes. However, wsgen generates the JAXB classes and put them in a jaxws folder and wsimport does not put those classes in any folder instead they will be placed in the current directory.
  • JAX-WS artifacts generated can be used by both service implementation and client implementation.
  • Using wsgen you can also generate the wsdl based on webservice implementation class.

Create web service in Bottom Up approach using command line


Create Service Interface MyJaxWSSEI.java

package in.malliktalksjava.ws;

import in.malliktalksjava.ws.pojo.*;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.WebParam.Mode;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.jws.soap.SOAPBinding.Use;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

@WebService(name = “MyJaxWSHello”,
targetNamespace = “http://malliktalksjava.in&#8221;,
wsdlLocation = “http://malliktalksjava.in/MyJaxWS?wsdl&#8221;)
@SOAPBinding(style=Style.RPC, use=Use.LITERAL)
public interface MyJaxWSSEI {

@WebMethod(operationName=”getJXWsRes”)
@RequestWrapper(targetNamespace=”http://malliktalksjava.in/ws/types&#8221;,
className=”java.lang.String”)
@ResponseWrapper(targetNamespace=”http://malliktalksjava.in/ws/types&#8221;,
className=”in.malliktalksjava.ws.JXRes”)
@WebResult(targetNamespace=”http://malliktalksjava.in/ws/types&#8221;,
name=”JXWsRes”)
public JXRes getJXWsRes(
@WebParam(targetNamespace=”http://malliktalksjava.in/ws/types&#8221;,
name=”name”,
mode=Mode.IN)
String name
);

}

 

Create Implementation class for the above interface – MyJaxWSSEIImpl.java

package in.malliktalksjava.ws;

import in.malliktalksjava.ws.pojo.*;
import javax.jws.WebService;

@WebService(endpointInterface=”in.malliktalksjava.ws.MyJaxWSSEI”,
targetNamespace=”http://malliktalksjava.in&#8221;,
portName=”MyJaxWSSEIPort”,
serviceName=”MyJaxWSHelloService”)
public class MyJaxWSSEIImpl implements MyJaxWSSEI {

/**
* Default Constructor
*/
public MyJaxWSSEIImpl() {

}

/* (non-Javadoc)
* @see in.malliktalksjava.ws.MyJaxWSSEI#getJXWsRes(java.lang.String)
*/
@Override
public JXRes getJXWsRes(String name) {
JXRes jxRes = new JXRes();
jxRes.setMessage(“Hello”);
jxRes.setName(name);
return jxRes;
}

}

Create Required Model object JXRes.java

package in.malliktalksjava.ws.pojo;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class JXRes {
protected String message;
protected String name;
/**
*
*/
public JXRes() {
super();
}
/**
* @return the id
*/
public String getMessage() {
return message;
}
/**
* @param id the id to set
*/
public void setMessage(String message) {
this.message = message;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}

}

Create Main Class JXResTest.java

package in.malliktalksjava.ws.main;

import javax.xml.ws.Endpoint;
import in.malliktalksjava.ws.*;

public class JXResTest {
public static void main(String[] args ){
Endpoint.publish(“http://localhost:8080/MyJaxWSService&#8221;, new MyJaxWSSEIImpl());
}
}

 

Compile Java Classes in command prompt:

compileclass

Run the class

runmainclass

Verify the service : http://localhost:8080/MyJaxWSService?wsdl

wsdl

 

Difference between ClassNotFoundException and NoClassDefFoundError


1. java.lang.ClassNotFoundException :  This exception indicates that the class was not found on the classpath. This indicates that we were trying to load the class definition, and the class did not exist on the classpath.

2. java.lang.NoClassDefFoundError :  This exception indicates that the JVM looked in its internal class definition data structure for the definition of a class and did not find it. This is different than saying that it could not be loaded from the classpath. Usually this indicates that we previously attempted to load a class from the classpath, but it failed for some reason – now we’re trying to use the class again (and thus need to load it, since it failed last time), but we’re not even going to try to load it, because we failed loading it earlier (and reasonably suspect that we would fail again). The earlier failure could be a ClassNotFoundException or an ExceptionInInitializerError (indicating a failure in the static initialization block) or any number of other problems. The point is, a NoClassDefFoundError is not necessarily a classpath problem.

Difference between HttpSession’s getSession(), getSession(true) and getSession(false) methods


  • getSession() : Returns the current session associated with this request, or if the request does not have a session, creates one.
  • getSession(true) : Returns the current HttpSession associated with this request, if there is no current session, returns a new session
  • getSession(false) : Returns the current HttpSession associated with this request, if there is no current session, returns null.

How to read a URL using Java?


  • Below program consists of steps to read data from the URL
package in.malliktalksjava;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

/**
* @author malliktalksjava
*
*/
public class URLConnectionReader {

public static void main(String[] args) throws Exception {

URL oracle = new URL("http://malliktalksjava.in/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
}
}