Learning Today,
Leading Tomorrow

Daemon threads:

Daemon threads are useful for background supporting tasks such as garbage collection, releasing memory of unused objects and removing unwanted entries from the cache.

Most of the JVM threads are daemon threads. Daemon threads is a low priority thread that provide supports to user threads. These threads can be user defined and system defined as well. 

Garbage collection thread is one of the system generated daemon thread that runs in background. These threads run in the background to perform tasks such as garbage collection. 

Daemon thread does allow JVM from existing until all the threads finish their execution. When a JVM founds daemon threads it terminates the thread and then shutdown itself, it does not care Daemon thread whether it is running or not.

Abstract class:

A class which is declared with the abstract keyword is known as an abstract class in Java. It can have abstract and non-abstract methods (method with the body).

An abstract class is mostly used to provide a base for subclasses to extend and implement the abstract methods and override or use the implemented methods in abstract class.

 public abstract class InputStream extends Object implements Closeable

 public abstract class OutputStream extends Object implements Closeable, Flushable

 public abstract class Enum<E extends Enum<E>> extends Object implements Comparable<E>, Serializable

Abstraction in Java

Abstraction is a process of hiding the implementation details and showing only functionality to the user.

It is a process of hiding complex internal implementation details from the user and providing only necessary functionality to the users.

Another way, it shows only essential things to the user and hides the internal details, for example, sending SMS where you type the text and send the message. We don't know the internal processing about the message delivery.

Abstraction in Java is a technique by which we can hide the data that is not required to a user.

It hides all unwanted data so that users can work only with the required data. It removes all non-essential things and shows only important things to users.

Abstraction lets you focus on what the object does instead of how it does it.

Ways to achieve Abstraction:

Abstract class (0 to 100%)

Interface (100%)

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.

Points to Remember

An abstract class must be declared with an abstract keyword.

It can have abstract and non-abstract methods.

It cannot be instantiated.

It can have constructors and static methods also.

It can have final methods which will force the subclass not to change the body of the method.

An abstract class can be used when we need to share the same method to all non-abstract subclasses with their own specific implementations.

Moreover, the common member of the abstract class can also be shared by the subclasses. Thus, abstract class is useful to make the program more flexible and understandable.

A method that is declared with abstract modifier in an abstract class and has no implementation (means no body) is called abstract method in java. It does not contain any body.

It has simply a signature declaration followed by a semicolon.

1. An abstract method can be used when the same method has to perform different tasks depending on the object calling it.

2. A method can be used as abstract when you need to be overridden in its non-abstract subclasses.

1. Abstract class is not a pure abstraction in java.

2. In Java, object creation is not possible for an abstract class because it is a partially implemented class, not fully implemented class.

3. It can be abstract even without any abstract method.

4. It can have one or more abstract methods or non-abstract methods (or concrete methods) or combination of both methods.

5. Abstract class allows to define private, final, static and concrete methods. Everything is possible to define in an abstract class as per application requirements.

6. It can have constructors.

7.  Abstract class does not support multiple inheritance in java but allows in interfaces.

8. It can implement one or more interfaces in java.

Rules of Abstract class in Java

1. Class must be declared with abstract keyword to make an abstract class.

2. We cannot instantiate an abstract class but we can create object of subclass of the abstract class provided they must implement abstract method.

3. If any method is abstract in a class, the class must be declared as abstract.

4. To use methods declared in an abstract class, the abstract class must be extended by an ordinary class and must implement (override) all abstract methods in that ordinary class.

5. If a new abstract method is added in the abstract class, all non-abstract subclass which extends that abstract class, must implement the newly added abstract method. If it does not implement all the abstract method, the class must be declared as abstract.

6. If a new instance method is added in the abstract class, all non-abstract subclass which extends that abstract class, is not necessary to implement newly added instance method.

7. Inside the abstract class, we can create any number of constructors. If you do not create a constructor, the compiler will create a default constructor.

Rules of Abstract method in Java:

1. Abstract method can only be declared in an abstract class.

2. A non-abstract class cannot have an abstract method whether it is inherited or declared in Java.

3. It must not provide a method body/implementation in the abstract class for which it is defined.

4. Method name and signature must be the same as in the abstract class.

5. The visibility of the method in the subclass cannot be reduced while overriding abstract method.

6. Abstract method cannot be static or final.

7. It cannot be private because the abstract method must be implemented in the subclass. If we declare it private, we cannot implement it from outside the class.

Let’s take some example programs based on these rules to understand the abstract class and abstract method concepts more clearly.

Why abstract class has constructor even though we cannot create object?

We cannot create an object of abstract class but we can create an object of subclass of abstract class. When we create an object of subclass of an abstract class, it calls the constructor of subclass.

This subclass constructor has super in the first line that calls constructor of an abstract class. Thus, the constructors of an abstract class are used from constructor of its subclass.

If the abstract class doesn’t have a constructor, a class that extends that abstract class will not get compiled.

Thus, the super class constructor is executing when creating an object of subclass. By executing this superclass constructor, JVM is initializing to non-static variables name and id in the abstract class.

Now suppose if an abstract class does not allow to define constructor, in such a case, is it possible to initialize the value of non-static variables in abstract class?

Answer is no because, without object creation of abstract class, we cannot initialize non-static variables. Therefore,  an abstract class allows constructors to initialize variables.

Why should we create reference to superclass (abstract class reference)?

We should create a reference of the superclass to access subclass features because superclass reference allows only to access those features of subclass which have already declared in superclass.

If you create an individual method in subclass, the superclass reference cannot access that method. Thus, any programmer cannot add their own additional features in subclasses other than whatever is given in superclass.

Advantage of Abstract class in Java

Abstract class makes programming better and more flexible by giving the scope of implementing abstract methods.

Programmers can implement an abstract method to perform different tasks depending on the need.

We can easily manage code.

Thread vs runnable

Thread

Thread is a class. It is used to create a thread    | Runnable is a functional interface which is used to create a thread 

It has multiple methods including start() and run() It has only abstract method run()

Multiple Inheritance is not allowed in java hence after a class extends Thread class, it can not extend any other classIf a class is implementing the runnable interface then your class can extend another class.

When we extend Thread class, each of our thread creates unique object and associate with it. | When we implements Runnable, it shares the same object to multiple threads.


Singleton break and how to prevent them

1. Reflection API

Using the Reflection API, we can create multiple objects in the Singleton class.

Constructor constructor = Singleton.class.getDeclaredConstructor();

constructor.setAccessible(true);

objTwo = (Singleton) constructor.newInstance();

Prevent Singleton Pattern From Reflection

