Introduction of Java

Java is a high-level, class-based, object-oriented programming language that is designed to have as few implementation dependencies as possible. It is intended to let application developers "write once, run anywhere" (WORA), meaning that compiled Java code can run on all platforms that support Java without the need for recompilation.

History

Java was originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++, but it has fewer low-level facilities than either of them. Over time, it has become one of the most popular programming languages, particularly for client-server web applications.

Uses

Java is used in a wide variety of computing platforms from embedded devices and mobile phones to enterprise servers and supercomputers. Some of the primary uses of Java include:

Installation

To get started with Java, you need to install the Java Development Kit (JDK). Follow these steps:

Windows

  1. Download the JDK from the official Oracle website or OpenJDK.
  2. Run the installer and follow the instructions.
  3. Set up the JAVA_HOME environment variable to point to the JDK installation directory.
  4. Add the JDK's bin directory to the PATH environment variable.

Mac

  1. Download the JDK from the official Oracle website or OpenJDK.
  2. Run the installer and follow the instructions.
  3. Set up the JAVA_HOME environment variable by adding the following line to your .bash_profile or .zshrc file:
  4. export JAVA_HOME=$(/usr/libexec/java_home)

Linux

  1. Install OpenJDK using the package manager. For example, on Ubuntu:
  2. sudo apt update
    sudo apt install openjdk-11-jdk
  3. Set up the JAVA_HOME environment variable in your .bashrc or .bash_profile file:
  4. export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
  5. Add the JDK's bin directory to the PATH environment variable:
  6. export PATH=$JAVA_HOME/bin:$PATH

Java Basics

Java programs are written in .java files and compiled into bytecode by the Java compiler. The bytecode can be run on any system that has the Java Virtual Machine (JVM) installed.

Hello World Program

// Example of a simple Java program
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
            

To compile and run the program, use the following commands:

javac HelloWorld.java
java HelloWorld
            

Object-Oriented Programming

Java is fundamentally object-oriented. It uses classes and objects to represent real-world entities and processes:

Classes and Objects

// Example of a class and an object
public class Dog {
    String name;
    int age;

    // Constructor
    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Method
    public void bark() {
        System.out.println(name + " says: Woof!");
    }

    public static void main(String[] args) {
        Dog myDog = new Dog("Buddy", 3);
        myDog.bark();
    }
}
            

Inheritance

// Example of inheritance
public class Animal {
    public void eat() {
        System.out.println("This animal eats food.");
    }
}

public class Dog extends Animal {
    public void bark() {
        System.out.println("The dog barks.");
    }

    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.eat();
        myDog.bark();
    }
}
            

Polymorphism

// Example of polymorphism
public class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

public class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog();

        myAnimal.sound();
        myDog.sound();
    }
}
            

Data Structures

Java provides a variety of data structures to handle data efficiently:

Arrays

// Example of arrays
public class Main {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        for (int number : numbers) {
            System.out.println(number);
        }
    }
}
            

ArrayList

// Example of ArrayList
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        for (String name : names) {
            System.out.println(name);
        }
    }
}
            

HashMap

// Example of HashMap
import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        HashMap ages = new HashMap<>();
        ages.put("Alice", 30);
        ages.put("Bob", 25);
        ages.put("Charlie", 35);

        for (String name : ages.keySet()) {
            System.out.println(name + " is " + ages.get(name) + " years old.");
        }
    }
}
            

Exception Handling

Exceptions are used to handle errors and other exceptional events in Java:

Try-Catch

// Example of try-catch
public class Main {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[5]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("An error occurred: " + e.getMessage());
        }
    }
}
            

Finally

// Example of finally
public class Main {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[5]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("An error occurred: " + e.getMessage());
        } finally {
            System.out.println("This block is always executed.");
        }
    }
}
            

Multithreading

Multithreading in Java allows concurrent execution of two or more threads:

Extending Thread Class

// Example of multithreading by extending Thread class
public class Main extends Thread {
    public void run() {
        System.out.println("This code is running in a thread");
    }

    public static void main(String[] args) {
        Main thread = new Main();
        thread.start();
    }
}
            

Implementing Runnable Interface

// Example of multithreading by implementing Runnable interface
public class Main implements Runnable {
    public void run() {
        System.out.println("This code is running in a thread");
    }

    public static void main(String[] args) {
        Main obj = new Main();
        Thread thread = new Thread(obj);
        thread.start();
    }
}
            

Input/Output

Java provides various classes to perform input and output operations:

Reading from a File

// Example of reading from a file
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
            

Writing to a File

// Example of writing to a file
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt"))) {
            bw.write("Hello, World!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
            

Advanced Topics

Java provides a rich set of advanced features for complex application development:

Generics

// Example of generics
public class Main {
    public static  void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] strArray = {"A", "B", "C"};

        printArray(intArray);
        printArray(strArray);
    }
}
            

Lambda Expressions

// Example of lambda expressions
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        names.forEach((name) -> {
            System.out.println(name);
        });
    }
}
            

Streams API

// Example of Streams API
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        List evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());
        System.out.println(evenNumbers);
    }
}
            

Advanced Topics

Java Collections Framework

The Java Collections Framework provides a set of interfaces and classes to represent and manipulate collections of objects:

// Example of Java Collections Framework
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // List example
        List names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        // Map example
        Map ages = new HashMap<>();
        ages.put("Alice", 30);
        ages.put("Bob", 25);
        ages.put("Charlie", 35);
    }
}
    

