---
# System prepended metadata

title: Java

---

# Java

## Keypoints:
<div style="text-align: justify"> 

- Java is Object Oriented. However it is not considered as pure object oriented as it provides support for primitive data types (like int, char, etc)
- The Java codes are first compiled into bytecode (machine independent code). Then the byte code is run on Java Virtual Machine (JVM) regardless of the underlying architecture.
- Java is a platform-independent language.
- Compile java code using `javac HelloWorld.java` ans run it using `java HelloWorld`
- Generally `CamelCase` is followed while programming in java
</div>
---

## Basic Java Code
Below given  program is the simplest program of Java printing “Hello World” to the screen.
```java=1
/* This is a simple Java program. 
   FileName : "HelloWorld.java". */
class HelloWorld 
{ 
    // Your program begins with a call to main(). 
    // Prints "Hello, World" to the terminal window. 
    public static void main(String args[]) 
    { 
        System.out.println("Hello, World"); 
    } 
} 
```

---


## JVM Architecture
<div style="text-align: justify"> 

- JVM(Java Virtual Machine) acts as a run-time engine to run Java applications. JVM is the one that actually calls the main method present in a java code. JVM is a part of JRE(Java Runtime Environment).
- Java applications are called WORA (Write Once Run Anywhere). This means a programmer can develop Java code on one system and can expect it to run on any other Java enabled system without any adjustment. This is all possible because of JVM.
- When we compile a .java file, .class files(contains byte-code) with the same class names present in .java file are generated by the Java compiler. This .class file goes into various steps when we run it. These steps together describe the whole JVM.