Throw a run-time exception in the constructor if the instance already exists.

2.Deserialization

In serialization, we can save the object of a byte stream into a file or send over a network. Suppose if you serialize the Singleton class, and then again de-serialize that object, it will create a new instance, hence deserialization will break the Singleton pattern. 

Singleton instanceOne = Singleton.getInstance();

ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.text"));

out.writeObject(instanceOne);

out.close();

ObjectInput in = new ObjectInputStream(new FileInputStream("file.text"));

Singleton instanceTwo = (Singleton) in.readObject();

in.close();

System.out.println("hashCode of instance 1 is - " + instanceOne.hashCode());

System.out.println("hashCode of instance 2 is - " + instanceTwo.hashCode());

Prevent Singleton Pattern From Deserialization

Override readResolve() method in the Singleton class and return the same Singleton instance

     protected Object readResolve() { 

           return instance; 

     }  


3.Cloning

Using the "clone" method, we can create a copy of the original object; it's the same thing if we applied clone in the singleton pattern. It will create two instances: one original and another one cloned object. In this case, we will break the Singleton principle, as shown in the below code.

Singleton instanceOne = Singleton.getInstance();

Singleton instanceTwo = (Singleton) instanceOne.clone();

Prevent Singleton Pattern From Cloning

we need to implement/override the clone() method and throw an exception CloneNotSupportedException from the clone method. If anyone tries to create a clone object of Singleton

protected Object clone() throws CloneNotSupportedException  {

        throw new CloneNotSupportedException();

    }


Checked vs unchecked exception : 

Checked are the exceptions that are checked at compile time. If some code within a method throws a checked exception, then the method must either handle the exception or it must specify the exception using throws keyword.

Unchecked are the exceptions that are not checked at compiled time.

In Java exceptions under Error and RuntimeException classes are unchecked exceptions, everything else under throwable is checked.

Exception Handling with Method Overriding

If the superclass method does not declare an exception, subclass overridden method cannot declare the checked exception but it can declare unchecked exception.

If the superclass method declares an exception, subclass overridden method can declare same, subclass exception or no exception but cannot declare parent exception.

Volatile and transient:

The Volatile keyword is used to mark the JVM and thread to read its value from primary memory and not utilize cached value present in the thread stack. It is used in concurrent programming in java.

The Transient keyword is used with the instance variable to eliminate it from the serialization process. During serialization, the value of the transient field or variable is not saved.

It is simply used to achieve thread-safety. If you mark any variable as volatile, then all the threads can read its value directly from the main memory rather than CPU cache, so that each thread can get an updated value of the variable.

Create constructor for abstract and interface -->

If you do not define your own constructor, the compiler will give a default constructor to the Abstract class.

When we define a class to be an Abstract Class it cannot be instantiated but that does not mean an Abstract class cannot have a constructor. Each abstract class must have a concrete subclass which will implement the abstract methods of that abstract class.

When we create an object of any subclass all the constructors in the corresponding inheritance tree are invoked in the top to bottom approach. 

The same case applies to abstract classes. Though we cannot create an object of an abstract class, when we create an object of a class which is concrete and subclass of the abstract class, the constructor of the abstract class is automatically invoked. Hence we can have a constructor in abstract classes.

ArrayList, LinkedList, and Vector are all implementations of the List interface. Which of them is most efficient for adding and removing elements from the list? Explain your answer, including any other alternatives you may be aware of.

Of the three, LinkedList is generally going to give you the best performance. Here’s why:

ArrayList and Vector each use an array to store the elements of the list. As a result, when an element is inserted into (or removed from) the middle of the list, the elements that follow must all be shifted accordingly. 

Vector is synchronized, so if a thread-safe implementation is not needed, it is recommended to use ArrayList rather than Vector.

LinkedList, on the other hand, is implemented using a doubly linked list. As a result, an inserting or removing an element only requires updating the links that immediately precede and follow the element being inserted or removed.

Why would it be more secure to store sensitive data (such as a password, social security number, etc.) in a character array rather than in a String?

In Java, Strings are immutable and are stored in the String pool. What this means is that, once a String is created, it stays in the pool in memory until being garbage collected. Therefore, even after you’re done processing the string value (e.g., the password), it remains available in memory for an indeterminate period of time thereafter (again, until being garbage collected) which you have no real control over. Therefore, anyone having access to a memory dump can potentially extract the sensitive data and exploit it.

In contrast, if you use a mutable object like a character array, for example, to store the value, you can set it to blank once you are done with it with confidence that it will no longer be retained in memory.

What is the volatile keyword ? How and why would you use it?

In Java, each thread has its own stack, including its own copy of variables it can access. When the thread is created, it copies the value of all accessible variables into its own stack. The volatile keyword basically says to the JVM “Warning, this variable may be modified in another Thread”.

In all versions of Java, the volatile keyword guarantees global ordering on reads and writes to a variable. This implies that every thread accessing a volatile field will read the variable’s current value instead of (potentially) using a cached value.

One common example for using volatile is for a flag to terminate a thread. If you’ve started a thread, and you want to be able to safely interrupt it from a different thread, you can have the thread periodically check a flag (i.e., to stop it, set the flag to true). By making the flag volatile, you can ensure that the thread that is checking its value will see that it has been set to true without even having to use a synchronized block. For example:

public class Foo extends Thread {

    private volatile boolean close = false;

    public void run() {

        while(!close) {

            // do work

        }

    }

    public void close() {

        close = true;

        // interrupt here if needed

    }

}

Compare the sleep() and wait() methods in Java, including when and why you would use one vs. the other.-->

sleep() is a blocking operation that keeps a hold on the monitor / lock of the shared object for the specified number of milliseconds.

The sleep() method in java is used to block a thread for a particular time, which means it pause the execution of a thread for a specific time. There are two methods of doing so.

When we call the sleep() method, it pauses the execution of the current thread for the given time and gives priority to another thread(if available). Moreover, when the waiting time completed then again previous thread changes its state from waiting to runnable and comes in running state, and the whole process works so on till the execution doesn't complete.

wait(), on the other hand, simply pauses the thread until either (a) the specified number of milliseconds have elapsed or (b) it receives a desired notification from another thread (whichever is first), without keeping a hold on the monitor/lock of the shared object.

sleep() is most commonly used for polling, or to check for certain results, at a regular interval. wait() is generally used in multithreaded applications, in conjunction with notify() / notifyAll(), to achieve synchronization and avoid race conditions.

What is the Java Classloader? 

The Java Classloader is the part of the Java runtime environment that loads classes on demand (lazy loading) into the JVM (Java Virtual Machine). Classes may be loaded from the local file system, a remote file system, or even the web.

