Thursday, November 16, 2023

why java ?


Java is a popular and widely used programming language for several reasons. Here are some of the key factors that make Java a compelling choice for many developers and organizations


1Platform Independence: Java is known for its "write once, run anywhere" capability. It accomplishes this through the use of the Java Virtual Machine (JVM), which allows Java applications to run on any platform that has a compatible JVM. This means you can develop an application on one platform and run it on various other platforms like macOS, ubuntu, Linux without modification.


2. Strongly Typed Language: Java is a statically typed language, which means that it requires variable types to be declared before use. This can help catch many errors at compile time, making it easier to write reliable code.


3. Object-Oriented: Java is an object-oriented programming language, which promotes the use of classes and objects. This approach makes it easier to model real-world problems and develop maintainable and modular code.


4. Rich Standard Library: Java provides a comprehensive standard library with a wide range of classes and methods for common programming tasks. This library covers everything from data structures to network communication, making it easier to develop applications without reinventing the wheel.


5. Security: Java has built-in security features to protect against various security threats, such as unauthorized access and malicious code execution. The JVM includes a security manager and bytecode verification to ensure a secure execution environment.


6. Memory Management: Java uses automatic memory management through a process called garbage collection. This relieves developers from the need to manage memory manually, reducing the risk of memory-related bugs like buffer overflows and memory leaks.


7. Community and Ecosystem: Java has a large and active developer community, which means you can find a wealth of resources, libraries, and frameworks for almost any type of project. It's used in various domains, from web development (Java EE, Spring) to Android app development (Java for Android).


8. Scalability: Java is known for its ability to build large-scale, high-performance applications. It's commonly used in enterprise software, web applications, and other systems that require scalability and reliability.


9. Backward Compatibility: Java places a strong emphasis on maintaining backward compatibility. This means that code written in older versions of Java can often run on newer Java runtimes without modification.


10. Robustness and Reliability: Java has features that contribute to the robustness and reliability of applications, such as exception handling and strong typing, which help prevent crashes and errors.


11. Multithreading and Concurrency: Java provides built-in support for multithreading and concurrency, making it well-suited for developing applications that can efficiently utilize modern multi-core processors.


While Java has many advantages, it may not be the best choice for every project. The choice of programming language depends on the specific requirements of your project and your team's expertise. There are many other programming languages available, each with its own strengths and weaknesses.


JVM ARCHITECTURE

The Java Virtual Machine (JVM) is a crucial component of the Java platform, responsible for executing Java applications. It's designed to be platform-independent, allowing Java code to run on various operating systems. The JVM architecture consists of several components:


1. Class Loader:

- Responsible for loading classes into memory.

- Classes are typically loaded from class files or other sources like networklocations.

- Class loading is essential for the dynamic nature of Java applications.


2. Class Memory Area:


- Divided into several components, including Method Area, Heap, and others.

- Method Area stores class-level structures such as class definitions, methods, and static fields.

- Heap is where objects are allocated and deallocated during runtime.




3. Execution Engine:

- Executes bytecode instructions.

- Consists of the Just-In-Time (JIT) compiler, which compiles bytecode into 
   native machine code for better performance.

- The JVM interpreter can also directly execute bytecode.


4. Java Native Interface (JNI):

- Enables interaction between Java code and native code (written in languages like    C and  C++).

- Useful for integrating platform-specific functionality and libraries.


5. Native Method Interface (NMI):

- Similar to JNI but used for calling native methods from Java classes.


6. Java Native Interface (JNI):

- Enables interaction between Java code and native code (written in languages like   C and C++).

- Useful for integrating platform-specific functionality and libraries.


7. Native Method Interface (NMI):

- Similar to JNI but used for calling native methods from Java classes.


8. Native Method Libraries:

- Contains the native methods provided by the JVM and the operating system.

- These methods are used for low-level tasks, such as memory management and    system calls.


9. Stack:

- Stores the call stack, which holds method call frames.

- Each frame contains local variables, operand stack, and the program counter.

- Used for method invocation and maintaining control flow.


10. Program Counter (PC) Register:

- Keeps track of the current execution point within a method.

- Helps in the sequential execution of bytecode instructions.


11. Execution Control:

- Responsible for managing thread synchronization, garbage collection, and exception handling.

- Ensures the proper execution of Java code and manages resources efficiently.


12. Security Manager:

- Enforces security policies to protect the system from potentially harmful code.

- Defines what operations Java code is allowed to perform, such as file access and network communication.



13. Thread Management:

- Manages multiple threads in a Java application.

- Ensures thread safety and coordination among threads.




    Types of Applications Where Java Used

    • There are various types of applications in software development, each designed to serve different purposes and address specific needs. Here are some common types of applications:

      Desktop Applications:
      These are applications designed to run on a user's local computer or device.
      They provide platform-specific user interfaces and often have better performance.
      Examples include word processors, graphic design software, and video games.


      Web Applications:
      These applications run on remote web servers and are accessed through web browsers.
      Users can access them from anywhere with an internet connection.
      Examples include email services, social media platforms, and online shopping websites.

      Mobile Applications:
      Designed for smartphones and tablets, these apps run on mobile operating systems like Android and iOS.
      They can be downloaded and installed from app stores.
      Examples include mobile games, social networking apps, and navigation apps.

  1.    Embedded Applications:
       Software that is integrated into hardware devices and systems.
  2.    Examples include firmware in smartphones, car navigation systems
  3.   and IoT.

  4. History of Java
1991: Java is created by James Gosling, Mike Sheridan, and Patrick Naughton at Sun Microsystems. It was originally known as "Oak."


1995: The official release of Java 1.0 by Sun Microsystems. This marked the beginning of the "Write Once, Run Anywhere" (WORA) concept.


1996: Java Applets became popular for web development. The "applet" allowed Java programs to run within web browsers.


1997: Java 1.1 introduced significant improvements and the event model, which made it easier to build GUI applications.


2000: Java 2 (J2SE) was released, bringing a new platform, improved performance, and the Swing GUI toolkit.


2004: Java 5 (also known as J2SE 5.0 or Java 1.5) was a major release with features like Generics, Metadata Annotations, and enhanced "for-each" loop.


2006: Sun Microsystems open-sourced Java under the GNU General Public License (GPL), known as OpenJDK.


2011: Java 7 was released with features like the try-with-resources statement and the diamond operator for simplified generics.


2014: Java 8 introduced lambdas, the Stream API for functional programming, and the java.time package for modern date and time handling.


2017: Java 9 brought modularization with the introduction of the module system and the "jshell" for a Read-Eval-Print Loop (REPL).


2018: Java had a new release cadence, with Oracle releasing Java every six months. Java 10, Java 11, and later versions followed, offering incremental improvements.


2020: The release of Java 15 featured sealed classes and records, adding more language features and enhancements.


2021: Java 16 introduced pattern matching and improvements to garbage collection and performance.
2022: Java 17 was a Long-Term Support (LTS) release, offering stability and ongoing support
.

  What is class?
   class is the blueprint of an object having some states and behaviors


  What is an object?
  object is anything present in the real world and having some physical existence.
   example:-car, bike, atm, mobile, etc
  

  What is a variable?
  variables are containers used to store some particular data into it.
  example:- godowns used to store different types of products.


  What is data type? and its types
  In a variable what kind of data we are storing is called as datatype.
  There are mainly two kinds of data types in Java we have
  1. Primitive data type
  2. Non primitive data type

    1. Primitive data type
         a.byte, short,int, long
         b.double, float  
         c.boolean
         d. char,String
    2.Non primitive data type
        class, objects are kind of non-primitive data types in java


       Byte- size is 8 bit=1-byte 
       char- 2 bytes
       short-2 bytes
       int -4 bytes
       long-8 bytes
       double-8 bytes
       float-4 bytes
       boolean-1 bit

Function:-

function is a block of code used to perform some specific task.
example:- here getString() is used to return some string value to perform task .

public String getString(String str){
   return str;
}


Method overloading:-
When class is having one or more same methods but differences in the of arguments or arguments order or datatypes of arguments. Then this type of methods are called as overloaded methods.
example:-
class Moblie{
  void createContact(int number1){
    System.out.println("number1");
}

void createContact(int number1, int number2){
System.out.println("number1 and number2");
}

public static void main(String[] args){

Moblile mobile=new Mobile();
mobile.createContact(9012341011);
mobile.createContact(9012341011,9536664783);
}

}

Method overriding:-
When a both super class and sub class having same methods then subclass method will override the superclass method and gives sub class method .This process in java is called as method overriding.



Rules for Java Method Overriding
The method must have the same name as in the parent class
The method must have the same parameter as in the parent class.
There must be an IS-A relationship (inheritance).

example:-

class Animal 
void makeSound() 
{ System.out.println("The animal makes a generic sound"); 
}
 class Dog extends Animal { 
@Override
 void makeSound() 
System.out.println("The dog barks"); 
}
 }