![](https://i.imgur.com/a5RjmpX.png)
</div>


### **Class Loader Subsystem**

<div style="text-align: justify"> 

It is mainly responsible for three activities.

* Loading
* Linking
* Initialization

**Loading:** The Class loader reads the .class file, generate the corresponding binary data and save it in method area. For each .class file, JVM stores following information in method area.

* Fully qualified name of the loaded class and its immediate parent class.
* Whether .class file is related to Class or Interface or Enum
* Modifier, Variables and Method information etc.

After loading .class file, JVM creates an object of type Class to represent this file in the heap memory. This Class object can be used by the programmer for getting class level information like name of class, parent name, methods and variable information etc. To get this object reference we can use getClass() method of Object class.

</div>

```java=1
// A Java program to demonstrate working of a Class type 
// object created by JVM to represent .class file in 
// memory. 
import java.lang.reflect.Field; 
import java.lang.reflect.Method; 
  
// Java code to demonstrate use of Class object 
// created by JVM 
public class Test 
{ 
    public static void main(String[] args) 
    { 
        Student s1 = new Student(); 
  
        // Getting hold of Class object created 
        // by JVM. 
        Class c1 = s1.getClass(); 
  
        // Printing type of object using c1. 
        System.out.println(c1.getName()); 
  
        // getting all methods in an array 
        Method m[] = c1.getDeclaredMethods(); 
        for (Method method : m) 
            System.out.println(method.getName()); 
  
        // getting all fields in an array 
        Field f[] = c1.getDeclaredFields(); 
        for (Field field : f) 
            System.out.println(field.getName()); 
    } 
} 
  
// A sample class whose information is fetched above using 
// its Class object. 
class Student 
{ 
    private String name; 
    private int roll_No; 
  
    public String getName()  {  return name;   } 
    public void setName(String name) { this.name = name; } 
    public int getRoll_no()  { return roll_No;  } 
    public void setRoll_no(int roll_no) { 
        this.roll_No = roll_no; 
    } 
} 

```
```
Output:

Student
getName
setName
getRoll_no
setRoll_no
name
roll_No
```
<div style="text-align: justify"> 

**Linking** : Performs verification, preparation, and (optionally) resolution.

* **Verification** : It ensures the correctness of .class file i.e. it check whether this file is properly formatted and generated by valid compiler or not. If verification fails, we get run-time exception java.lang.VerifyError.
* **Preparation** : JVM allocates memory for class variables and initializing the memory to default values.
* **Resolution** : It is the process of replacing symbolic references from the type with direct references. It is done by searching into method area to locate the referenced entity.

**Initialization** : In this phase, all static variables are assigned with their values defined in the code and static block(if any). This is executed from top to bottom in a class and from parent to child in class hierarchy.
In general, there are three class loaders :

* **Bootstrap class loader** : Every JVM implementation must have a bootstrap class loader, capable of loading trusted classes. It loads core java API classes present in JAVA_HOME/jre/lib directory. This path is popularly known as bootstrap path. It is implemented in native languages like C, C++.
* **Extension class loader** : It is child of bootstrap class loader. It loads the classes present in the extensions directories JAVA_HOME/jre/lib/ext(Extension path) or any other directory specified by the java.ext.dirs system property. It is implemented in java by the sun.misc.Launcher$ExtClassLoader class.
* **System/Application class loader** : It is child of extension class loader. It is responsible to load classes from application class path. It internally uses Environment Variable which mapped to java.class.path. It is also implemented in Java by the sun.misc.Launcher$AppClassLoader class.
 
</div>

```java=1
// Java code to demonstrate Class Loader subsystem 
public class Test 
{ 
    public static void main(String[] args) 
    { 
        // String class is loaded by bootstrap loader, and 
        // bootstrap loader is not Java object, hence null 
        System.out.println(String.class.getClassLoader()); 
  
        // Test class is loaded by Application loader 
        System.out.println(Test.class.getClassLoader()); 
    } 
}

```

```
Output:

null
sun.misc.Launcher$AppClassLoader@73d16e93
```

<div style="text-align: justify"> 

**Note** : JVM follow Delegation-Hierarchy principle to load classes. System class loader delegate load request to extension class loader and extension class loader delegate request to boot-strap class loader. If class found in boot-strap path, class is loaded otherwise request again transfers to extension class loader and then to system class loader. At last if system class loader fails to load class, then we get run-time exception java.lang.ClassNotFoundException.
</div>

![](https://i.imgur.com/L7UxL5f.png)

### **JVM Memory**
<div style="text-align: justify"> 

* **Method area**: In method area, all class level information like class name, immediate parent class name, methods and variables information etc. are stored, including static variables. There is only one method area per JVM, and it is a shared resource.
* **Heap area**: Information of all objects is stored in heap area. There is also one Heap Area per JVM. It is also a shared resource.
* **Stack area**: For every thread, JVM create one run-time stack which is stored here. Every block of this stack is called activation record/stack frame which store methods calls. All local variables of that method are stored in their corresponding frame. After a thread terminate, it’s run-time stack will be destroyed by JVM. It is not a shared resource.
* **PC Registers**: Store address of current execution instruction of a thread. Obviously each thread has separate PC Registers.
* **Native method stacks**: For every thread, separate native stack is created. It stores native method information.
</div>

![](https://i.imgur.com/odwPSUY.png)


### **Execution Engine**
<div style="text-align: justify"> 


Execution engine execute the .class (bytecode). It reads the byte-code line by line, use data and information present in various memory area and execute instructions. It can be classified in three parts :-

* **Interpreter** : It interprets the bytecode line by line and then executes. The disadvantage here is that when one method is called multiple times, every time interpretation is required.
* **Just-In-Time Compiler(JIT)** : It is used to increase efficiency of interpreter. It compiles the entire bytecode and changes it to native code so whenever interpreter see repeated method calls, JIT provide direct native code for that part so re-interpretation is not required,thus efficiency is improved.
* **Garbage Collector** : It destroy un-referenced objects.For more on Garbage Collector,refer Garbage Collector.
</div>

### **Java Native Interface (JNI)**
<div style="text-align: justify"> 
It is an interface which interacts with the Native Method Libraries and provides the native libraries(C, C++) required for the execution. It enables JVM to call C/C++ libraries and to be called by C/C++ libraries which may be specific to hardware.
</div>

### **Native Method Libraries**
<div style="text-align: justify"> 
It is a collection of the Native Libraries(C, C++) which are required by the Execution Engine.
</div>


### **Stack Frame Structure**
<div style="text-align: justify"> 

The stack frame basically consists of three parts: Local Variable Array, Operand Stack & Frame Data. When JVM invokes a Java method, first it checks the class data to determine the number of words (size of the local variable array and operand stack, which are measured in words for each individual method) required by the method in the local variables array and operand stack. It creates a stack frame of the proper size for invoked method and pushes it onto the Java stack.

**Local Variable Array (LVA):**

* The local variables part of stack frame is organized as a zero-based array of words.
* It contains all parameters and local variables of the method.
* Each slot or entry in the array is of 4 Bytes.
* Values of type int, float, and reference occupy 1 entry or slot in the array i.e. 4 bytes.
* Values of double and long occupy 2 consecutive entries in the array i.e. 8 bytes total.
* Byte, short and char values will be converted to int type before storing and occupy 1 slot i.e. 4 Bytes.
* But the way of storing Boolean values is varied from JVM to JVM. But most of the JVM gives 1 slot for Boolean values in the local variable array.
* The parameters are placed into the local variable array first, in the order in which they are declared.

**Operand Stack (OS):**
* JVM uses operand stack as work space like rough work or we can say for storing intermediate calculation’s result.
* Operand stack is organized as array of words like local variable array. But this is not accessed by using index like local variable array rather it is accessed by some instructions that can push the value to the operand stack and some instructions that can pop values from operand stack and some instructions that can perform required operations.

**Frame Data (FD):**

* It contains all symbolic reference (constant pool resolution) and normal method return related to that particular method.
* It also contains a reference to Exception table which provide the corresponding catch block information in the case of exceptions.

</div>

---

## JVM Shutdown Hook in Java
<div style="text-align: justify">

* Shutdown Hooks are a special construct that allows developers to plug in a piece of code to be executed when the JVM is shutting down. This comes in handy in cases where we need to do special clean up operations in case the VM is shutting down.
* Handling this using the general constructs such as making sure that we call a special procedure before the application exits (calling System.exit(0) ) will not work for situations where the VM is shutting down due to an external reason (ex. kill request from O/S), or due to a resource problem (out of memory). As we will see soon, shutdown hooks solve this problem easily, by allowing us to provide an arbitrary code block, which will be called by the JVM when it is shutting down.
* From the surface, using a shutdown hook is downright straight forward. All we have to do is simply write a class which extends the java.lang.Thread class, and provide the logic that we want to perform when the VM is shutting down, inside the public void run() method. Then we register an instance of this class as a shutdown hook to the VM by calling Runtime.getRuntime().addShutdownHook(Thread) method. If you need to remove a previously registered shutdown hook, the Runtime class provides the removeShutdownHook(Thread) method as well.

</div>

```java=1
public class ShutDownHook 
{ 
  public static void main(String[] args) 
  { 
  
    Runtime.getRuntime().addShutdownHook(new Thread() 
    { 
      public void run() 
      { 
        System.out.println("Shutdown Hook is running !"); 
      } 
    }); 
    System.out.println("Application Terminating ..."); 
  } 
}

Output:
Application Terminating ...
Shutdown Hook is running !
```

<div style="text-align: justify">

**Notes**
- Shutdown Hooks may not be executed in some cases
- Once started, Shutdown Hooks can be forcibly stopped before completion.
- We can have more than one Shutdown Hooks, but their execution order is not guaranteed.
- We cannot register/unregister Shutdown Hooks within Shutdown Hooks
-  Once shutdown sequence starts, it can be stopped by `Runtime.halt()` only.
- Using shutdown hooks require security permissions.


A single class file structure contains attributes that describe a class file, which are as follows:
* **magic_number**: The first 4 bytes of class file are termed as magic_number. This is a predefined value which the JVM use to identify whether the .class file is generated by valid compiler or not. The predefined value will be in hexadecimal form i.e. 0xCAFEBABE.
* **minor_version & major_version**: These both together represents .class file version. JVM will use these versions to identify which version of the compiler generates the current .class file. We denotes the version of class file as M.m where M stands for major_version and m stands for minor_version
* **constant_pool_count**: It represents the number of the constants present in the constant pool (When a Java file is compiled, all references to variables and methods are stored in the class’s constant pool as a symbolic reference).
* **constant_pool[]**: It represents the information about constants present in constant pool file.
* **access_flags**: It provide the information about the modifiers which are declared to the class file.
* this_class: It represents fully qualified name of the class file.
* **super_class**: It represents fully qualified name of the immediate super class of current class. Consider above Sample.java file. When we will compile it, then we can say this_class will be Sample class and super_class will be Object class.
* **interface_count**: It returns the number of interfaces implemented by current class file.
* **interface[]**: It returns interfaces information implemented by current class file.
* **fields_count**: It represents the number of fields (static variable) present in current class file.
* **fields[]**: It represent fields (static variable) information present in current class file.
* **method_count**: It represents number of methods present in current class file.
* **method[]**: It returns information about all methods present in current class file.
* **attributes_count**: It returns the number of attributes (instance variables) present in current class file.
* **attributes[]**: It provides information about all attributes present in current class file.
</div>

---

## JDK, JRE & JVM
<div style="text-align: justify">

**JDK – Java Development Kit (in short JDK)** is Kit which provides the environment to develop and execute(run) the Java program. JDK is a kit(or package) which includes two things
Development Tools(to provide an environment to develop your java programs)
JRE (to execute your java program).
Note : JDK is only used by Java Developers.

**JRE – Java Runtime Environment (to say JRE**) is an installation package which provides environment to only run(not develop) the java program(or application)onto your machine. JRE is only used by them who only wants to run the Java Programs i.e. end users of your system.
**JVM – Java Virtual machine(JVM)** is a very important part of both JDK and JRE because it is contained or inbuilt in both. Whatever Java program you run using JRE or JDK goes into JVM and JVM is responsible for executing the java program line by line hence it is also known as interpreter.

### How JRE works:
![](https://i.imgur.com/UUJfY85.png)

### How JDK and JRE interact
![](https://i.imgur.com/n8I7tiP.png)

</div>

---

## JDBC Drivers
<div style="text-align: justify">

**Java Database Connectivity (JDBC)** is an application programming interface (API) for the programming language Java, which defines how a client may access any kind of tabular data, especially relational database. It is part of Java Standard Edition platform, from Oracle Corporation. It acts as a middle layer **interface between java applications and database**.

The JDBC classes are contained in the Java Package `java.sql` and `javax.sql`.

JDBC helps you to write Java applications that manage these three programming activities:
* Connect to a data source, like a database.
* Send queries and update statements to the database
* Retrieve and process the results received from the database in answer to your query.


There are 4 types of JDBC drivers:
* Type-1 driver or JDBC-ODBC bridge driver
* Type-2 driver or Native-API driver
* Type-3 driver or Network Protocol driver
* Type-4 driver or Thin driver

To know more about these drivers click [here](https://www.geeksforgeeks.org/java-platform-independent/).

**Which Driver to use When?**
1. If you are accessing one type of database, such as Oracle, Sybase, or IBM, the preferred driver type is type-4.
2. If your Java application is accessing multiple types of databases at the same time, type 3 is the preferred driver.
3. Type 2 drivers are useful in situations, where a type 3 or type 4 driver is not available yet for your database.
4. The type 1 driver is not considered a deployment-level driver, and is typically used for development and testing purposes only.
</div>

## Myth about the file name and class name in Java
```java=1
/*** File name: Trial.java ***/
class ForGeeks { 
    public static void main(String[] args) 
    { 
        System.out.println("For Geeks class"); 
    } 
} 
  
class GeeksTest { 
    public static void main(String[] args) 
    { 
        System.out.println("Geeks Test class"); 
    } 
} 
```

<div style="text-align: justify">

When the above file is compiled as `javac Trial.java` this will create 2 .class files as `ForGeeks.class` and `GeeksTest.class` .
Since each class has separate main() stub they can be tested individually.
- When **java ForGeeks** is executed the output is For **Geeks class**.
- When **java GeeksTest** is executed the output is **Geeks Test**.

### Note 
The myth about the file name and class name should be same only when the class is declared in **public**.
</div>

---

## Microservices
<div style="text-align: justify">

A **microservice** is a small, loosely coupled distributed service. Microservice Architectures evolved as a solution to the scalability and innovation challenges with Monolith architectures

**Reasons for using Microservice:**
In monolith application, there are few challenges:
* For a large application, it is difficult to understand the complexity and make code changes fast and correctly, sometimes it becomes hard to manage the code.
* Applications need extensive manual testing to ensure the impact of changes.
* For small change, the whole application needs to be built and deployed.
* The heavy application slows down start-up time.

**Benefits of Microservices:**
* **Small Modules** – Application is broken into smaller modules which are easy for developers to code and maintain.
* **Easier Process Adaption** – By using microservices, new Technology & Process Adaption becomes easier. You can try new technologies with the newer microservices that we use.
* **Independent scaling** – Each microservice can scale independently via X-axis scaling (cloning with more CPU or memory) and Z-axis scaling (sharding), based upon their needs.
* **Unaffected** – Large applications remain largely unaffected by the failure of a single module.
* **DURS** – Each service can be independently DURS (deployed, updated, replaced, and scaled).

**Restrictions of Microservices:**

* **Configuration Management** – As it becomes granular the headache comes for configuring the services and monitoring those. You need to maintain configurations for hundreds of components across environments.
* **Debugging** – Tracking down the service failure is painstaking job. You might need to look into multiple services across different components. Centralized Logging and Dashboards are essential to make it easy to debug problems.
* **Automation** – Because there are a number of smaller components instead of a monolith, you need to automate everything – Builds, Deployment, Monitoring etc.
* **Testing** – Needs a greater effort for end to end testing as it needs all the dependent services to be up and running.

**Microservice Frameworks for Java:**
There are several microservices frameworks that you can use for developing for Java. Some of these are:
* **Spring Boot** – This is probably the best Java microservices framework that works on top of languages for Inversion of Control, Aspect Oriented Programming, and others.
* **Dropwizard** – Dropwizard pulls together stable, mature libraries from the Java ecosystem into a simple, light-weight package that lets you focus on getting things done.
* **Restlet** – Restlet Framework helps Java developers build better web APIs that follow the REST architecture style.
* **Spark** – A micro-framework for creating web applications in Kotlin and Java 8 with minimal effort

</div>

---

## Things should be learned with Java
1. Java 8
1. Spring Framework (Spring Boot)
1. Unit Testing
1. APIs and Libraries
1. JVM’s Internals
1. Design Patterns
1. DevOps Tools
1. Kotlin
1. Microservices
1. Learn Your IDE Better
---
## **Java Keywords**

* **abstract** -Specifies that a class or method will be implemented later, in a subclass
* **assert** -Assert describes a predicate (a true–false statement) placed in a Java program to indicate that the developer thinks that the predicate is always true at that place. If an assertion evaluates to false at run-time, an assertion failure results, which typically causes execution to abort.
* **boolean** – A data type that can hold True and False values only
* **break** – A control statement for breaking out of loops
* **byte** – A data type that can hold 8-bit data values
* **case** – Used in switch statements to mark blocks of text
* **catch** – Catches exceptions generated by try statements
* **char** – A data type that can hold unsigned 16-bit Unicode characters
* **class** -Declares a new class
* **continue** -Sends control back outside a loop
* **default** -Specifies the default block of code in a switch statement
* **do** -Starts a do-while loop
* **double** – A data type that can hold 64-bit floating-point numbers
* **else** – Indicates alternative branches in an if statement
* **enum** – A Java keyword used to declare an enumerated type. Enumerations extend the base class.
* **extends** -Indicates that a class is derived from another class or interface
* **final** -Indicates that a variable holds a constant value or that a method will not be overridden
* **finally** -Indicates a block of code in a try-catch structure that will always be executed
* **float** -A data type that holds a 32-bit floating-point number
* **for** -Used to start a for loop
* **if** -Tests a true/false expression and branches accordingly
* **implements** -Specifies that a class implements an interface
* **import** -References other classes
* **instanceof** -Indicates whether an object is an instance of a specific class or implements an interface
* **int** – A data type that can hold a 32-bit signed integer
* **interface** – Declares an interface
* **long** – A data type that holds a 64-bit integer
* **native** -Specifies that a method is implemented with native (platform-specific) code
* **new** – Creates new objects
* **null** -Indicates that a reference does not refer to anything
* **package** – Declares a Java package
* **private** -An access specifier indicating that a method or variable may be accessed only in the class it’s declared in
* **protected** – An access specifier indicating that a method or variable may only be accessed in the class it’s declared in (or a subclass of the class it’s declared in or other classes in the same package)
* **public** – An access specifier used for classes, interfaces, methods, and variables indicating that an item is accessible throughout the application (or where the class that defines it is accessible)
* **return** -Sends control and possibly a return value back from a called method
* **short** – A data type that can hold a 16-bit integer
* **static** -Indicates that a variable or method is a class method (rather than being limited to one particular object)
* **strictfp** – A Java keyword used to restrict the precision and rounding of floating point calculations to ensure portability.
* **super** – Refers to a class’s base class (used in a method or class constructor)
* **switch** -A statement that executes code based on a test value
* **synchronized** -Specifies critical sections or methods in multithreaded code
* **this** -Refers to the current object in a method or constructor
* **throw** – Creates an exception
* **throws** -Indicates what exceptions may be thrown by a method
* **transient** -Specifies that a variable is not part of an object’s persistent state
* **try** -Starts a block of code that will be tested for exceptions
* **void** -Specifies that a method does not have a return value
* **volatile** -Indicates that a variable may change asynchronously
* **while** -Starts a while loop

---

## Enums
* Every enum internally implemented by using Class.
* Every enum constant represents an object of type enum.
* enum type can be passed as an argument to switch statement.
* Every enum constant is always implicitly public static final. Since it is static, we can access it by using enum Name. Since it is final, we can’t create child enums.
* We can declare main() method inside enum. Hence we can invoke enum directly from the Command Prompt.
* enum can contain constructor and it is executed separately for each enum constant at the time of enum class loading.
* We can’t create enum objects explicitly and hence we can’t invoke enum constructor directly.
* enum can contain both concrete methods and abstract methods. If an enum class has an abstract method, then each instance of the enum class must implement it.

**values(), ordinal() and valueOf() methods** :
These methods are present inside java.lang.Enum.
* **values()** method can be used to return all values present inside enum.
* Order is important in enums.By using **ordinal()** method, each enum constant index can be found, just like array index.
* **valueOf()** method returns the enum constant of the specified string value, if exists.


### General code for enums
```java=1
// Java program to demonstrate working of values(), 
// ordinal() and valueOf() 
enum Color 
{ 
    RED, GREEN, BLUE; 
} 
  
public class Test 
{ 
    public static void main(String[] args) 
    { 
        // Calling values() 
        Color arr[] = Color.values(); 
  
        // enum with loop 
        for (Color col : arr) 
        { 
            // Calling ordinal() to find index 
            // of color. 
            System.out.println(col + " at index "
                             + col.ordinal()); 
        } 
  
        // Using valueOf(). Returns an object of 
        // Color with given constant. 
        // Uncommenting second line causes exception 
        // IllegalArgumentException 
        System.out.println(Color.valueOf("RED")); 
        // System.out.println(Color.valueOf("WHITE")); 
    } 
} 
```
```
Output :

RED at index 0
GREEN at index 1
BLUE at index 2
RED
```
### Enum with Customized Value
```java=1
// Java program to demonstrate how values can 
// be assigned to enums. 
enum TrafficSignal 
{ 
    // This will call enum constructor with one 
    // String argument 
    RED("STOP"), GREEN("GO"), ORANGE("SLOW DOWN"); 
  
    // declaring private variable for getting values 
    private String action; 
  
    // getter method 
    public String getAction() 
    { 
        return this.action; 
    } 
  
    // enum constructor - cannot be public or protected 
    private TrafficSignal(String action) 
    { 
        this.action = action; 
    } 
} 
  
// Driver code 
public class EnumConstructorExample 
{ 
    public static void main(String args[]) 
    { 
        // let's print name of each enum and there action 
        // - Enum values() examples 
        TrafficSignal[] signals = TrafficSignal.values(); 
  
        for (TrafficSignal signal : signals) 
        { 
            // use getter method to get the value 
            System.out.println("name : " + signal.name() + 
                        " action: " + signal.getAction() ); 
        } 
    } 
} 
```
```
Output:
name : RED action: STOP
name : GREEN action: GO 
name : ORANGE action: SLOW DOWN
```
---
## Currying Functions
Function Currying is a concept of breaking a function with many arguments into many functions with single argument in such a way, that the output is same. In other words, its a technique of simplifying a multi-valued argument function into single-valued argument multi-functions.
![](https://i.imgur.com/wp4q0Gf.png)

```java=1

// Java Program to demonstrate Function Currying 
  
import java.util.function.Function; 
  
public class GFG { 
    public static void main(String args[]) 
    { 
  
        // Using Java 8 Functions 
        // to create lambda expressions for functions 
        // and with this, applying Function Currying 
  
        // Curried Function for Adding u, v & w 
        Function<Integer, 
                 Function<Integer, 
                          Function<Integer, Integer> > > 
            triadder = u -> w -> v -> u + w + v; 
  
        // Calling the curried functions 
  
        // Calling Curried Function for Adding u, v & w 
        System.out.println("Add 2, 3, 4 :"
                           + triadder 
                                 .apply(2) 
                                 .apply(3) 
                                 .apply(4)); 
    } 
} 

Output:
Add 2, 3, 4 :9
```
---
## Implemented Methods
### Sorting
Arrays.sort method and Collection.sort() uses Timsort
```java=1
// for Arrays
int[] arr = { 13, 7, 6, 45, 21, 9, 101, 102 }; 
Arrays.sort(arr)
Arrays.sort(arr, 1, 5); // for subarray

// for Collections
ArrayList<String> al = new ArrayList<String>(); 
al.add("Geeks For Geeks"); 
al.add("Friends"); 
al.add("Dear"); 
al.add("Is"); 
al.add("Superb"); 
Collections.sort(al);
```

### Binary Search
```java=
// for Array
int key = 22; 
int res = Arrays.binarySearch(arr, key);

// for Collections
int key = 10; 
int res = Collections.binarySearch(al, key); 
```

### Swapping of two objects
If we create a wrapper class that contains references of Car, we can swap cars by swapping references of wrapper class.
```java=

// A Java program to demonstrate that we can use wrapper 
// classes to swap to objects 
  
// A car with model and no. 
class Car 
{ 
    int model, no; 
  
    // Constructor 
    Car(int model, int no) 
    { 
        this.model = model; 
        this.no = no; 
    } 
  
    // Utility method to print object details 
    void print() 
    { 
        System.out.println("no = " + no +  
                           ", model = " + model); 
    } 
} 
  
// A Wrapper over class that is used for swapping 
class CarWrapper 
{ 
   Car c; 
  
   // Constructor 
   CarWrapper(Car c)   {this.c = c;} 
} 
  
// A Class that use Car and swaps objects of Car 
// using CarWrapper 
class Main 
{ 
    // This method swaps car objects in wrappers 
    // cw1 and cw2 
    public static void swap(CarWrapper cw1,  
                            CarWrapper cw2) 
    { 
        Car temp = cw1.c; 
        cw1.c = cw2.c; 
        cw2.c = temp; 
    } 
  
    // Driver method 
    public static void main(String[] args) 
    { 
        Car c1 = new Car(101, 1); 
        Car c2 = new Car(202, 2); 
        CarWrapper cw1 = new CarWrapper(c1); 
        CarWrapper cw2 = new CarWrapper(c2); 
        swap(cw1, cw2); 
        cw1.c.print(); 
        cw2.c.print(); 
    } 
}
```
---
## Object Oriented Programming

### Class
<div style="text-align: justify">
A class is a user defined blueprint or prototype from which objects are created.  It represents the set of properties or methods that are common to all objects of one type. In general, class declarations can include these components **Modifiers, class keyword, class name, Supper class, Interfaces, Body**.

</div>

### Object
<div style="text-align: justify">
It is a basic unit of Object Oriented Programming and represents the real life entities.
An object consists of : 

1. **State** : It is represented by attributes of an object. It also reflects the properties of an object.
1. **Behavior** : It is represented by methods of an object. It also reflects the response of an object with other objects.
1. **Identity** : It gives a unique name to an object and enables one object to interact with other objects.
</div>

```java=
// Class Declaration
 
public class Dog
{
    // Instance Variables
    String name;
    String breed;
    int age;
    String color;
 
    // Constructor Declaration of Class
    public Dog(String name, String breed,
                   int age, String color)
    {
        this.name = name;
        this.breed = breed;
        this.age = age;
        this.color = color;
    }
 
    // method 1
    public String getName()
    {
        return name;
    }
 
    // method 2
    public String getBreed()
    {
        return breed;
    }
 
    // method 3
    public int getAge()
    {
        return age;
    }
 
    // method 4
    public String getColor()
    {
        return color;
    }
 
    @Override
    public String toString()
    {
        return("Hi my name is "+ this.getName()+
               ".\nMy breed,age and color are " +
               this.getBreed()+"," + this.getAge()+
               ","+ this.getColor());
    }
 
    public static void main(String[] args)
    {
        Dog tuffy = new Dog("tuffy","papillon", 5, "white");
        System.out.println(tuffy.toString());
    }
}

/*
Output: 
Hi my name is tuffy.
My breed,age and color are papillon,5,white
*/
```

#### Ways to create object of a class
* Using new keyboard
```java=
// Java program to illustrate creation of Object 
// using new keyword 
public class NewKeywordExample  
{ 
    String name = "GeeksForGeeks"; 
    public static void main(String[] args)  
    { 
        // Here we are creating Object of  
        // NewKeywordExample using new keyword 
        NewKeywordExample obj = new NewKeywordExample(); 
        System.out.println(obj.name); 
    } 
}
```
* Using Class.forName(String className) method
```java=
// Java program to illustrate creation of Object 
// using new Instance 
public class NewInstanceExample 
{ 
    String name = "GeeksForGeeks"; 
    public static void main(String[] args) 
    { 
        try
        { 
            Class cls = Class.forName("NewInstanceExample"); 
            NewInstanceExample obj = 
                    (NewInstanceExample) cls.newInstance(); 
            System.out.println(obj.name); 
        } 
        catch (ClassNotFoundException e) 
        { 
            e.printStackTrace(); 
        } 
        catch (InstantiationException e) 
        { 
            e.printStackTrace(); 
        } 
        catch (IllegalAccessException e) 
        { 
            e.printStackTrace(); 
        } 
    } 
} 
```
* Using clone() method
```java=
// Java program to illustrate creation of Object 
// using clone() method 
public class CloneExample implements Cloneable 
{ 
    @Override
    protected Object clone() throws CloneNotSupportedException 
    { 
        return super.clone(); 
    } 
    String name = "GeeksForGeeks"; 
  
    public static void main(String[] args) 
    { 
        CloneExample obj1 = new CloneExample(); 
        try
        { 
            CloneExample obj2 = (CloneExample) obj1.clone(); 
            System.out.println(obj2.name); 
        } 
        catch (CloneNotSupportedException e) 
        { 
            e.printStackTrace(); 
        } 
    } 
} 

```
* Deserialization
```java=
// Java program to illustrate Serializing 
// an Object. 
import java.io.*; 
  
class DeserializationExample implements Serializable 
{ 
    private String name; 
    DeserializationExample(String name) 
    { 
        this.name = name; 
    } 
  
    public static void main(String[] args) 
    { 
        try
        { 
            DeserializationExample d = 
                    new DeserializationExample("GeeksForGeeks"); 
            FileOutputStream f = new FileOutputStream("file.txt"); 
            ObjectOutputStream oos = new ObjectOutputStream(f); 
            oos.writeObject(d); 
            oos.close(); 
            f.close(); 
        } 
        catch (Exception e) 
        { 
            e.printStackTrace(); 
        } 
    } 
}
```
### Java objects stored in memory
<div style="text-align: justify">

In Java, all objects are dynamically allocated on Heap. This is different from C++ where objects can be allocated memory either on Stack or on Heap. In C++, when we allocate the object using new(), the object is allocated on Heap, otherwise on Stack if not global or static.

In Java, when we only declare a variable of a class type, only a reference is created (memory is not allocated for the object). To allocate memory to an object, we must use new(). So the object is always allocated memory on heap (See [this](https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/garbage_collect.html) for more details).
</div>

### Inheritance
<div style="text-align: justify">

It is the mechanism in java by which one class is allow to inherit the features(fields and methods) of another class. The keyword used for inheritance is extends.
**Important terminology:**
* **Super Class**: The class whose features are inherited is known as super class(or a base class or a parent class).
* **Sub Class**: The class that inherits the other class is known as sub class(or a derived class, extended class, or child class). The subclass can add its own fields and methods in addition to the superclass fields and methods.
* **Reusability**: Inheritance supports the concept of “reusability”, i.e. when we want to create a new class and there is already a class that includes some of the code that we want, we can derive our new class from the existing class. By doing this, we are reusing the fields and methods of the existing class.
</div>


```java=
//Java program to illustrate the  
// concept of inheritance 
  
// base class 
class Bicycle  
{ 
    // the Bicycle class has two fields 
    public int gear; 
    public int speed; 
          
    // the Bicycle class has one constructor 
    public Bicycle(int gear, int speed) 
    { 
        this.gear = gear; 
        this.speed = speed; 
    } 
          
    // the Bicycle class has three methods 
    public void applyBrake(int decrement) 
    { 
        speed -= decrement; 
    } 
          
    public void speedUp(int increment) 
    { 
        speed += increment; 
    } 
      
    // toString() method to print info of Bicycle 
    public String toString()  
    { 
        return("No of gears are "+gear 
                +"\n"
                + "speed of bicycle is "+speed); 
    }  
} 
  
// derived class 
class MountainBike extends Bicycle  
{ 
      
    // the MountainBike subclass adds one more field 
    public int seatHeight; 
  
    // the MountainBike subclass has one constructor 
    public MountainBike(int gear,int speed, 
                        int startHeight) 
    { 
        // invoking base-class(Bicycle) constructor 
        super(gear, speed); 
        seatHeight = startHeight; 
    }  
          
    // the MountainBike subclass adds one more method 
    public void setHeight(int newValue) 
    { 
        seatHeight = newValue; 
    }  
      
    // overriding toString() method 
    // of Bicycle to print more info 
    @Override
    public String toString() 
    { 
        return (super.toString()+ 
                "\nseat height is "+seatHeight); 
    } 
      
} 
  
// driver class 
public class Test  
{ 
    public static void main(String args[])  
    { 
          
        MountainBike mb = new MountainBike(3, 100, 25); 
        System.out.println(mb.toString()); 
              
    } 
}
```
#### **Types of Inheritance in Java**
1. **Single Inheritance**
![](https://i.imgur.com/G7QRqXs.png)
```java=
//Java program to illustrate the  
// concept of single inheritance 
import java.util.*; 
import java.lang.*; 
import java.io.*; 
  
class one 
{ 
    public void print_geek() 
    { 
        System.out.println("Geeks"); 
    } 
} 
  
class two extends one 
{ 
    public void print_for() 
    { 
        System.out.println("for"); 
    } 
} 
// Driver class 
public class Main 
{ 
    public static void main(String[] args) 
    { 
        two g = new two(); 
        g.print_geek(); 
        g.print_for(); 
        g.print_geek(); 
    } 
} 
```
2. **Multilevel Inheritance**
![](https://i.imgur.com/KSQJe3a.png)
```java=
// Java program to illustrate the  
// concept of Multilevel inheritance 
import java.util.*; 
import java.lang.*; 
import java.io.*; 
  
class one 
{ 
    public void print_geek() 
    { 
        System.out.println("Geeks"); 
    } 
} 
  
class two extends one 
{ 
    public void print_for() 
    { 
        System.out.println("for"); 
    } 
} 
  
class three extends two 
{ 
    public void print_geek() 
    { 
        System.out.println("Geeks"); 
    } 
} 
  
// Drived class 
public class Main 
{ 
    public static void main(String[] args) 
    { 
        three g = new three(); 
        g.print_geek(); 
        g.print_for(); 
        g.print_geek(); 
    } 
} 
```
3. **Hierarchical Inheritance** 
![](https://i.imgur.com/2oCi7EV.png)
```java=
// Java program to illustrate the  
// concept of Hierarchical inheritance 
import java.util.*; 
import java.lang.*; 
import java.io.*; 
  
class one 
{ 
    public void print_geek() 
    { 
        System.out.println("Geeks"); 
    } 
} 
  
class two extends one 
{ 
    public void print_for() 
    { 
        System.out.println("for"); 
    } 
} 
  
class three extends one 
{ 
    /*............*/
} 
  
// Drived class 
public class Main 
{ 
    public static void main(String[] args) 
    { 
        three g = new three(); 
        g.print_geek(); 
        two t = new two(); 
        t.print_for(); 
        g.print_geek(); 
    } 
} 
```
4. **Multiple Inheritance (Through Interfaces)** 
![](https://i.imgur.com/5LxrSEs.png)
```java=
// Java program to illustrate the  
// concept of Multiple inheritance 
import java.util.*; 
import java.lang.*; 
import java.io.*; 
   
interface one 
{ 
    public void print_geek(); 
} 
   
interface two 
{ 
    public void print_for(); 
} 
   
interface three extends one,two 
{ 
    public void print_geek(); 
} 
class child implements three 
{ 
    @Override
    public void print_geek() { 
        System.out.println("Geeks"); 
    } 
   
    public void print_for() 
    { 
        System.out.println("for"); 
    } 
} 
  
// Drived class 
public class Main 
{ 
    public static void main(String[] args) 
    { 
        child c = new child(); 
        c.print_geek(); 
        c.print_for(); 
        c.print_geek(); 
    } 
} 
```
5. **Hybrid Inheritance(Through Interfaces)**
![](https://i.imgur.com/68ccMGA.png)


### **Encapsualtion**
<div style="text-align: justify">

**Encapsulation** is defined as the wrapping up of data under a single unit. It is the mechanism that binds together code and the data it manipulates.Other way to think about encapsulation is, it is a protective shield that prevents the data from being accessed by the code outside this shield.
* Technically in encapsulation, the variables or data of a class is hidden from any other class and can be accessed only through any member function of own class in which they are declared.
* As in encapsulation, the data in a class is hidden from other classes using the data hiding concept which is achieved by making the members or methods of class as private and the class is exposed to the end user or the world without providing any details behind implementation using the abstraction concept, so it is also known as **combination of data-hiding and abstraction**.
* Encapsulation can be achieved by: Declaring all the variables in the class as private and writing public methods in the class to set and get the values of variables.
</div>

```java=
// Java program to demonstrate encapsulation 
public class Encapsulate 
{ 
    // private variables declared  
    // these can only be accessed by  
    // public methods of class 
    private String geekName; 
    private int geekRoll; 
    private int geekAge; 
  
    // get method for age to access  
    // private variable geekAge 
    public int getAge()  
    { 
      return geekAge; 
    } 
   
    // get method for name to access  
    // private variable geekName 
    public String getName()  
    { 
      return geekName; 
    } 
      
    // get method for roll to access  
    // private variable geekRoll 
    public int getRoll()  
    { 
       return geekRoll; 
    } 
   
    // set method for age to access  
    // private variable geekage 
    public void setAge( int newAge) 
    { 
      geekAge = newAge; 
    } 
   
    // set method for name to access  
    // private variable geekName 
    public void setName(String newName) 
    { 
      geekName = newName; 
    } 
      
    // set method for roll to access  
    // private variable geekRoll 
    public void setRoll( int newRoll)  
    { 
      geekRoll = newRoll; 
    } 
} 

// using above class in TestEncapsulation
public class TestEncapsulation 
{     
    public static void main (String[] args)  
    { 
        Encapsulate obj = new Encapsulate(); 
          
        // setting values of the variables  
        obj.setName("Harsh"); 
        obj.setAge(19); 
        obj.setRoll(51); 
          
        // Displaying values of the variables 
        System.out.println("Geek's name: " + obj.getName()); 
        System.out.println("Geek's age: " + obj.getAge()); 
        System.out.println("Geek's roll: " + obj.getRoll()); 
          
        // Direct access of geekRoll is not possible 
        // due to encapsulation 
        // System.out.println("Geek's roll: " + obj.geekName);         
    } 
} 
```

### Abstraction
<div style="text-align: justify">

Data Abstraction is the property by virtue of which only the essential details are displayed to the user.The trivial or the non-essentials units are not displayed to the user. Ex: A car is viewed as a car rather than its individual components.

Data Abstraction may also be defined as the process of identifying only the required characteristics of an object ignoring the irrelevant details.The properties and behaviors of an object differentiate it from other objects of similar type and also help in classifying/grouping the objects.

#### Abstract classes and Abstract methods
* An abstract class is a class that is declared with **abstract** keyword.
* An abstract method is a method that is declared without an implementation.
* An abstract class may or may not have all abstract methods. Some of them can be concrete methods
* A method defined abstract must always be redefined in the subclass,thus making overriding compulsory OR either make subclass itself abstract.
* Any class that contains one or more abstract methods must also be declared with abstract keyword.
* There can be no object of an abstract class.That is, an abstract class can not be directly instantiated with the new operator.
* An abstract class can have parametrized constructors and default constructor is always present in an abstract class.

</div>

```java=
// Java program to illustrate the 
// concept of Abstraction 
abstract class Shape  
{ 
    String color; 
      
    // these are abstract methods 
    abstract double area(); 
    public abstract String toString(); 
      
    // abstract class can have constructor 
    public Shape(String color) { 
        System.out.println("Shape constructor called"); 
        this.color = color; 
    } 
      
    // this is a concrete method 
    public String getColor() { 
        return color; 
    } 
} 
class Circle extends Shape 
{ 
    double radius; 
      
    public Circle(String color,double radius) { 
  
        // calling Shape constructor 
        super(color); 
        System.out.println("Circle constructor called"); 
        this.radius = radius; 
    } 
  
    @Override
    double area() { 
        return Math.PI * Math.pow(radius, 2); 
    } 
  
    @Override
    public String toString() { 
        return "Circle color is " + super.color +  
                       "and area is : " + area(); 
    } 
      
} 
class Rectangle extends Shape{ 
  
    double length; 
    double width; 
      
    public Rectangle(String color,double length,double width) { 
        // calling Shape constructor 
        super(color); 
        System.out.println("Rectangle constructor called"); 
        this.length = length; 
        this.width = width; 
    } 
      
    @Override
    double area() { 
        return length*width; 
    } 
  
    @Override
    public String toString() { 
        return "Rectangle color is " + super.color +  
                           "and area is : " + area(); 
    } 
  
} 
public class Test  
{ 
    public static void main(String[] args) 
    { 
        Shape s1 = new Circle("Red", 2.2); 
        Shape s2 = new Rectangle("Yellow", 2, 4); 
          
        System.out.println(s1.toString()); 
        System.out.println(s2.toString()); 
    } 
}
```

**Encapsulation vs Data Abstraction**

* Encapsulation is data hiding(information hiding) while Abstraction is detail hiding(implementation hiding).
* While encapsulation groups together data and methods that act upon the data, data abstraction deals with exposing the interface to the user and hiding the details of implementation.

### Interfaces
<div style="text-align: justify">
Like a class, an interface can have methods and variables, but the methods declared in an interface are by default abstract (only method signature, no body).
* Interfaces specify what a class must do and not how. It is the blueprint of the class.
* An Interface is about capabilities like a Player may be an interface and any class implementing Player must be able to (or must implement) move(). So it specifies a set of methods that the class has to implement.
* If a class implements an interface and does not provide method bodies for all functions specified in the interface, then the class must be declared abstract.
</div>

```java=
import java.io.*; 
  
interface Vehicle { 
      
    // all are the abstract methods. 
    void changeGear(int a); 
    void speedUp(int a); 
    void applyBrakes(int a); 
} 
  
class Bicycle implements Vehicle{ 
      
    int speed; 
    int gear; 
      
     // to change gear 
    @Override
    public void changeGear(int newGear){ 
          
        gear = newGear; 
    } 
      
    // to increase speed 
    @Override
    public void speedUp(int increment){ 
          
        speed = speed + increment; 
    } 
      
    // to decrease speed 
    @Override
    public void applyBrakes(int decrement){ 
          
        speed = speed - decrement; 
    } 
      
    public void printStates() { 
         System.out.println("speed: " + speed 
              + " gear: " + gear); 
    } 
} 
  
class Bike implements Vehicle { 
      
    int speed; 
    int gear; 
      
    // to change gear 
    @Override
    public void changeGear(int newGear){ 
          
        gear = newGear; 
    } 
      
    // to increase speed 
    @Override
    public void speedUp(int increment){ 
          
        speed = speed + increment; 
    } 
      
    // to decrease speed 
    @Override
    public void applyBrakes(int decrement){ 
          
        speed = speed - decrement; 
    } 
      
    public void printStates() { 
         System.out.println("speed: " + speed 
             + " gear: " + gear); 
    } 
      
} 
class GFG { 
      
    public static void main (String[] args) { 
      
        // creating an inatance of Bicycle  
        // doing some operations  
        Bicycle bicycle = new Bicycle(); 
        bicycle.changeGear(2); 
        bicycle.speedUp(3); 
        bicycle.applyBrakes(1); 
          
        System.out.println("Bicycle present state :"); 
        bicycle.printStates(); 
          
        // creating instance of the bike. 
        Bike bike = new Bike(); 
        bike.changeGear(1); 
        bike.speedUp(4); 
        bike.applyBrakes(3); 
          
        System.out.println("Bike present state :"); 
        bike.printStates(); 
    } 
} 
```

### Polymorphism
#### Static Polymorphism or Overlading
<div style="text-align: justify">
Overloading allows different methods to have the same name, but different signatures where the signature can differ by the number of input parameters or type of input parameters or both. Overloading is related to compile-time (or static) polymorphism.
</div>

```java=
// Java program to demonstrate working of method 
// overloading in Java. 
  
public class Sum { 
  
    // Overloaded sum(). This sum takes two int parameters 
    public int sum(int x, int y) 
    { 
        return (x + y); 
    } 
  
    // Overloaded sum(). This sum takes three int parameters 
    public int sum(int x, int y, int z) 
    { 
        return (x + y + z); 
    } 
  
    // Overloaded sum(). This sum takes two double parameters 
    public double sum(double x, double y) 
    { 
        return (x + y); 
    } 
  
    // Driver code 
    public static void main(String args[]) 
    { 
        Sum s = new Sum(); 
        System.out.println(s.sum(10, 20)); 
        System.out.println(s.sum(10, 20, 30)); 
        System.out.println(s.sum(10.5, 20.5)); 
    } 
} 
```


#### Runtime Polymorphism
<div style="text-align: justify">

**Method overriding** is one of the ways in which Java supports Runtime Polymorphism. Dynamic method dispatch is the mechanism by which a call to an overridden method is resolved at run time, rather than compile time.

* When an overridden method is called through a superclass reference, Java determines which version(superclass/subclasses) of that method is to be executed based upon the type of the object being referred to at the time the call occurs. Thus, this determination is made at run time.
* At run-time, it depends on the type of the object being referred to (not the type of the reference variable) that determines which version of an overridden method will be executed
* A superclass reference variable can refer to a subclass object. This is also known as upcasting. Java uses this fact to resolve calls to overridden methods at run time.

</div>

```java=
// A Java program to illustrate Dynamic Method 
// Dispatch using hierarchical inheritance 
class A 
{ 
    void m1() 
    { 
        System.out.println("Inside A's m1 method"); 
    } 
} 
  
class B extends A 
{ 
    // overriding m1() 
    void m1() 
    { 
        System.out.println("Inside B's m1 method"); 
    } 
} 
  
class C extends A 
{ 
    // overriding m1() 
    void m1() 
    { 
        System.out.println("Inside C's m1 method"); 
    } 
} 
  
// Driver class 
class Dispatch 
{ 
    public static void main(String args[]) 
    { 
        // object of type A 
        A a = new A(); 
  
        // object of type B 
        B b = new B(); 
  
        // object of type C 
        C c = new C(); 
  
        // obtain a reference of type A 
        A ref; 
          
        // ref refers to an A object 
        ref = a; 
  
        // calling A's version of m1() 
        ref.m1(); 
  
        // now ref refers to a B object 
        ref = b; 
  
        // calling B's version of m1() 
        ref.m1(); 
  
        // now ref refers to a C object 
        ref = c; 
  
        // calling C's version of m1() 
        ref.m1(); 
    } 
} 

Output:
Inside A's m1 method
Inside B's m1 method
Inside C's m1 method
```

<div style="text-align: justify">

**Rules for method overriding:**
1. **Overriding and Access-Modifiers** : The access modifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the super-class can be made public, but not private, in the subclass. Doing so, will generate compile-time error.
2. **Final methods can not be overridden** : If we don’t want a method to be overridden, we declare it as final. Please see Using final with Inheritance.
3. **Static methods can not be overridden(Method Overriding vs Method Hiding)** : When you define a static method with same signature as a static method in base class, it is known as method hiding.
4. **Private methods can not be overridden** : Private methods cannot be overridden as they are bonded during compile time. Therefore we can’t even override private methods in a subclass.(See this for details).
5. **The overriding method must have same return type (or subtype)** : From Java 5.0 onwards it is possible to have different return type for a overriding method in child class, but child’s return type should be sub-type of parent’s return type. This phenomena is known as [covariant return type](https://www.geeksforgeeks.org/covariant-return-types-java/).
6. **Invoking overridden method from sub-class** : We can call parent class method in overriding method using super keyword.
7. **Overriding and constructor** : We can not override constructor as parent and child class can never have constructor with same name(Constructor name must always be same as Class name).
8. **Overriding and Exception-Handling** : Below are two rules to note when overriding methods related to exception-handling.
    - **Rule#1** : If the super-class overridden method does not throw an exception, subclass overriding method can only throws the unchecked exception, throwing checked exception will lead to compile-time error.
    - **Rule#2** : If the super-class overridden method does throws an exception, subclass overriding method can only throw same, subclass exception. Throwing parent exception in Exception hierarchy will lead to compile time error.Also there is no issue if subclass overridden method is not throwing any exception.
9. **Overriding and abstract method**: Abstract methods in an interface or abstract class are meant to be overridden in derived concrete classes otherwise a compile-time error will be thrown.
10. **Overriding and synchronized/strictfp method** : The presence of synchronized/strictfp modifier with method have no effect on the rules of overriding, i.e. it’s possible that a synchronized/strictfp method can override a non synchronized/strictfp one and vice-versa.
</div>

### Access and Non Access Modifiers
<div style="text-align: justify">

**Access Modifiers** : Java’s access modifiers are public, private, and protected. Java also defines a default access level (called package-private).

- **public**: When a member of a class is modified by public, then that member can be accessed by any other code.
- **private**: When a member of a class is specified as private, then that member can only be accessed by other members of its class.
- **protected**: It is same as private with a difference that it can be accessed in subclasses only when inheritance is involved.

![](https://i.imgur.com/KL22kDm.png)

**Non-access modifiers** : In java, we have 7 non-access modifiers. They are used with classes, methods, variables, constructors etc to provide information about their behavior to JVM.They are
* [static](https://www.geeksforgeeks.org/static-keyword-java/)
* [final](https://www.geeksforgeeks.org/final-keyword-java/)
* [abstract](https://www.geeksforgeeks.org/abstract-keyword-in-java/)
* synchronized
* [transient](https://www.geeksforgeeks.org/transient-keyword-java/)
* [volatile](https://www.geeksforgeeks.org/volatile-keyword-in-java/)
* native

</div>


### Static methods vs Instance methods

<div style="text-align: justify">

**Instance method** are methods which require an object of its class to be created before it can be called. To invoke a instance method, we have to create an Object of the class in within which it defined.

**Memory allocation**: These methods themselves are stored in Permanent Generation space of heap but the parameters (arguments passed to them) and their local variables and the value to be returned are allocated in stack. They can be called within the same class in which they reside or from the different classes defined either in the same package or other packages depend on the access type provided to the desired instance method.

**Important Points**:

* Instance method(s) belong to the Object of the class not to the class i.e. they can be called after creating the Object of the class.
* Every individual Object created from the class has its own copy of the instance method(s) of that class.
* Instance methods are not stored on a per-instance basis, even with virtual methods. They’re stored in a single memory location, and they only “know” which object they belong to because the this pointer is passed when you call them.
* They can be overridden since they are resolved using dynamic binding at run time.


**Static methods** are the methods in Java that can be called without creating an object of class. They are referenced by the class name itself or reference to the Object of that class.

**Memory Allocation**: They are stored in Permanent Generation space of heap as they are associated to the class in which they reside not to the objects of that class. But their local variables and the passed argument(s) to them are stored in the stack. Since they belong to the class so they can be called to without creating the object of the class.

**Important Points:**

* Static method(s) are associated to the class in which they reside i.e. they can be called even without creating an instance of the class i.e ClassName.methodName(args).
* They are designed with aim to be shared among all Objects created from the same class.
* Static methods can not be overridden. But can be overloaded since they are resolved using static binding by compiler at compile time.
</div>


### Object class 
1. **toString()**
2. **hashCode()**
3. **equals(Object obj)**
4. **getClass()**
5. **finalize()**
6. **clone()**
7. **wait()**
8. **notify()**
9. **notifyAll()**


---
### Association, Composition and Aggregation in Java
![](https://i.imgur.com/lGWqb7L.png)

<div style="text-align: justify">

**Association** is relation between two separate classes which establishes through their Objects. Association can be one-to-one, one-to-many, many-to-one, many-to-many.
In Object-Oriented programming, an Object communicates to other Object to use functionality and services provided by that object. Composition and Aggregation are the two forms of association.
</div>

```java=
// Java program to illustrate the  
// concept of Association 
import java.io.*; 
  
// class bank 
class Bank  
{ 
    private String name; 
      
    // bank name 
    Bank(String name) 
    { 
        this.name = name; 
    } 
      
    public String getBankName() 
    { 
        return this.name; 
    } 
}  
  
// employee class  
class Employee 
{ 
    private String name; 
      
    // employee name  
    Employee(String name)  
    { 
        this.name = name; 
    } 
      
    public String getEmployeeName() 
    { 
        return this.name; 
    }  
} 
  
// Association between both the  
// classes in main method 
class Association  
{ 
    public static void main (String[] args)  
    { 
        Bank bank = new Bank("Axis"); 
        Employee emp = new Employee("Neha"); 
          
        System.out.println(emp.getEmployeeName() +  
               " is employee of " + bank.getBankName()); 
    } 
} 
```

**Aggregation** is a special form of Association where:
* It represents **Has-A** relationship.
* It is a **unidirectional association** i.e. a one way relationship. For example, department can have students but vice versa is not possible and thus unidirectional in nature.
* In Aggregation, **both the entries can survive individually** which means ending one entity will not effect the other entity


```java=
// Java program to illustrate 
//the concept of Aggregation. 
import java.io.*; 
import java.util.*; 
  
// student class 
class Student  
{ 
    String name; 
    int id ; 
    String dept; 
      
    Student(String name, int id, String dept)  
    { 
          
        this.name = name; 
        this.id = id; 
        this.dept = dept; 
          
    } 
} 
  
/* Department class contains list of student 
Objects. It is associated with student 
class through its Object(s). */
class Department  
{ 
      
    String name; 
    private List<Student> students; 
    Department(String name, List<Student> students)  
    { 
          
        this.name = name; 
        this.students = students; 
          
    } 
      
    public List<Student> getStudents()  
    { 
        return students; 
    } 
} 
  
/* Institute class contains list of Department 
Objects. It is asoociated with Department 
class through its Object(s).*/
class Institute  
{ 
      
    String instituteName; 
    private List<Department> departments; 
      
    Institute(String instituteName, List<Department> departments) 
    { 
        this.instituteName = instituteName; 
        this.departments = departments; 
    } 
      
    // count total students of all departments 
    // in a given institute  
    public int getTotalStudentsInInstitute() 
    { 
        int noOfStudents = 0; 
        List<Student> students;  
        for(Department dept : departments) 
        { 
            students = dept.getStudents(); 
            for(Student s : students) 
            { 
                noOfStudents++; 
            } 
        } 
        return noOfStudents; 
    } 
      
}  
  
// main method 
class GFG 
{ 
    public static void main (String[] args)  
    { 
        Student s1 = new Student("Mia", 1, "CSE"); 
        Student s2 = new Student("Priya", 2, "CSE"); 
        Student s3 = new Student("John", 1, "EE"); 
        Student s4 = new Student("Rahul", 2, "EE"); 
      
        // making a List of  
        // CSE Students. 
        List <Student> cse_students = new ArrayList<Student>(); 
        cse_students.add(s1); 
        cse_students.add(s2); 
          
        // making a List of  
        // EE Students 
        List <Student> ee_students = new ArrayList<Student>(); 
        ee_students.add(s3); 
        ee_students.add(s4); 
          
        Department CSE = new Department("CSE", cse_students); 
        Department EE = new Department("EE", ee_students); 
          
        List <Department> departments = new ArrayList<Department>(); 
        departments.add(CSE); 
        departments.add(EE); 
          
        // creating an instance of Institute. 
        Institute institute = new Institute("BITS", departments); 
          
        System.out.print("Total students in institute: "); 
        System.out.print(institute.getTotalStudentsInInstitute()); 
    } 
} 
```

**Composition** is a restricted form of Aggregation in which two entities are highly dependent on each other.
* It represents **part-of** relationship.
* In composition, both the entities are dependent on each other.
* When there is a composition between two entities, the composed object **cannot exist** without the other entity.

```java=
// Java program to illustrate  
// the concept of Composition 
import java.io.*; 
import java.util.*; 
  
// class book 
class Book  
{ 
  
    public String title; 
    public String author; 
      
    Book(String title, String author) 
    { 
          
        this.title = title; 
        this.author = author; 
    } 
} 
  
// Libary class contains  
// list of books. 
class Library  
{ 
  
    // reference to refer to list of books. 
    private final List<Book> books; 
      
    Library (List<Book> books) 
    { 
        this.books = books;  
    } 
      
    public List<Book> getTotalBooksInLibrary(){ 
          
       return books;   
    } 
      
} 
  
// main method 
class GFG  
{ 
    public static void main (String[] args)  
    { 
          
        // Creating the Objects of Book class. 
        Book b1 = new Book("EffectiveJ Java", "Joshua Bloch"); 
        Book b2 = new Book("Thinking in Java", "Bruce Eckel"); 
        Book b3 = new Book("Java: The Complete Reference", "Herbert Schildt"); 
          
        // Creating the list which contains the  
        // no. of books. 
        List<Book> books = new ArrayList<Book>(); 
        books.add(b1); 
        books.add(b2); 
        books.add(b3); 
          
        Library library = new Library(books); 
          
        List<Book> bks = library.getTotalBooksInLibrary(); 
        for(Book bk : bks){ 
              
            System.out.println("Title : " + bk.title + " and " 
            +" Author : " + bk.author); 
        } 
    } 
} 
```
---

## Operator Precedence and Associativity
![](https://i.imgur.com/Gy9JHNn.png)

---

## Strings in Java
- [String](https://www.geeksforgeeks.org/string-class-in-java/): Immutable
- [StringBuffer](https://www.geeksforgeeks.org/stringbuffer-class-in-java/): Mutable and Synchronised
- [StringBuilder](https://www.geeksforgeeks.org/stringbuilder-class-in-java-with-examples/): Mutable and Non Sync
- [StringTokenizer](https://www.geeksforgeeks.org/stringtokenizer-class-java-example-set-1-constructors/)
- [StringJoiner](https://www.geeksforgeeks.org/java-util-stringjoiner-java8/)

---
## Arrays In Java
- [Array Classes](https://www.geeksforgeeks.org/array-class-in-java/)
- [Reflection Array Class](https://www.geeksforgeeks.org/reflection-array-class-in-java/)
- [Jagged Array](https://www.geeksforgeeks.org/jagged-array-in-java/)
---
## Exceptions In Java
An **exception** is an unwanted or unexpected event, which occurs during the execution of a program i.e at run time, that disrupts the normal flow of the program’s instructions.
![](https://i.imgur.com/w7sJ5FZ.png)

**Default Exception Handling** : Whenever inside a method, if an exception has occurred, the method creates an Object known as Exception Object and hands it off to the run-time system(JVM). The exception object contains name and description of the exception, and current state of the program where exception has occurred. Creating the Exception Object and handling it to the run-time system is called throwing an Exception.There might be the list of the methods that had been called to get to the method where exception was occurred. This ordered list of the methods is called Call Stack.Now the following procedure will happen.
* The run-time system searches the call stack to find the method that contains block of code that can handle the occurred exception. The block of the code is called **Exception handler**.
* The run-time system starts searching from the method in which exception occurred, proceeds through call stack in the reverse order in which methods were called.
* If it finds  appropriate handler then it passes the occurred exception to it. Appropriate handler means the type of the exception object thrown matches the type of the exception object it can handle.
* If run-time system searches all the methods on call stack and couldn’t have found the appropriate handler then run-time system handover the Exception Object to **default exception handler** , which is part of run-time system. This handler prints the exception information in the following format and terminates program **abnormally**.

**Customized Exception Handling** : Java exception handling is managed via five keywords: **try, catch, throw, throws, and finally**. Briefly, here is how they work. Program statements that you think can raise exceptions are contained within a try block. If an exception occurs within the try block, it is thrown. Your code can catch this exception (using catch block) and handle it in some rational manner. System-generated exceptions are automatically thrown by the Java run-time system. To manually throw an exception, use the keyword throw. Any exception that is thrown out of a method must be specified as such by a throws clause. Any code that absolutely must be executed after a try block completes is put in a finally block.

### Types of Exceptions:
![](https://i.imgur.com/qky6pZS.png)
**Built-in exceptions**
* **ArithmeticException**: It is thrown when an exceptional condition has occurred in an arithmetic operation.
* **ArrayIndexOutOfBoundsException**: It is thrown to indicate that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.
* **ClassNotFoundException**: This Exception is raised when we try to access a class whose definition is not found
* **FileNotFoundException**: This Exception is raised when a file is not accessible or does not open.
* **IOException**: It is thrown when an input-output operation failed or interrupted
* **InterruptedException**: It is thrown when a thread is waiting , sleeping , or doing some processing , and it is interrupted.
* **NoSuchFieldException**: It is thrown when a class does not contain the field (or variable) specified
* **NoSuchMethodException**: It is thrown when accessing a method which is not found.
* **NullPointerException**: This exception is raised when referring to the members of a null object. Null represents nothing
* **NumberFormatException**: This exception is raised when a method could not convert a string into a numeric format.
* **RuntimeException**: This represents any exception which occurs during runtime.
* **StringIndexOutOfBoundsException**: It is thrown by String class methods to indicate that an index is either negative than the size of the string

### Errors in Java
- StackOverflowError 
- [OutOfMemoryError](https://www.geeksforgeeks.org/understanding-outofmemoryerror-exception-java/)
    - Java Heap Space
    - Garbage Collector Overhead limit exceeded 
    - Permgen space is thrown
    - Metaspace 
    - Requested array size exceeds VM limit
    - Request size bytes for reason. Out of swap space
    - Reason stack_trace_with_native_method


### Printing Exceptions
- e.printStackTrace()
- System.out.println(e.toString())
- System.out.println(e.getMessage())

---

## Collections
Any group of individual objects which are represented as a single unit is known as the collection of the objects. In Java, a separate framework named the “**Collection Framework**” 

A **framework** is a set of classes and interfaces which provide a ready-made architecture. In order to implement a new feature or a class, there is no need to define a framework. However, an optimal object-oriented design always includes a framework with a collection of classes such that all the classes perform the same kind of task.

Before Collection the standard way of grouping objects were **Arrays, Vectors and HashTables**
```java=
// Java program to demonstrate 
// why collection framework was needed 
import java.io.*; 
import java.util.*; 
  
class CollectionDemo { 
  
    public static void main(String[] args) 
    { 
        // Creating instances of the array, 
        // vector and hashtable 
        int arr[] = new int[] { 1, 2, 3, 4 }; 
        Vector<Integer> v = new Vector(); 
        Hashtable<Integer, String> h 
            = new Hashtable(); 
  
        // Adding the elements into the 
        // vector 
        v.addElement(1); 
        v.addElement(2); 
  
        // Adding the element into the 
        // hashtable 
        h.put(1, "geeks"); 
        h.put(2, "4geeks"); 
  
        // Array instance creation requires [], 
        // while Vector and hastable require () 
        // Vector element insertion requires addElement(), 
        // but hashtable element insertion requires put() 
  
        // Accessing the first element of the 
        // array, vector and hashtable 
        System.out.println(arr[0]); 
        System.out.println(v.elementAt(0)); 
        System.out.println(h.get(1)); 
  
        // Array elements are accessed using [], 
        // vector elements using elementAt() 
        // and hashtable elements using get() 
    } 
```
**Advantages of the Collection Framework:** Since the lack of collection framework gave rise to the above set of disadvantages, the following are the advantages of the collection framework.

* **Consistent API**: The API has a basic set of interfaces like Collection, Set, List, or Map, all the classes (ArrayList, LinkedList, Vector, etc) that implement these interfaces have some common set of methods.
* **Reduces programming effort**: A programmer doesn’t have to worry about the design of the Collection but rather he can focus on its best use in his program. Therefore, the basic concept of Object-oriented programming (i.e.) abstraction has been successfully implemented.
* **Increases program speed and quality**: Increases performance by providing high-performance implementations of useful data structures and algorithms because in this case, the programmer need not think of the best implementation of a specific data structure. He can simply use the best implementation to drastically boost the performance of his algorithm/program.

### Hierarchy of the Collection Framework
![](https://i.imgur.com/Su8SNa1.png)

### Methods of the Collection Interface



| Method                     | Description                                                                                                                                                     |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **add(Object)**                | This method is used to add an object to the collection.                                                                                                         |
| **addAll(Collection c)**       | This method adds all the elements in the given collection to this collection.                                                                                   |
| **clear()**                    | This method removes all of the elements from this collection.                                                                                                   |
| **contains(Object o)**         | This method returns true if the collection contains the specified element.                                                                                      |
| **containsAll(Collection c)**  | This method returns true if the collection contains all of the elements in the given collection.                                                                |
| **equals(Object o)**           | This method compares the specified object with this collection for equality.                                                                                    |
| **hashCode()**                 | This method is used to return the hash code value for this collection.                                                                                          |
| **isEmpty()**                  | This method returns true if this collection contains no elements.                                                                                               |
| **iterator()**                 | This method returns an iterator over the elements in this collection.                                                                                           |
| **max()**                      | This method is used to return the maximium value present in the collection.                                                                                     |
| **parallelStream()**           | This method returns a parallel Stream with this collection as its source.                                                                                       |
| **remove(Object o)**           | This method is used to remove the given object from the collection. If there are duplicate values, then this method removes the first occurrence of the object. |
| **removeAll(Collection c)**    | This method is used to remove all the objects mentioned in the given collection from the collection.                                                            |
| **removeIf(Predicate filter)** | This method is used to removes all the elements of this collection that satisfy the given predicate.                                                            |
| **retainAll(Collection c)**    | This method is used to retains only the elements in this collection that are contained in the specified collection.                                             |
| **size()**                     | This method is used to return the number of elements in the collection.                                                                                         |
| **spliterator()**             | This method is used to create a Spliterator over the elements in this collection.                                                                               |
| **stream()**                  | This method is used to return a sequential Stream with this collection as its source.                                                                          |
| **toArray()**                  | This method is used to return an array containing all of the elements in this collection.                                                                       |

### Interfaces which extend the Collections Interface
1. **Iterable Interface**: This is the root interface for the entire collection framework. The collection interface extends the iterable interface. Therefore, inherently, all the interfaces and classes implement this interface. The main functionality of this interface is to provide an iterator for the collections. Therefore, this interface contains only one abstract method which is the iterator. It returns the
2. **Collection Interface**: This interface extends the iterable interface and is implemented by all the classes in the collection framework. This interface contains all the basic methods which every collection has like adding the data into the collection, removing the data, clearing the data, etc. All these methods are implemented in this interface because these methods are implemented by all the classes irrespective of their style of implementation. And also, having these methods in this interface ensures that the names of the methods are universal for all the collections. Therefore, in short, we can say that this interface builds a foundation on which the collection classes are implemented.
3. **List Interface**: This is a child interface of the collection interface. This interface is dedicated to the data of the list type in which we can store all the ordered collection of the objects. This also allows duplicate data to be present in it. This list interface is implemented by various classes like ArrayList, Vector, Stack, etc. Since all the subclasses implement the list, we can instantiate a list object with any of these classes. 
![](https://i.imgur.com/zBgAl9d.png)

### Iterators in Java
#### Enumeration
It is a interface used to get elements of legacy collections(Vector, Hashtable).
We can create Enumeration object by calling elements() method of vector class on any vector object

```java=
// Java program to demonstrate Enumeration 
import java.util.Enumeration; 
import java.util.Vector; 
  
public class Test 
{ 
    public static void main(String[] args) 
    { 
        // Create a vector and print its contents 
        Vector v = new Vector(); 
        for (int i = 0; i < 10; i++) 
            v.addElement(i); 
        System.out.println(v); 
  
        // At beginning e(cursor) will point to 
        // index just before the first element in v 
        Enumeration e = v.elements(); 
  
        // Checking the next element availability 
        while (e.hasMoreElements()) 
        { 
            // moving cursor to next element 
            int i = (Integer)e.nextElement(); 
  
            System.out.print(i + " "); 
        } 
    } 
} 

Output:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 1 2 3 4 5 6 7 8 9 
```
**Limitations of Enumeration** :
* Enumeration is for legacy classes(Vector, Hashtable) only. Hence it is not a universal iterator.
* Remove operations can’t be performed using Enumeration.
* Only forward direction iterating is possible

#### Iterator
It is a universal iterator as we can apply it to any Collection object. By using Iterator, we can perform both read and remove operations. It is improved version of Enumeration with additional functionality of remove-ability of a element.
remove() method can throw two exceptions:
UnsupportedOperationException : If the remove operation is not supported by this iterator
IllegalStateException : If the next method has not yet been called, or the remove method has already been called after the last call to the next method

```java=
// Java program to demonstrate Iterator 
import java.util.ArrayList; 
import java.util.Iterator; 
  
public class Test 
{ 
    public static void main(String[] args) 
    { 
        ArrayList<Integer> al = new ArrayList<Integer>(); 
  
        for (int i = 0; i < 10; i++) 
            al.add(i); 
  
        System.out.println(al); 
  
        // at beginning itr(cursor) will point to 
        // index just before the first element in al 
        Iterator itr = al.iterator(); 
  
        // checking the next element availabilty 
        while (itr.hasNext()) 
        { 
            //  moving cursor to next element 
            int i = (Integer)itr.next(); 
  
            // getting even elements one by one 
            System.out.print(i + " "); 
  
            // Removing odd elements 
            if (i % 2 != 0) 
               itr.remove();  
        } 
        System.out.println();  
        System.out.println(al); 
    } 
}
```
Limitations of Iterator :
* Only forward direction iterating is possible.
* Replacement and addition of new element is not supported by Iterator.

#### ListIterator
It is only applicable for List collection implemented classes like arraylist, linkedlist etc. It provides bi-directional iteration.
ListIterator must be used when we want to enumerate elements of List. This cursor has more functionality(methods) than iterator.
- public boolean hasNext()
- public Object next()
- public int nextIndex()
- public boolean hasPrevious()
- public Object previous()
- public int previousIndex()
- public void remove()
- public void set(Object obj)
- public void add(Object obj)

set() method can throw four exceptions:
- UnsupportedOperationException – if the set operation is not supported by this list iterator
- ClassCastException : If the class of the specified element prevents it from being added to this list
- IllegalArgumentException : If some aspect of the specified element prevents it from being added to this list
- IllegalStateException : If neither next nor previous have been called, or remove or add have been called after the last call to next or previous

add() method can throw three exceptions
- UnsupportedOperationException : If the add method is not supported by this list iterator
- ClassCastException : If the class of the specified element prevents it from being added to this list
- IllegalArgumentException : If some aspect of this element prevents it from being added to this list

```java=
// Java program to demonstrate ListIterator 
import java.util.ArrayList; 
import java.util.ListIterator; 
  
public class Test 
{ 
    public static void main(String[] args) 
    { 
        ArrayList al = new ArrayList(); 
        for (int i = 0; i < 10; i++) 
            al.add(i); 
  
        System.out.println(al); 
  
        // at beginning ltr(cursor) will point to 
        // index just before the first element in al 
        ListIterator ltr = al.listIterator(); 
  
        // checking the next element availabilty 
        while (ltr.hasNext()) 
        { 
            //  moving cursor to next element 
            int i = (Integer)ltr.next(); 
  
            // getting even elements one by one 
            System.out.print(i + " "); 
  
            // Changing even numbers to odd and 
            // adding modified number again in  
            // iterator 
            if (i%2==0) 
            { 
                i++;  // Change to odd 
                ltr.set(i);  // set method to change value 
                ltr.add(i);  // to add 
            } 
        } 
        System.out.println(); 
        System.out.println(al); 
    } 
}
```

### Classes implemented by Collection Interface
1. [ArrayList](https://www.geeksforgeeks.org/arraylist-in-java/): Non-synchronised
2. [LinkedList](https://www.geeksforgeeks.org/linked-list-in-java/)
3. [Vector](https://www.geeksforgeeks.org/java-util-vector-class-java/): Synchronised
4. [Stack](https://www.geeksforgeeks.org/stack-class-in-java/): LIFO
5. [Queue](https://www.geeksforgeeks.org/queue-interface-java/): FIFO, It also implemets LinkedList, for safe-threaded implementation we use PriorityBlockingQueue.
    1. [PriorityQueue](https://www.geeksforgeeks.org/priority-queue-class-in-java-2/): Not Thread Safe
    2. [AbstractQueue](https://www.geeksforgeeks.org/abstractqueue-in-java-with-examples/)
    3. [BlockingQueue](https://www.geeksforgeeks.org/blockingqueue-interface-in-java/): Thread-safe
        1. [ArrayBlockingQueue](https://www.geeksforgeeks.org/arrayblockingqueue-class-in-java/): Bounded
        2. [LinkedBlockingQueue](https://www.geeksforgeeks.org/linkedblockingqueue-class-in-java/): Bounded if its size is initialised
        3. [PriorityBlockingQueue](https://www.geeksforgeeks.org/priorityblockingqueue-class-in-java/)
        4. [DelayQueue](https://www.geeksforgeeks.org/delayqueue-class-in-java-with-example/): DelayQueue is a specialized Priority Queue that orders elements based on their delay time. It means that only those elements can be taken from the queue whose time has expired. If no delay has expired, then there is no head and poll will return null. DelayQueue accepts only those elements that belong to a class of type Delayed.
    4. [Deque](https://www.geeksforgeeks.org/deque-interface-java-example/): implemnted using ArrayDeque
    5. [ArrayDeque](https://www.geeksforgeeks.org/arraydeque-in-java/): Prefered to use instead of stack in single threaded environment.
    6. [ConcurrentLinkedQueue](https://www.geeksforgeeks.org/concurrentlinkedqueue-in-java-with-examples/)
6. [Set](https://www.geeksforgeeks.org/set-in-java/): Unordered collection of objects in which duplicates values can't be stored
    1. [HashSet](https://www.geeksforgeeks.org/hashset-in-java/): Ordered the objects based on the hashCode of the objects, non synchronised
    2. [LinkedHashSet](https://www.geeksforgeeks.org/linkedhashset-in-java-with-examples/): It is implemented using DoublyLinkedList while maintaining the order
    3. [EnumSet](https://www.geeksforgeeks.org/enumset-class-java/): not synchronised
    4. [AbstractSet](https://www.geeksforgeeks.org/abstractset-class-in-java-with-examples/)
7. [SortedSet](https://www.geeksforgeeks.org/sortedset-java-examples/): It extends set, having extra methods that maintain the order of the objects
    1. [TreeSet](https://www.geeksforgeeks.org/treeset-in-java-with-examples/): Non synchronised, TreeSet serves as an excellent choice for storing large amounts of sorted information which are supposed to be accessed quickly because of its faster access and retrieval time
    2. [NavigableSet](https://www.geeksforgeeks.org/navigableset-java-examples/): It is interface
    3. [ConcurentSkipListSet](https://www.geeksforgeeks.org/concurrentskiplistset-in-java-with-examples/): Synchronised, similar to TreeSet with an added feature of being concurrent
8. [Map](https://www.geeksforgeeks.org/map-interface-java-examples/): key-value pair mapping, It can't have duplicate keys but can have duplicate values
    1. [HashMap](https://www.geeksforgeeks.org/java-util-hashmap-in-java-with-examples/): NonSynchronised
    2. [SortedMap](https://www.geeksforgeeks.org/sortedmap-java-examples/): It is an interface
    3. [NavigableMap](https://www.geeksforgeeks.org/navigablemap-interface-in-java-with-example/)
    4. [TreeMap](https://www.geeksforgeeks.org/treemap-in-java/): Not Synchronised
    5. [EnumMap](https://www.geeksforgeeks.org/enummap-class-java-example/)
    6. [IdentityHashMap](https://www.geeksforgeeks.org/identityhashmap-class-java/):While this class implements the Map interface, it intentionally violates Map’s general contract, which mandates the use of the equals() method when comparing objects. This class is used when the user requires the objects to be compared via reference. It follows reference equality, instead of using the equals() method it uses the == operator. It is not synchronized and must be synchronized externally.
    7. [LinkedHashMap](https://www.geeksforgeeks.org/linkedhashmap-class-java-examples/): not synchronized
    8. [HashTable](https://www.geeksforgeeks.org/hashtable-in-java/): It is similar to HashMap, but is synchronised.
    9. [ConcurretMap](https://www.geeksforgeeks.org/concurrentmap-interface-java/)
    10. [ConcurrentHashMap](https://www.geeksforgeeks.org/concurrenthashmap-in-java/)
    11. [WeakHashMap](https://www.geeksforgeeks.org/java-util-weakhashmap-class-java/):  An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. More precisely, the presence of a mapping for a given key will not prevent the key from being discarded by the garbage collector, that is, made finalizable, finalized, and then reclaimed. It is not synchronised.

### AbstractList and Abstract in Java
The AbstractList class in Java is a part of the Java Collection Framework and implements the Collection interface and the AbstractCollection class. This class provides a skeletal implementation of the List interface to minimize the effort required to implement this interface backed by a Random Access data store (such as an array). For sequential access data (such as a linked list), AbstractSequentialList should be used in preference to this class.
To implement an unmodifiable list, for which one needs to only extend this AbstractList Class and implement the get(int) and the size() methods. To implement a modifiable list, for which one additionally override the set(int index, E element) method (which otherwise throws an UnsupportedOperationException). If the list is variable-size, for which one should override the add(int, E) and remove(int) methods.
```java=
// Java code to illustrate 
// methods of AbstractCollection 
 
import java.util.*; 
 
public class AbstractListDemo { 
    public static void main(String args[]) 
    { 
 
        // Creating an empty AbstractList 
        AbstractList<String> 
            list = new LinkedList<String>(); 
 
        // Using add() method to add elements in the list 
        list.add("Geeks"); 
        list.add("for"); 
        list.add("Geeks"); 
        list.add("10"); 
        list.add("20"); 
 
        // Output the list 
        System.out.println("AbstractList: " + list); 
 
        // Remove the head using remove() 
        list.remove(3); 
 
        // Print the final list 
        System.out.println("Final AbstractList: " + list); 
 
        // getting the index of last occurence 
        // using lastIndexOf() method 
        int lastindex = list.lastIndexOf("A"); 
 
        // printing the Index 
        System.out.println("Last index of A : "
                        + lastindex); 
    } 
}
```
For Methods in AbstractList and AbstractCollection refer [this](https://www.geeksforgeeks.org/abstractlist-in-java-with-examples/)

For Methods in AbstractSequentialList refer [this](https://www.geeksforgeeks.org/abstractsequentiallist-in-java-with-examples/)

---

## Wrapper Class
![](https://i.imgur.com/sKmrRg2.png)

<div style="text-align: justify">
<br><br><br><br><br><br>
</div>