When the JVM is started, three class loaders are used: 

1. Bootstrap Classloader: Loads core java API file rt.jar from folder. 

2. Extension Classloader: Loads jar files from folder. 

3. System/Application Classloader: Loads jar files from path specified in the CLASSPATH environment variable.

What are method references, and how are they useful?

Method references were introduced in Java 8 and allow constructors and methods (static or otherwise) to be used as lambdas. They allow one to discard the boilerplate of a lambda when the method reference matches an expected signature.

What is the difference between String s = "Test" and String s = new String("Test")? Which is better and why?

In general, String s = "Test" is more efficient to use than String s = new String("Test").

In the case of String s = "Test", a String with the value “Test” will be created in the String pool. If another String with the same value is then created (e.g., String s2 = "Test"), it will reference this same object in the String pool.


However, if you use String s = new String("Test"), in addition to creating a String with the value “Test” in the String pool, that String object will then be passed to the constructor of the String Object (i.e., new String("Test")) and will create another String object (not in the String pool) with that value. Each such call will therefore create an additional String object (e.g., String s2 = new String("Test") would create an addition String object, rather than just reusing the same String object from the String pool).


Why Should an Object Used As the Key should be Immutable? 

Key should be immutable so that hashCode() method always return the same value.

Since the hash code returned by the hashCode() method depends on the content of the object i.e. values of member variables. If an object is mutable then those values can change and so is the hash code. If the same object returns a different hash code once you inserted the value in HashMap, you will end up searching in different bucket locations and will not able to retrieve the object.

How to create Immutable class?

There are many immutable classes like String, Boolean, Byte, Short, Integer, Long, Float, Double etc. In short, all the wrapper classes and String class is immutable. We can also create immutable class by creating final class that have final data members

The instance variable of the class is final i.e. we cannot change the value of it after creating an object.

The class is final so we cannot create the subclass.

There is no setter methods i.e. we have no option to change the value of the instance variable.

Inter-thread communication in Java

Inter-thread communication is a process in which a thread is paused running in its critical region and another thread is allowed to enter (or lock) 

in the same critical region to be executed. i.e. synchronized threads communicate with each other.

It is implemented by following methods of Object class:

wait()

notify()

notifyAll()

1) wait() method

This method instructs the current thread to release the monitor held by it and to get suspended until some other threads sends a notification from the same monitor.

Causes current thread to release the lock and wait until either another thread invokes the notify() method or the notifyAll() method for this object, 

or a specified amount of time has elapsed.

The current thread must own this object's monitor, so it must be called from the synchronized method only otherwise it will throw exception.

It is a non-static method that causes the current thread to wait and go to sleep until some other threads call the notify () or notifyAll() method for the object’s monitor (lock).

It simply releases the lock and is mostly used for inter-thread communication. It is defined in the object class, and should only be called from a synchronized context. 

synchronized(monitor) 

{ 

monitor.wait();       Here Lock Is Released by Current Thread  

} 

2) notify() method

This method is used to send the notification to the thread that is suspended by the wait() method.

Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. 

The choice is arbitrary and occurs at the discretion of the implementation. 

It sends a notification and wakes up only a single thread instead of multiple threads that are waiting on the object’s monitor.

Syntax:

public final void notify()

3) notifyAll() method

This method is used to send the notification to all the threads that are suspended by wait() method.

Wakes up all threads that are waiting on this object's monitor. 

It sends notifications and wakes up all threads and allows them to compete for the object's monitor instead of a single thread.

Syntax:

public final void notifyAll()

sleep(): As the name suggests, it is a static method that pauses or stops the execution of the current thread for some specified period. 

It doesn’t release the lock while waiting and is mostly used to introduce pause on execution. It is defined in thread class, and no need to call from a synchronized context.  

synchronized(monitor) 

{ 

Thread.sleep(1000);     Here Lock Is Held by The Current Thread 

//after 1000 milliseconds, the current thread will wake up, or after we call that is interrupt() method 

}

Why wait(), notify(), and notifyAll() methods are present in Object class?

We know that every object has a monitor that allows the thread to hold a lock on the object. 

But the thread class doesn't contain any monitors. Thread usually waits for the object’s monitor (lock) by calling the wait() method on an object, 

and notify other threads that are waiting for the same lock using notify() or notifyAll() method. 

 Therefore, these three methods are called on objects only and allow all threads to communicate with each that are created on that object.

What is the difference between Runnable and Callable in Java.

Main difference between these two is that Callable's call() method can return value and throw Exception, which was not possible with Runnable's run() method. 

Callable return Future object, which can hold the result of computation.

It uses the run() method to define a task. | It uses the call() method to define a task. 

It does not return any result and therefore, cannot throw a checked exception.  | It returns a result and therefore, can throw an exception.

What is thread-safety? is Vector a thread-safe class?

Thread-safety is a property of an object or code which guarantees that if executed or used by multiple threads in any manner e.g. read vs write it will behave as expected.

What is race condition in Java? Given one example?

A race condition occurs due to race between multiple threads, if a thread which is supposed to execute first lost the race and executed second, behaviour of code changes, which surface as non-deterministic bugs.


What’s the difference between class lock and object lock?

Class Lock: In java, each and every class has a unique lock usually referred to as a class level lock. These locks are achieved using the keyword ‘static synchronized’ and can be used to make static data thread-safe. 

It is generally used when one wants to prevent multiple threads from entering a synchronized block. 

public class ClassLevelLockExample  

{    

  public void classLevelLockMethod()  

 {       

     synchronized (ClassLevelLockExample.class)  

       {         

            //DO your stuff here       

       }    

 } 

} 

Object Lock: In java, each and every object has a unique lock usually referred to as an object-level lock. These locks are achieved using the keyword ‘synchronized’ and can be used to protect non-static data. 

It is generally used when one wants to synchronize a non-static method or block so that only the thread will be able to execute the code block on a given instance of the class.


What is the start() and run() method of Thread class?

start(): In simple words, the start() method is used to start or begin the execution of a newly created thread. 

When the start() method is called, a new thread is created and this newly created thread executes the task that is kept in the run() method. 

One can call the start() method only once.  

run(): In simple words, the run() method is used to start or begin the execution of the same thread. 

When the run() method is called, no new thread is created as in the case of the start() method. This method is executed by the current thread. 

One can call the run() method multiple times.

Explain thread pool?

A Thread pool is simply a collection of pre-initialized or worker threads at the start-up that can be used to execute tasks and put back in the pool when completed. 

It is referred to as pool threads in which a group of fixed-size threads is created.  