public class Main { 
public static void main(String[] args) {
Dog dog = new Dog(); 
dog.makeSound(); 

}
}

oops concept in java

 OOPS

Java is object oriented programming language means in java everthing is in the form of class and object.

java mainly depends on four pillars like

1. abstraction 

2.encapsulation 

3.inheritence

4.polymorphism

Abstraction

abstraction is process of hiding implementation and only showing functionality to the users is called abstraction .


The abstract keyword is a non-access modifier, used for classes and methods:

Abstract class: is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class).

Abstract method: can only be used in an abstract class, and it does not have a body. The body is provided by the subclass (inherited from).
 Realtime example:-atm ,sms chatbox etc
example :-without inheritence

abstract class Animal { 
public abstract void animalSound();
 public void sleep() {
 System.out.println("Zzz"); 
}
 }


example :-with inheritence

abstract class Animal {

public abstract void animalSound(); 
 public void sleep()
 System.out.println("Zzz");
 }
 } 

 class Elephant extends Animal {
 public void animalSound() { 
 System.out.println("The  Elephant  says: ooo ooo"); 
class Main {
 public static void main(String[] args) {
 Elephant   elephant  = new  Elephant (); 

 elephant.animalSound(); 
 elephant.sleep(); } 
}


Encapsulation

It is a process of binding variables and methods in single class .These variables are private   by default and cannot accessible out side the class.
It is 100% not secure.
Real time example mobile :- interaction between mobile and user.
Example

public class Person { 

private String name; 
private int age;

public Person(String name, int age) { 
this.name = name;
 this.age = age; 
}

public String getName() {
 return name; 

 public void setName(String name) {
 this.name = name; 

 public int getAge() { 
return age; 
}
 
 public void setAge(int age) { 
if (age >= 0) {
 this.age = age; 
 }
 }
 } 
public class Main { 
public static void main(String[] args) {
Person person = new Person("John", 30); 

System.out.println("Name: " + person.getName()); 
System.out.println("Age: " + person.getAge());

person.setName("Alice"); 
person.setAge(25); 

System.out.println("Updated Name: " + person.getName()); 
System.out.println("Updated Age: " + person.getAge()); 
}
 }

Inheritence
Inheritence is a process of aquiring properties from one class to another class using extend keyword.
The class which is providing properties is called super class or parent class.
The class which is aquiring properties from super class is called sub class or chield class.

Types of Inheritence
1.single level inheritence:- 1 super class and 1 sub calss
2.multilevel inheritence:- 1,2,3  - - ,n classes extended in one super and 1 sub class manner untill n class.
3.heirarchy inheritence:- 1 super class an d 2 sub class
4.hybrid inheritence:-combination any 2 type of inheritence.
5.multiple inheritence:- 2 super class an d 1 sub class which is not supported by java so thats they are using interface concept.



Example for inheritence

class Vehicle {
 protected String brand = "maruti";


public void honk() { 
 System.out.println("Tuut, tuut!"); 
}
 } 

class Car extends Vehicle {
private String modelName = "Maruti800";

 public static void main(String[] args) { 
 Car myCar = new Car(); 
 myCar.honk();
System.out.println(myCar.brand + " " + myCar.modelName); } 
}


Polymorphism
 If one object is behaving in different characters in different lifecycle of project is called as polymorphism.

It is achived using two diffrent ways

1.RunTime polymorphism
2.CompileTime polymorphism


RunTime polymorphism:-
Runtime polymorphism is allso called as dynamic polymorphism beacuse the overriden methods are called during run time .
In this process, an overridden method is called through the reference variable of a superclass.
  example:-Bank
class Bank{
float getRateOfInterest(){
return 0;
}  
class HDFC extends Bank{
float getRateOfInterest(){
return 8.4f;
}  
}  
class SBI extends Bank{  
float getRateOfInterest(){
return 7.3f;
}  
}  
class AXIS extends Bank{  
float getRateOfInterest(){
return 9.7f;
}  
}  

class TestPolymorphism{  

public static void main(String args[]){  
Bank b;  
b=new HDFC();  
System.out.println("HDFC Rate of Interest: "+b.getRateOfInterest());  

b=new SBI();  
System.out.println("SBI Rate of Interest: "+b.getRateOfInterest());  

b=new AXIS();  
System.out.println("AXIS Rate of Interest: "+b.getRateOfInterest());  
}  
}  




CompileTime polymorphism
The compiletime polymorphism is allso called as static binding because method binding will be done during compilation only.
There is no concept of inheritence .
In Java, compile-time polymorphism is mostly achieved by method overloading.

example:- simple calculator

public class Calculator {
public int add(int x, int y) {
return x + y;
}
public double add(double x, double y) {
return x+ y;
}
public static void main(String[] args) {
Calculator calculator = new Calculator();

int sum1 = calculator.add(5, 10);
System.out.println("sum of integers (integers): " + sum1);

double sum2 = calculator.add(2.5, 3.7);
System.out.println("Sum of  doble numbers(doubles): " + sum2);
}
}



Strings

 Strings

strings are sequence of characters  often used for representing text normally.  But in Java, string is an object that represents a sequence of characters.It is covered by " " in each side object.

example:- "kumar", "leela"

Strings Immutabality

Generally strings immutable in nature means when we want change the original string value directly  then it will not change instead it will return  original  value.

Once String object is created then  its data or state can't be changed but a new String object is created

example1:-

Class Immutable{

public  static void main(String[] args){

String str1="rahul";

//we are directly try to change the originalvalueusing conact//

str1.concat("dravid");

System.out.println(str1);

}

}

output:- rahul

example2:-

Class Immutable{

public  static void main(String[] args){

String str1="rahul";

//we are assigning a  object reference variable here and then concat//

str1=str1.concat("dravid");

System.out.println(str1);

}

}

output:-rahuldravid


Strings Mutable Versions

StringBuffer:-

Because of string high usabelity  oracle introduced one of the mutable version called

stringbuffer .

Intraduced in JDK 1.0 version

It is synchronized and threadsafe means two threads can call the method simultaneously.

Suitable for scenarios where multiple threads may access the same instance concurrently.

It is less efficient.

example
StringBuffer stringBuffer = new StringBuffer("Hello");
stringBuffer.append(" World");
String result = stringBuffer.toString();
System.out.println(result);

output:-HelloWorld

StringBuilder:-
Because less efficiency of StringBuffer oracle introduced StringBuilder in JDK version 5.0

It is  not synchronized and threadsafe means two threads cannot  call the method simultaneously.

Preferred when the class will only be accessed by a single thread.

It is more efficient.

example
StringBuilder stringBuilder = new StringBuilder("Hello");
stringBuilder.append(" World"); 
String result = stringBuilder.toString(); 
System.out.println(result);

output;- HelloWorld

Collections in java

 Collections

In Java, the term collections  refers to the Java Collections Framework. 

Collections which is a set of classes and interfaces in the java.util package that provide various implementations of common data structures. 

The Java Collections Framework simplifies the process of working with groups of objects, such as lists, sets, and maps.




List

List is an interface in java extends the collection interface used to ordered and index based collection of objects which may contains duplicate values.

We can store null values allso.

Types of List

1.ArrayList

2.LinkedList

3.Vector and Stack


ArrayList:-

The ArrayList class implements the List interface,means it provides all the methods specified by the List interface. 

This includes methods for adding, removing, accessing, and manipulating elements in a dynamic list.

It allows duplicates values to store and maintain a insertion order.

It is index based and random acess is allowed.

ArrayList manipulation is slow because the lot of shifting of index and values needs to be occur.It is  one  of the disadvantage of arraylist.




LinkedList:-

The LinkedList class implements the List interface,means it provides all the methods specified by the List interface. 

Unlike ArrayList, which is based on an array, LinkedList is based on a doubly-linked list data structure.

Each element in a LinkedList is represented as a node that contains a data element and references to the next and previous nodes in the sequence.
This structure allows for efficient insertion and deletion operations at both the beginning and end of the list.

It is allso allows duplicates values to store and maintains insertion order.

It has  node based datastrcture .

LinkedList manipulation is very fast because no shifting occurs.






Vector and Stack
Vector is a class in the Java Collections Framework that represents a dynamic array, capable of resizing itself to accommodate the number of elements it contains.
It implements the List interface, providing methods for adding, accessing, modifying, and removing elements.

Key Features:

Dynamic Resizing: Similar to ArrayList, Vector dynamically adjusts its size to handle the addition or removal of elements.

Synchronized: One distinctive feature is its synchronization, making it thread-safe. However, in modern Java development, synchronization is often handled differently for better performance.





Stack: LIFO Operations
Stack is a subclass of Vector that extends its capabilities to implement a last-in, first-out (LIFO) stack. 
This means that the last element added is the first one to be removed.

Key Features:

LIFO Structure: Elements are added and removed from the top of the stack.

Push and Pop Operations: It provides methods like push() for adding elements to the top and pop() for removing and returning the top element.





Set
set is an interface available in the java.util package .The set interface extends collection interface.
It is a unordered collection or list in which duplicates are not allowed.
It is widely  used in  creating mathematical set.





Types of Set
1.Hashset
2.LinkedHashSet
3.Treeset

Hashset:-
HashSet is a data structure in programming that stores a collection of unique elements where each element is unique, means it cannot contain duplicates. 
The elements in a HashSet are not stored in any particular order.

                              

Hashing Mechanism: HashSet uses a hashing mechanism to store elements. It computes a hash code for each element added to it and uses this code to determine the storage location for that element within the HashSet.
This hashing mechanism allows for fast retrieval, insertion, and deletion of elements.

Characteristics:
Addition and Retrieval: Adding an element to a HashSet checks if the element already exists by computing its hash code. If the hash code already exists in the set, it won't add a duplicate.

Performance: Offers constant-time performance for basic operations such as add, remove, contains, and size.

Unordered: Doesn’t maintain the order of elements in which they were added.
Common Usage:

Unique Element Storage: Ideal for scenarios where you need to store a collection of unique items without concern for their order.

Checking Uniqueness: Used to check whether an element is already present in the collection efficiently.


LinkedHashSet:-

A LinkedHashSet is similar to a HashSet but with an additional feature: it maintains the insertion order of elements.

Characteristics:
Uniqueness: Similar to HashSet, it contains only unique elements, meaning duplicates are not allowed.
Order Maintenance: Unlike HashSet, LinkedHashSet maintains the order in which elements are inserted. When you iterate through a LinkedHashSet, the elements are returned in the order they were added.

How it Works:
Hashing Mechanism: 
In addition to hashing, it maintains a doubly-linked list to preserve the insertion order.
Characteristics in Comparison to HashSet:
Ordered Elements: HashSet doesn’t maintain the order of elements, while LinkedHashSet does.
Performance: Offers similar performance to HashSet for basic operations with a slight overhead due to maintaining the insertion order.
Common Usage:
Preserving Order: Useful when you need a collection of unique elements and want to preserve the order in which they were added.
Iteration Order: When you need to iterate through elements in the same order they were inserted.



TreeSet
TreeSet is one of the most important implementations of the Set interface in Java that uses a Tree for storage. 
The ordering of the elements is maintained by a set using their natural ordering whether or not an explicit comparator is provided

characteristics:
Sorted Order: TreeSet stores elements in a sorted order defined by either natural ordering or a custom comparator.
Unique Elements: Similar to HashSet, it contains only unique elements.

How it Works:
Red-Black Tree: Internally, TreeSet uses a Red-Black tree data structure to maintain the elements in a sorted order.
Comparator or Natural Ordering: Elements are sorted according to a Comparator provided during TreeSet instantiation or by their natural ordering if they implement the Comparable interface.
Characteristics in Comparison to HashSet and LinkedHashSet:
Ordered Elements: Unlike HashSet and LinkedHashSet, TreeSet ensures that elements are stored and traversed in a sorted order.

Performance: TreeSet provides logarithmic time cost for basic operations like add, remove, and contains, which makes it slightly slower than HashSet and LinkedHashSet for these operations.

Common Usage:
Sorted Collection: Useful when you need a set with elements sorted in a specific order.
Custom Sorting: Allows defining custom sorting behavior using a Comparator.
Unique and Sorted Elements: Combines the features of uniqueness and sorting.

Example set:-

package collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.NavigableSet;
import java.util.TreeSet;

//no insertion order is maintained ,no duplicates
public class SetExample {

public static void main(String[] args) {
HashSet<String> hs=new HashSet<String>();
hs.add("java");
hs.add("sql");
hs.add("html");
hs.add("sql");
System.out.println(hs);
hs.remove("html");
System.out.println(hs);
// hs.removeAll(hs);
// System.out.println(hs);
hs.clear();
System.out.println(hs);

TreeSet<Integer> ts=new TreeSet<Integer>();
ts.add(1);
ts.add(1);
ts.add(3);
ts.add(2);
System.out.println(ts);
        NavigableSet<Integer> descendingSet = ts.descendingSet();
        System.out.println(descendingSet);
       ts.remove(3); 
       System.out.println(ts);
       ts.removeAll(ts);
       System.out.println(ts);
    }
}







Map
In Java, the Map interface represents a collection of key-value pairs where each key is unique. 
Some commonly used implementations of the Map interface in Java include HashMap, TreeMap, LinkedHashMap, and HashTable. 



HashMap
Stores key-value pairs in a hash table.
Does not maintain any order.
Allows null keys and values (not synchronized).
Performance: Generally offers O(1) time complexity for get(), put(), remove() operations (average case).
Frequently used for general-purpose mapping.

LinkedHashMap
Similar to HashMap but is synchronized (thread-safe).
Does not allow null keys or values.
Considered legacy:ConcurrentHashMap is preferred in concurrent scenarios.
Offers slightly slower performance than HashMap due to maintaining order.
Useful when you need predictable iteration order.

HashTable
Similar to HashMap but is synchronized (thread-safe).
Does not allow null keys or values.
Considered legacy: ConcurrentHashMap is preferred in concurrent scenarios.
Slower in comparison to HashMap due to synchronization.
Used in multi-threaded environments where thread safety is required.


TreeMap
Stores keys in a sorted tree structure (usually a Red-Black Tree).
Maintains the keys in a sorted order.
Does not allow null keys but permits null values (not synchronized).
Provides O(log n) time complexity for get(), put(), remove() operations.
Useful when keys need to be sorted.

Exceptions in java

 Exception Handling

What is Exception in Java?

Exception is process in which the flow of executing program terminates  during run time.

Exception is an abnormal condition.

so in order to handle this abnormal process  we are using exception handling mechanism in java.




Types of Handling Exceptions

we can handle exceptions using three methods
1.Try/Catch Block
2.Using Throws
3.Using Throw 


Try/Catch:-
The code which may throw exceptions are written in try block.
In Java Try block must be followed by either catch block or finally block.
To handle this exception we are using catch block.

example:-

public class TryCatch {

public static void main(String[] args) {
try
{
int data=60/0; 
//may throw exception
}
//handling the exception
catch(ArithmeticException e){
System.out.println(e);
}
System.out.println("rest of the code");
}
}

output:- 
java.lang.ArithmeticException: / by zero
rest of the code


Throws keyword:-
Java throws keyword is used in the method signature to declare an exception which might be thrown by the function while the execution of the code.

We can declare multiple exceptions using throws keyword that can be thrown by the method. For example, main() throws IOException, SQLException.

example:-

import java.io.IOException;

public class ThrowsExample {

public void readFile(String fileName) throws IOException {

if (fileName == null || fileName.isEmpty()) {
throw new IOException("Invalid file name");
}

}

public static void main(String[] args) {
ThrowsExample example = new ThrowsExample();
try {
example.readFile("nonexistentfile.txt");
} catch (IOException e) {
System.err.println("IOException caught: " + e.getMessage());
}
}
}




Throw keyword:-
The throw keyword is used inside function to throw an exceptions explicitly.


example:-

package exceptions;

class CustomException extends Exception {
public CustomException(String message) {
super(message);
}
}


public class ThrowExample {
public void checkAge(int age) throws CustomException {
if (age < 0 || age > 150) {
throw new CustomException("Invalid age provided");
else {
System.out.println("Age is: " + age);
}
}


public static void main(String[] args) {
ThrowExample example = new ThrowExample();
try {
example.checkAge(170); 
}
catch (CustomException e) {
System.err.println("CustomException caught: " + e.getMessage());
}
}
}


output:-
CustomException caught: Invalid age provided.


Types Exceptions
1.Checked Exceptions
2.Unchecked  Exceptions

Checked Exceptions:-
Checked exceptions are  also called  as compile-time exceptions because these exceptions are checked at compile-time by the compiler.

package exceptions;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;

public class ReadFileExample {
    public static void main(String[] args) {
        File file = new File("user.txt");
        
        try {
            FileReader fr = new FileReader(file);
            
        } catch (FileNotFoundException e) {
            System.out.println("File not found: " + e.getMessage());
           
        }
    }
}

Unchecked  Exceptions:-
The unchecked exceptions are also called as runtime  exceptions. 
The compiler will not check these exceptions during compile time. 
In simple words, if a program throws an unchecked exception and even if we didn’t handle or declare it, the program would not give a compilation error.


package exceptions;
public class UncheckedExceptionExample {
    public static void main(String[] args) {
        String text = null;

        try {
            int length = text.length(); 
            System.out.println("Length of text: " + length);
        } catch (NullPointerException e) {
            System.out.println("Error: The string is null");
            
        }
    }
}