Concurrency Utilities

Java provides classes and interfaces in the java.util.concurrent package to support concurrent programming:

// Example of concurrency utilities
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            executor.execute(worker);
        }
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }
}

class WorkerThread implements Runnable {
    private String message;

    public WorkerThread(String s) {
        this.message = s;
    }

    public void run() {
        System.out.println(Thread.currentThread().getName() + " (Start) message = " + message);
        processMessage(); // Call processMessage method that sleeps the thread for 2 seconds
        System.out.println(Thread.currentThread().getName() + " (End)"); // prints thread name
    }

    private void processMessage() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
    

Java Database Connectivity (JDBC)

JDBC is a Java API for executing SQL statements and managing relational databases:

// Example of JDBC
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Main {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "root", "password");
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");
            while (rs.next()) {
                System.out.println(rs.getInt(1) + "  " + rs.getString(2) + "  " + rs.getString(3));
            }
            con.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
    

Serialization and Deserialization

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it over a network, and deserialization is the process of converting those bytes back into an object.

Example:

// Serialization example
import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            // Serialization
            FileOutputStream fileOut = new FileOutputStream("employee.ser");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            Employee employee = new Employee("John", "Doe", 30);
            out.writeObject(employee);
            out.close();
            fileOut.close();

            // Deserialization
            FileInputStream fileIn = new FileInputStream("employee.ser");
            ObjectInputStream in = new ObjectInputStream(fileIn);
            Employee restoredEmployee = (Employee) in.readObject();
            in.close();
            fileIn.close();
            System.out.println("Deserialized Employee: " + restoredEmployee);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class Employee implements Serializable {
    private String firstName;
    private String lastName;
    private int age;

    public Employee(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", age=" + age +
                '}';
    }
}
    

Advanced Topics

Java Collections Framework

The Java Collections Framework provides a set of interfaces and classes to represent and manipulate collections of objects. It includes several data structures such as lists, sets, maps, and queues.

Here's an example demonstrating the usage of some collection classes:

// Example of Java Collections Framework
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        // List example
        List names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        System.out.println("Names:");
        for (String name : names) {
            System.out.println(name);
        }

        // Map example
        Map ages = new HashMap<>();
        ages.put("Alice", 30);
        ages.put("Bob", 25);
        ages.put("Charlie", 35);

        System.out.println("\nAges:");
        for (Map.Entry entry : ages.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}
        

Concurrency Utilities

Concurrency utilities in Java provide classes and interfaces to support concurrent programming, allowing multiple threads to execute concurrently.

Here's an example demonstrating the use of ExecutorService for managing a pool of threads:

// Example of concurrency utilities
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread("" + i);
            executor.execute(worker);
        }
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }
}

class WorkerThread implements Runnable {
    private String message;

    public WorkerThread(String s) {
        this.message = s;
    }

    public void run() {
        System.out.println(Thread.currentThread().getName() + " (Start) message = " + message);
        processMessage();
        System.out.println(Thread.currentThread().getName() + " (End)");
    }

    private void processMessage() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
        

In this example, a pool of five threads is created using ExecutorService. Each thread executes a task represented by the WorkerThread class.

Java Database Connectivity (JDBC)

JDBC is an API for connecting and executing SQL queries against a database. It provides a standard interface for accessing relational databases from Java programs.

Here's an example demonstrating JDBC to connect to a MySQL database:

// Example of JDBC
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Main {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "root", "password");
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM mytable");
            while (rs.next()) {
                System.out.println(rs.getInt(1) + "  " + rs.getString(2) + "  " + rs.getString(3));
            }
            con.close();
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
        

In this example, we connect to a MySQL database, execute a SELECT query, and print the results.

Generics

Generics in Java allow you to create classes, interfaces, and methods that operate with types as parameters. They provide compile-time type safety and allow you to write generic algorithms that work with different types.

Here's an example demonstrating the usage of generics:

// Example of generics
public class Main {
    public static  void printArray(T[] array) {
        for (T element : array) {
            System.out.println(element);
        }
    }

    public static void main(String[] args) {
        Integer[] intArray = {1, 2, 3, 4, 5};
        String[] strArray = {"A", "B", "C"};

        System.out.println("Integer Array:");
        printArray(intArray);

        System.out.println("\nString Array:");
        printArray(strArray);
    }
}
        

In this example, the printArray method is generic, allowing it to print arrays of any type.

Lambda Expressions

Lambda expressions introduce functional programming features to Java. They allow you to treat functionality as a method argument, or to create concise code blocks.

Here's an example demonstrating the usage of lambda expressions:

// Example of lambda expressions
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");

        // Using lambda expression to print each name
        names.forEach((name) -> {
            System.out.println(name);
        });
    }
}
        

In this example, the forEach method of ArrayList is used with a lambda expression to print each element of the list.

Streams API

The Streams API introduced in Java 8 provides a mechanism for processing collections of objects in a functional style. It allows for concise and expressive code for common operations like filtering, mapping, and reducing.

Here's an example demonstrating the usage of the Streams API:

// Example of Streams API
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

        // Filter even numbers and collect them into a new list
        List evenNumbers = numbers.stream()
                                           .filter(n -> n % 2 == 0)
                                           .collect(Collectors.toList());

        System.out.println("Even Numbers: " + evenNumbers);
    }
}