By reducing the number of application threads and managing their lifecycle, one can mitigate the issue of performance using a thread pool. 

Using threads, performance can be enhanced and better system stability can occur. To create the thread pools, java.util.concurrent.Executors class usually provides factory methods.

What is the synchronization process? Why use it?

Synchronization is basically a process in java that enables a simple strategy for avoiding thread interference and memory consistency errors. This process makes sure that resource will be only used one thread at a time when one thread tries to access a shared resource. It can be achieved in three different ways as given below: 


By the synchronized method

By synchronized block

By static synchronization


synchronized (object) 

{        

   //statement to be synchronized 

}

What is synchronized method and synchronized block? Which one should be preferred?

Synchronized Method: In this method, the thread acquires a lock on the object when they enter the synchronized method and releases the lock either normally or

 by throwing an exception when they leave the method.  No other thread can use the whole method unless and until the current thread finishes its execution and release the lock. 

 It can be used when one wants to lock on the entire functionality of a particular method. 

Synchronized Block: In this method, the thread acquires a lock on the object between parentheses after the synchronized keyword, and releases the lock when they leave the block.

 No other thread can acquire a lock on the locked object unless and until the synchronized block exists. It can be used when one wants to keep other parts of the programs accessible to other threads.

 Synchronized blocks should be preferred more as it boosts the performance of a particular program. It only locks a certain part of the program (critical section) rather than the entire method and therefore leads to less contention.

static synchronization

If you make any static method as synchronized, the lock will be on the class not on the object. If we use the synchronized keyword before a method so it will lock the object (one thread can access an object at a time) but if we use static synchronized so it will lock a class (one thread can access a class at a time).

What is thread starvation?

Thread starvation is basically a situation or condition where a thread won’t be able to have regular access to shared resources and therefore is unable to proceed or make progress.

 This is because other threads have high priority and occupy the resources for too long.

 This usually happens with low-priority threads that do not get CPU for its execution to carry on.

Can you start a thread twice?

No, it's not at all possible to restart a thread once a thread gets started and completes its execution. Thread only runs once and if you try to run it for a second time, then it will throw a runtime exception i.e., java.lang.IllegalThreadStateException.

What is ConcurrentHashMap and Hashtable? In java, why is ConcurrentHashMap considered faster than Hashtable?

ConcurrentHashMap: It was introduced in Java 1.5 to store data using multiple buckets. As the name suggests, it allows concurrent read and writes operations to the map. 

It only locks a certain portion of the map while doing iteration to provide thread safety so that other readers can still have access to the map without waiting for iteration to complete.  

Hashtable: It is a thread-safe legacy class that was introduced in old versions of java to store key or value pairs using a hash table.  

It does not provide any lock-free read, unlike ConcurrentHashMap. It just locks the entire map while doing iteration. 

ConcurrentHashMap and Hashtable, both are thread-safe but ConcurrentHashMap generally avoids read locks and improves performance, unlike Hashtable. 

ConcurrentHashMap also provides lock-free reads, unlike Hashtable. Therefore, ConcurrentHashMap is considered faster than Hashtable especially when the number of readers is more as compared to the number of writers.

What do you mean by the ThreadLocal variable in Java?

ThreadLocal variables are special kinds of variables created and provided by the Java ThreadLocal class.

 These variables are only allowed to be read and written by the same thread. Two threads cannot be able to see each other’s ThreadLocal variable,  so even if they will execute the same code, then there won't be any race condition and the code will be thread-safe.

What is the ExecutorService interface?

ExecutorService interface is basically a sub-interface of Executor interface with some additional methods or features that help in managing and controlling the execution of threads. It enables us to execute tasks asynchronously on threads.

What will happen if we don’t override the thread class run() method?

Nothing will happen as such if we don’t override the run() method. The compiler will not show any error. It will execute the run() method of thread class and we will just don’t get any output because the run() method is with an empty implementation.

What does join() method?

The join() method waits for a thread to die. In other words, it causes the currently running threads to stop executing until the thread it joins with completes its task. Join method is overloaded in Thread class in the following ways.

public void join()throws InterruptedException

public void join(long milliseconds)throws InterruptedException

What is shutdown hook?

The shutdown hook is a thread that is invoked implicitly before JVM shuts down. So we can use it to perform clean up the resource or save the state when JVM shuts down normally or abruptly. We can add shutdown hook by using the following method:

public void addShutdownHook(Thread hook){}    

Runtime r=Runtime.getRuntime();  

r.addShutdownHook(new MyThread());  

Shutdown hooks initialized but can only be started when JVM shutdown occurred.

Shutdown hooks are more reliable than the finalizer() because there are very fewer chances that shutdown hooks not run.

The shutdown hook can be stopped by calling the halt(int) method of Runtime class.




What is BlockingQueue?

The java.util.concurrent.BlockingQueue is the subinterface of Queue that supports the operations such as waiting for the space availability before inserting a new value or waiting for the queue to become non-empty before retrieving an element from it.

import java.util.Random;  

import java.util.concurrent.ArrayBlockingQueue;  

import java.util.concurrent.BlockingQueue;  

  

public class TestThread {  

     public static void main(final String[] arguments) throws InterruptedException {  

      BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(10);  

        Insert i = new Insert(queue);  

      Retrieve r = new Retrieve(queue);  

  

      new Thread(i).start();  

      new Thread(r).start();  

        Thread.sleep(2000);  

   }    

  

   static class Insert implements Runnable {  

      private BlockingQueue<Integer> queue;  

        public Insert(BlockingQueue queue) {  

         this.queue = queue;  

      }  

  

      @Override  

      public void run() {  

         Random random = new Random();  

           try {  

            int result = random.nextInt(200);  

            Thread.sleep(1000);  

            queue.put(result);  

            System.out.println("Added: " + result);  

           result = random.nextInt(10);  

            Thread.sleep(1000);  

            queue.put(result);  

            System.out.println("Added: " + result);  

             result = random.nextInt(50);  

            Thread.sleep(1000);  

            queue.put(result);  

            System.out.println("Added: " + result);  

         } catch (InterruptedException e) {  

            e.printStackTrace();  

         }  

      }      

   }  

     static class Retrieve implements Runnable {  

      private BlockingQueue<Integer> queue;  

  

      public Retrieve(BlockingQueue queue) {  

         this.queue = queue;  

      }  

             @Override  

      public void run() {  

                    try {  

            System.out.println("Removed: " + queue.take());  

            System.out.println("Removed: " + queue.take());  

            System.out.println("Removed: " + queue.take());  

         } catch (InterruptedException e) {  

            e.printStackTrace();  

         }  

      }  

   }  

}  

Added: 96

Removed: 96

Added: 8

Removed: 8

Added: 5

Removed: 5

What is hashing:

Hashing is a way to assign a unique code for any variable/object after applying any function/algorithm on its properties.

A true Hashing function must follow this rule:

Hash function should return the same hash code each and every time, when function is applied on same or equal objects. In other words, two equal objects must produce same hash code consistently.

All objects in java inherit a default implementation of hashCode() function defined in Object class. This function produce hash code by typically converting the internal address of the object into an integer, thus producing different hash codes for all different objects.

Hashing: Applies transformation to keys to arrive at address of an element. Performance is independent of table size.

Perfect hash function: Each key is transformed into a unique storage location. Element could be stored and retrieved using same transformation.

Imperfect hash function: Maps more than one key to the same storage location.

hash function for strings:

Java String class uses following algorithm to compute hash code:


public int hashCode()

{

  int hash = 0;

  for (int i = 0; i < length(); i++) 

  {

      hash = hash * 31 + charAt(i);

  }

  return hash;

}

This isn’t literally the code, because inside the String class, the code can access the characters of the string more efficiently than with the public charAt()method. And after it is calculated, the hash code is cached. But this is the essence of how the hash codes of Java strings are calculated.

Overriding hashcode() and equals():

If you want to use objects of your own classes as a key : Overriding hashcode() and equals() methods, which is effectively what you need to do to plug in your hash function and make your class work as a hash map key.

the hashCode() method is where we put our hash function: Writing a good hashCode() method is always a tricky task for a new class.

@Override

public int hashCode() 

{

   //implementation

}


@Override

public int hashCode() 

{

   //implementation

}

The equals() method must return true if the fields of the current object equal those of the object passed in, else return false. By “equal”, we generally mean that primitive fields match via the == operator, and objects are either both null or both non-null and match via the equals() method.

Two important constraints on equals():

if x.equals(y) returns true, then the hash codes of x and y must be identical;

it must be reflexive and transitive : that is, x.equals(y) must return the same value as y.equals(x), and if x.equals(y) and y.equals(z), then x.equals(z) must also be true.

 Immutable objects as key:

It is a advice that you should use immutable object as a key in a Collection. HashCode work best when calculated from immutable data. If you use Mutable object as key and change the state of the object so that the hashCode changes, then the store object will be in the wrong bucket in the Collection.

The most important thing you should consider while implementing hashCode() is that regardless of when this method is called, it should produces the same value for a particular object every time when it is called. If you have a scenario like the object produces one hashCode() value when  it is put() in to a HaspMap and produces another value during a get(), in that case you would not be able to retrieve that object. Therefore, if you hashCode() depends on mutable data in the object, then made changing those data will surely produce a different key by generating a different hashCode().

Hashcode is best when calculated from immutable data; therefore ensure that only immutable object would be used as key with Collections.

If you need mutable fields included in the hashCode method then you can calculate and store the hash value when the object is created and whenever you update mutable field, you must first remove it from the collection and then add it back to the collection after updating it.

Can we execute a program without main method?

The static keyword in Java is used for memory management mainly. We can apply static keyword with variables, methods, blocks and nested classes. The static keyword belongs to the class than an instance of the class.

Java static variable

If you declare any variable as static, it is known as a static variable.

The static variable can be used to refer to the common property of all objects (which is not unique for each object), for example, the company name of employees, college name of students, etc.

The static variable gets memory only once in the class area at the time of class loading.

Suppose there are 500 students in my college, now all instance data members will get memory each time when the object is created. All students have its unique rollno and name, so instance data member is good in such case. Here, "college" refers to the common property of all objects. If we make it static, this field will get the memory only once.

Java static method

If you apply static keyword with any method, it is known as static method.

A static method belongs to the class rather than the object of a class.

A static method can be invoked without the need for creating an instance of a class.

A static method can access static data member and can change the value of it.

The static method can not use non static data member or call non-static method directly.

this and super cannot be used in static context

Why is the Java main method static?

Is because the object is not required to call a static method. If it were a non-static method, JVM creates an object first then call main() method that will lead the problem of extra memory allocation.

Java static block

Is used to initialize the static data member.

It is executed before the main method at the time of classloading.

Can we execute a program without main() method?

No, one of the ways was the static block, but it was possible till JDK 1.6. Since JDK 1.7, it is not possible to execute a Java class without the main method.


Final Variable in Java

A variable declared with a final keyword is known as a final variable in Java. Final variable means a constant (value cannot be modified).

When the final variable once initialized, the value of the final variable can never be changed. In other words, we cannot be assigned a new value.

Declaration of Final variable

The final variable must be declared at a time of declaration otherwise, it will give a compilation error. The syntax to declare a final variable in Java is as follows:

A final variable can be used where we want to remain constant the value of a variable throughout the execution of a program.

Key points:

The only difference between a normal variable and a final variable is that we can re-assign value to a normal variable but we cannot re-assign the value of a final variable once assigned.

A variable that is declared as final and not initialized at a time of declaration is known as a blank final variable in Java.

A blank final variable must be initialized in the constructor of the class otherwise we will get a compilation error. Once the final variable is initialized in the constructor, it cannot be assigned a new value.

class Test 

{ 

// Declaration of final instance variable. 

   final int x; 

   Test(){ 

// Initialization of final variable in the constructor. 

      x = 20; 

   } 

Uninitialized Static Blank Final Variable

When a blank final variable is declared as static and not initialized at a time of declaration, it can only be initialized in the static block. It cannot be initialized in the constructor of the class.

Final Method in Java

A method that is declared with the final keyword is known as final method in Java. A final method cannot be overridden in Java.

When a class is extended by another class, its method can be overridden for reuse but if we want to prevent a particular method being overridden,

In this case, declare that method as final because a subclass can call the final method of superclass without any issues but it cannot override it. Any attempt to do so will cause a compilation problem.

Java Final Method Example Program

1. A final method can be inherited in the subclass but we cannot override it. Look at the above example program.

2. The main difference between abstract method and final method is that abstract method must be overridden in the subclass but final method cannot be overridden in the subclass.

Final Class in Java

A class that is declared with a final keyword is known as final class in Java. Final class means Restricting inheritance!. It does not allow itself to be inherited by another class.

In other words, Java classes declared as a final cannot be extended (inherited). If you do not want to be a subclass, declare it final. A lot of classes in Java API are final.

For example, String class is the most common predefined final class object in Java.

There are two ways to make a class as final.

1. The first way to make a class final is to use the final keyword in the class declaration. The syntax to make a class final, is as follows:

public final class Student 

{

 // class contents

}

 The second way is to declare all of its constructors as private. If a class has only private constructors, it cannot be subclasses.

  Use of Final class in Java

There are three important uses of a final class in Java. They are as follows:

1. The first use is to prevent inheritance, as the final classes cannot be extended.

2. The second use is to create an immutable class like the predefined String class. We cannot make a class immutable without making it final.

3. A final class is very useful when we want high security in any application because the final class cannot be extended.

Key Points:

1. A constructor cannot be final.

2. A block cannot be final.

3. A local final variable must be initialized at the time of declaration.

4. We cannot change the value of a final variable after initialization.

5. A final method cannot be overridden.

6. A final class cannot be extended(inherited).

7. We can create the object for a final class but cannot extend it.

8. If the method parameters are declared as final, the value of these parameters cannot be changed.


One of the most used classes in Java is the String class. It represents a string (array) of characters, and therefore contains textual data such as "Hello World!". Besides the String class, there are two other classes used for similar purposes, though not nearly as often - StringBuilder and StringBuffer.


public final class String

    implements java.io.Serializable, Comparable<String>, CharSequence {

    /** The value is used for character storage. */

    private final char value[];


    public String() {

        this.value = new char[0];

    }


    public String(char value[]) {

        this.value = Arrays.copyOf(value, value.length);

    }

    }

A really important thing to note here is the fact that String is defined as final. This means that String is immutable.

Since String is final, none of these methods really changed it. They merely returned the changed state which we didn't use or assign anywhere. Each time a method on a String is called, a new String gets created, the state is changed and it's returned.


public String concat(String str) {

    int otherLen = str.length();

    if (otherLen == 0) {

        return this;

    }

    int len = value.length;

    char buf[] = Arrays.copyOf(value, len + otherLen);

    str.getChars(buf, len);

    return new String(buf, true);

}


String str1 = "qwerty";

String str2 = "qwerty";

String str3 = new String("qwerty");


System.out.println(str1 == str2); //true

System.out.println(str1 == str3); //false

System.out.println(str1.equals(str2)); //true

System.out.println(str1.equals(str3));/true

StringBuffer and StringBuilder objects basically hold the same value as a String object - a sequence of characters. Both StringBuffer and StringBuilder are also mutable which means that once we assign a value to them, that value is processed as an attribute of a StringBuffer or StringBuilder object.

No matter how many times we modify their value, as a result a new String, StringBuffer, or StringBuilder object will not be created. This approach is much more time efficient and less resource consuming.

Thread Safety: StringBuffer methods are synchronized, which means that only one thread can call the methods of a StringBuffer instance at a time. On the other hand StringBuilder methods are not synchronized, therefore multiple threads can call the methods in StringBuilder class without being blocked.

So we have come to a conclusion that StringBuffer is a thread-safe class while StringBuffer isn't.

Is that something you should worry about? Maybe. If you are working on application which uses multiple threads it can be potentially dangerous to work with StringBuilder.

Speed: StringBuffer is actually two to three times slower than StringBuilder. The reason behind this is StringBuffer synchronization - only allowing 1 thread to execute on an object at a time results in much slower code execution.

Methods

Both StringBuffer and StringBuilder have the same methods (besides synchronized method declaration in the StringBuilder class). Let's go through some of the most common ones:


append()

insert()

replace()

delete()

reverse()

Usage of hashCode() and equals() Methods

equals(Object otherObject) – As method name suggests, is used to simply verify the equality of two objects. It’s default implementation simply check the object references of two objects to verify their equality. By default, two objects are equal if and only if they are stored in the same memory address.

hashcode() – Returns a unique integer value for the object in runtime. By default, integer value is mostly derived from memory address of the object in heap (but it’s not mandatory always).

This hash code is used for determining the bucket location, when this object needs to be stored in some HashTable like data structure.


Contract between hashCode() and equals()

It is generally necessary to override the hashCode() method whenever equals() method is overridden, so as to maintain the general contract for the hashCode() method, which states that equal objects must have equal hash codes.

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.

This integer need not remain consistent from one execution of an application to another execution of the same application.

If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results.

However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.


override only equals() method?

public boolean equals(Object o) {

    if(o == null)

    {

        return false;

    }

    if (o == this)

    {

        return true;

    }

    if (getClass() != o.getClass())

    {

        return false;

    }

     

    Employee e = (Employee) o;

    return (this.getId() == e.getId());

}


Override hashCode() method also


@Override

public int hashCode()

{

    final int PRIME = 31;

    int result = 1;

    result = PRIME * result + getId();

    return result;

}

Java hashCode() and equals() best practices

Always use same attributes of an object to generate hashCode() and equals() both. As in our case, we have used employee id.

equals() must be consistent (if the objects are not modified, then it must keep returning the same value).

Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().

If you override one, then you should override the other.

Serialization and Deserialization in Java

Serialization in Java is a mechanism of writing the state of an object into a byte-stream. It is mainly used in Hibernate, RMI, JPA, EJB and JMS technologies.

The reverse operation of serialization is called deserialization where byte-stream is converted into an object. The serialization and deserialization process is platform-independent, it means you can serialize an object on one platform and deserialize it on a different platform.


For serializing the object, we call the writeObject() method of ObjectOutputStream class, and for deserialization we call the readObject() method of ObjectInputStream class.

We must have to implement the Serializable interface for serializing the object.

java.io.Serializable interface

Serializable is a marker interface (has no data member and method). It is used to "mark" Java classes so that the objects of these classes may get a certain capability. The Cloneable and Remote are also marker interfaces.

The Serializable interface must be implemented by the class whose object needs to be persisted.

The String class and all the wrapper classes implement the java.io.Serializable interface by default.

ObjectOutputStream class

The ObjectOutputStream class is used to write primitive data types, and Java objects to an OutputStream. Only objects that support the java.io.Serializable interface can be written to streams.

Constructor

1) public ObjectOutputStream(OutputStream out) throws IOException {}    It creates an ObjectOutputStream that writes to the specified OutputStream.

Important Methods

Method    Description

1) public final void writeObject(Object obj) throws IOException {}    It writes the specified object to the ObjectOutputStream.

2) public void flush() throws IOException {}    It flushes the current output stream.

3) public void close() throws IOException {}    It closes the current output stream.


ObjectInputStream class

An ObjectInputStream deserializes objects and primitive data written using an ObjectOutputStream.

Constructor

1) public ObjectInputStream(InputStream in) throws IOException {}    It creates an ObjectInputStream that reads from the specified InputStream.

Method    Description

1) public final Object readObject() throws IOException, ClassNotFoundException{}    It reads an object from the input stream.

2) public void close() throws IOException {}    It closes ObjectInputStream.


Marker Interfaces

A marker interface is an interface that has no methods or constants inside it. It provides run-time type information about objects, so the compiler and JVM have additional information about the object.

A marker interface is also called a tagging interface.

Though marker interfaces are still in use, they very likely point to a code smell and should be used carefully. The main reason for this is that they blur the lines about what an interface represents since markers don't define any behavior. Newer development favors annotations to solve some of the same problems.

Java has many built-in marker interfaces, such as Serializable, Cloneable, and Remote.

Let's take the example of the Cloneable interface. If we try to clone an object that doesn't implement this interface, the JVM throws a CloneNotSupportedException. Hence, the Cloneable marker interface is an indicator to the JVM that we can call the Object.clone() method.

In the same way, when calling the ObjectOutputStream.writeObject() method, the JVM checks if the object implements the Serializable marker interface. When it's not the case, a NotSerializableException is thrown. Therefore, the object isn't serialized to the output stream.

Custom Marker Interface

For example, we could create a marker that indicates whether an object can be removed from the database:

public interface Deletable {

}

In order to delete an entity from the database, the object representing this entity has to implement our Deletable marker interface:


public class Entity implements Deletable {

    // implementation details

}

Let's say that we have a DAO object with a method for removing entities from the database. We can write our delete() method so that only objects implementing our marker interface can be deleted:

public class ShapeDao {


    // other dao methods


    public boolean delete(Object object) {

        if (!(object instanceof Deletable)) {

            return false;

        }


        // delete implementation details

        

        return true;

    }

}

As we can see, we are giving an indication to the JVM, about the runtime behavior of our objects. If the object implements our marker interface, it can be deleted from the database.

Daemon threads are useful for background supporting tasks such as garbage collection, releasing memory of unused objects and removing unwanted entries from the cache.

Most of the JVM threads are daemon threads.

Daemon threads is a low priority thread that provide supports to user threads. These threads can be user defined and system defined as well. 

Garbage collection thread is one of the system generated daemon thread that runs in background. These threads run in the background to perform tasks such as garbage collection. 

Daemon thread does allow JVM from existing until all the threads finish their execution. When a JVM founds daemon threads it terminates the thread and then shutdown itself, it does not care Daemon thread whether it is running or not.

Stacks

The class is based on the basic principle of last-in-first-out

push(Object element) - Adding Elements

peek() - To retrieve or fetch the first element of the Stack or the element present at the top of the Stack. The element retrieved does not get deleted or removed from the Stack.

pop() - To remove element, The element is popped from the top of the stack and is removed from the same.

search(Object element) -It determines whether an object exists in the stack. If the element is found, It returns the position of the element from the top of the stack. Else, it returns -1.



StringBuffer and StringBuilder

StringBuffer and StringBuilder objects basically hold the same value as a String object - a sequence of characters. Both StringBuffer and StringBuilder are also mutable which means that once we assign a value to them, that value is processed as an attribute of a StringBuffer or StringBuilder object.

StringBuilder vs StringBuffer

These two classes are almost identical to one another - they use methods with the same names which return the same results. Although there are two major differences between them:

Thread Safety: StringBuffer methods are synchronized, which means that only one thread can call the methods of a StringBuffer instance at a time. On the other hand StringBuilder methods are not synchronized, therefore multiple threads can call the methods in StringBuilder class without being blocked.

So we have come to a conclusion that StringBuffer is a thread-safe class while StringBuffer isn't.

Is that something you should worry about? Maybe. If you are working on application which uses multiple threads it can be potentially dangerous to work with StringBuilder.

Speed: StringBuffer is actually two to three times slower than StringBuilder. The reason behind this is StringBuffer synchronization - only allowing 1 thread to execute on an object at a time results in much slower code execution.

String vs StringBuilder vs StringBuffer

                         String    StringBuffer    StringBuilder

Mutable    No    Yes    Yes

Thread-Safe    Yes    Yes    No

Time Efficient    No    No    Yes

Memory Efficient    No    Yes    Yes

Well the perfect answer on this question is "It depends". We know that Strings are easy to type, easy to use, and are thread-safe. On the other hand they are immutable (which means more memory consumption) and very slow when doing string manipulation.

StringBuffers are mutable, memory efficient, and thread-safe. Their downfall is the speed when compared to much faster StringBuilders.

As for StringBuilders, they are also mutable and memory efficient, they are the fastest in string manipulation, but unfortunately they are not thread-safe.



Comparable    Comparator

1) Comparable provides a single sorting sequence. In other words, we can sort the collection on the basis of a single element such as id, name, and price.    The Comparator provides multiple sorting sequences. In other words, we can sort the collection on the basis of multiple elements such as id, name, and price etc.

2) 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.

3) Comparable provides compareTo() method to sort elements.    Comparator provides compare() method to sort elements.

4) Comparable is present in java.lang package.    A Comparator is present in the java.util package.

5) We can sort the list elements of Comparable type by Collections.sort(List) method.    We can sort the list elements of Comparator type by Collections.sort(List, Comparator) method.


Java Enum (Enumerations)

An enum is just like any other Java Class, with a predefined set of instances. It is basically a data type that lets you describe each member of a type in a more readable and reliable way, for example, Alert type like BLAD, BLDL and NEWBL.


public enum Alert {

    BLAD,

    BLDL,

    NEWBL

}


When should I use?

You can use enum types any time you need to represent a fixed set of constants .

How to use Java Enum

You can use enums when a variable (especially a method parameter) can only take one out of a small set of possible values. Examples would be things like days in a Week(Sunday, Monday etc..), or Directions (NORTH, SOUTH, EAST and WEST).

Enum switch...case Example :

You can also use an enum type in a Java switch...case statement. You can use Enum in Java inside the Switch statement like int or char primitive data type.

The following program shows how to use Enum in switch...case statement.


enum Directions {

    BLAD,

    BLDL,

    NEWBL

}

public class SwitchCaseEnum {

    public static void main(String args[])

    {

        Alert alert;

        direct = Alert.BLAD;

        switch(direct) {

            case BLAD:

                System.out.println("You chose BLAD!");

                break;

            case BLDL:

                System.out.println("You chose BLDL!");

                break;

            case NEWBL:

                System.out.println("You chose NEWBL!");

                break;

            

            default:

                System.out.println("Invalid Direction....!!");

                break;

        }

    }

}



try-with-resources 

Introduced in Java 7 — allows us to declare resources to be used in a try block with the assurance that the resources will be closed after the execution of that block.

The try-with-resources statement ensures that each resource is closed at the end of the statement execution.

You can pass any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable.

The resources declared need to implement the AutoCloseable interface.

Using try-with-resources

Simply put, to be auto-closed, a resource has to be both declared and initialized inside the try:


try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {

    writer.println("Hello World");

}


Shallow Copy Vs. Deep Copy in Java

Shallow Copy

When we do a copy of some entity to create two or more than two entities such that changes in one entity are reflected in the other entities as well, then we can say we have done a shallow copy. In shallow copy, new memory allocation never happens for the other entities, and the only reference is copied to the other entities. The following example demonstrates the same.

Deep Copy

When we do a copy of some entity to create two or more than two entities such that changes in one entity are not reflected in the other entities, then we can say we have done a deep copy. In the deep copy, a new memory allocation happens for the other entities, and reference is not copied to the other entities. Each entity has its own independent reference. The following example demonstrates the same.


Differences Between Shallow Copy and Deep Copy

After learning about shallow and deep copy, let's see the differences between shallow and deep copy.

Shallow Copy    Deep Copy

It is fast as no new memory is allocated.    It is slow as new memory is allocated.

Changes in one entity is reflected in other entity.    Changes in one entity are not reflected in changes in another identity.

The default version of the clone() method supports shallow copy.    In order to make the clone() method support the deep copy, one has to override the clone() method.

A shallow copy is less expensive.    Deep copy is highly expensive.

Cloned object and the original object are not disjoint.    Cloned object and the original object are disjoint.

Tight coupling

Tight coupling means classes and objects are dependent on one another. In general, tight coupling is usually not good because it reduces the flexibility and re-usability of the code while Loose coupling means reducing the dependencies of a class that uses the different class directly.

Generics in Java

The Java Generics programming is introduced in J2SE 5 to deal with type-safe objects. It makes the code stable by detecting the bugs at compile time.

Before generics, we can store any type of objects in the collection, i.e., non-generic. Now generics force the java programmer to store a specific type of objects.

Advantage of Java Generics

1) Type-safety: We can hold only a single type of objects in generics. It doesn?t allow to store other objects.

2) Type casting is not required: There is no need to typecast the object.

3) Compile-Time Checking: It is checked at compile time so problem will not occur at runtime. The good programming strategy says it is far better to handle the problem at compile time than runtime.


Object Serialization with inheritance in Java?s

1. When super class is implements Serializable interface and subclass is not.

In this case the object of subclass get serialized by default when superclass get serialize, even if subclass doesn't implements Serializable interface.

2. When super class is not implementing serializable interface and subclass implements.

In this case super class instances variables which are inherited in subclass doesn't get serialize and also looses their assigned values during serialization of sub class.Also JVM during serialization of subclass re-assign the default initialized values to these instance variables of superclass.One more point which is to be taken care of it in this scenerio is super class must have default no argument constructor as JVM access super class during deserialization.In case this constructor is not present a compile time exception will be encountered.

3. When requirement is to serialize superclass but not to subclass (Custom Serialization).

In order to prevent subclass from serialization we need to implement writeObject() and readObject() methods which are executed by JVM during serialization and deserialization also NotSerializableException is made to be thrown from these methods.We can also provide our custom logic in these methods which would be executed during serialization/deserializatin.

Why String is Immutable or Final in Java

In object-oriented programming, the immutable string or objects that cannot be modified once it is created. But we can only change the reference to the object. We restrict to change the object itself. The String is immutable in Java because of the security, synchronization and concurrency, caching, and class loading. The reason of making string final is to destroy the immutability and to not allow others to extend it.

The String objects are cached in the String pool, and it makes the String immutable

The cached String literals are accessed by multiple clients. So, there is always a risk, where action performs by one client affects all other clients. For example, if one client performs an action and changes the string value from Pressure to PRESSURE, all remaining clients will also read that value. For the performance reason, caching of String objects was important, so to remove that risk, we have to make the String Immutable.


These are some more reasons of making String immutable:

The String pool cannot be possible if String is not immutable in Java. A lot of heap space is saved by JRE

 The same string variable can be referred to by more than one string variable in the pool. String interning can also not be possible if the String would not be immutable.

If we don't make the String immutable, it will pose a serious security threat to the application. For example, database usernames, passwords are passed as strings to receive database connections. The socket programming host and port descriptions are also passed as strings. The String is immutable, so its value cannot be changed. If the String doesn't remain immutable, any hacker can cause a security issue in the application by changing the reference value.

The String is safe for multithreading because of its immutableness. Different threads can access a single "String instance". It removes the synchronization for thread safety because we make strings thread-safe implicitly.

Immutability gives the security of loading the correct class by Classloader. For example, suppose we have an instance where we try to load java.sql.Connection class but the changes in the referenced value to the myhacked.Connection class does unwanted things to our database.


Private Class In Java

Yes, we can declare a class as private but these classes can be only inner or nested classes. We can’t a top-level class as private because it would be completely useless as nothing would have access to it.

private class Main

{

    public static void main(String[] args) {

        System.out.println("Inside private class");

    }

}

Main.java:1: error: modifier private not allowed here

private class Main

        ^

1 error

==

Daemon threads are useful for background supporting tasks such as garbage collection, releasing memory of unused objects and removing unwanted entries from the cache.

Most of the JVM threads are daemon threads.

Daemon threads is a low priority thread that provide supports to user threads. These threads can be user defined and system defined as well. 

Garbage collection thread is one of the system generated daemon thread that runs in background. These threads run in the background to perform tasks such as garbage collection. 

Daemon thread does allow JVM from existing until all the threads finish their execution. When a JVM founds daemon threads it terminates the thread and then shutdown itself, it does not care Daemon thread whether it is running or not.


Diamond problem

For instance, let us assume that Java does support multiple inheritance.

And if we have an abstract class named Sample with an abstract method demo().

Then if two other classes in the same package extends this class and try to implement its abstract method, demo().

Then, as per the basic rule of inheritance, a copy of both demo() methods should be created in the subclass object which leaves the subclass with two methods with same prototype (name and arguments).

Then, if you call the demo() method using the object of the subclass compiler faces an ambiguous situation not knowing which method to call. This issue is known as diamond problem in Java.

Solution to diamond problem

You can achieve multiple inheritance in Java, using the default methods (Java8) and interfaces.

From Java8 on wards default methods are introduced in an interface. Unlike other abstract methods these are the methods of an interface with a default implementation. If you have default method in an interface, it is not mandatory to override (provide body) it in the classes that are already implementing this interface.

You can have same default methods (same name and signature) in two different interfaces and, from a class you can implement these two interfaces.

If you do so, you must override the default method from the class explicitly specifying the default method along with its interface name.