Author: Pooja Kotwani

  • Arrays

    Arrays in Java

    Operators are the foundation of any programming language, enabling us to perform various computations, logic evaluations, and functions. Java offers several types of operators that are categorized based on the functions they perform.

    Array Initialization in C

    Initialization in C involves assigning initial values to variables. When an array is declared or memory is allocated for it, its elements initially contain garbage values. To give these elements meaningful values, we initialize the array. There are several methods for initializing an array in C.

    1. Array Initialization During Declaration :This method involves initializing the array at the time of its declaration. We use an initializer list, which is a set of values enclosed in curly braces { } and separated by commas, to assign values to the array.

    Examples:

    int[] numbers; // Declaring an integer array

    This declares an integer array numbers. However, it does not allocate memory yet.

    2. Creating an Array :Allocate memory using the new keyword:

    numbers = new int[5]; // Creates an array of 5 integers

    This initializes the array to hold 5 integers, with default values of 0.

    3. Accessing Array Elements :You can access and modify array elements using their index (starting from 0):

    numbers[0] = 10; // Setting the first element to 10
    int firstElement = numbers[0]; // Accessing the first element

    4. Changing Array Elements :To update an element, assign a new value:

    numbers[0] = 20; // Changes the first element to 20

    5. Array Length :You can get the length of an array using its length property:

    int length = numbers.length; // Returns 5 for this array

    6. Array Initialization :You can declare and initialize arrays in different ways:

    int[] numbers = new int[5]; // Declaration + memory allocation
    int[] otherNumbers = {1, 2, 3, 4, 5}; // Array literal initialization

    7. Iterating Through Arrays :You can loop through arrays using a for loop or for-each loop:

    for (int i = 0; i < numbers.length; i++) {
        System.out.println(numbers[i]);
    }
    
    for (int number : numbers) {
        System.out.println(number); // For-each loop
    }

    8. Multidimensional Arrays :Java supports multidimensional arrays, like 2D arrays (matrix):

    int[][] matrix = new int[3][3]; // 2D array
    matrix[0][0] = 1;

    Example:

    int[][] multiDimArray = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    }; // A 3x3 matrix

    9. Array of Objects ;Arrays can also hold objects of a class:

    Student[] students = new Student[3]; // Array of Student objects
    students[0] = new Student("John", 1);

    Output:

    num1 = 20
    num2 = 10
    The product = 200

    10. Passing Arrays to Methods :You can pass arrays to methods:

    public class MultiplicationExample {
        public static void main(String[] args) {
            int num1 = 20, num2 = 10;
            int product = num1 * num2;
            System.out.println("The product = " + product);
        }
    }

    Calling the method:

    printArray(numbers);

    11. Returning Arrays from Methods :A method can return an array:

    public static int[] getArray() {
        return new int[] {1, 2, 3};
    }

    12. Cloning Arrays :To clone an array (create a shallow copy):

    int[] cloneArray = numbers.clone();

    For multidimensional arrays, the cloning creates a shallow copy, meaning only the references are copied, not the actual elements.

    13. Handling Array Exceptions :If you try to access an element outside the array size, Java throws an ArrayIndexOutOfBoundsException:

    System.out.println(numbers[5]); // Throws an exception if the array has fewer elements

    Arrays class in Java

    The Arrays class in Java, part of the java.util package, provides several static methods to help developers perform operations on arrays in a more optimized and efficient manner. Here are some of the most common methods:

    Key Methods in Arrays Class:

    1. asList(): Converts an array to a fixed-size list.

    Integer[] arr = {1, 2, 3};
    List<Integer> list = Arrays.asList(arr);

    2. binarySearch(): Searches for a specific element using the binary search algorithm.

    int[] arr = {1, 2, 3, 4, 5};
    int index = Arrays.binarySearch(arr, 3); // Returns index of 3

    3. compare(): Compares two arrays lexicographically.

    int result = Arrays.compare(arr1, arr2);

    4. copyOf(): Copies the array to a new array of a specified length.

    int[] newArr = Arrays.copyOf(arr, 10); // Extends or truncates

    5. copyOfRange(): Copies a range of an array.

    int[] newArr = Arrays.copyOfRange(arr, 1, 3);

    6. deepEquals():Compares two arrays deeply for nested arrays.

    boolean isEqual = Arrays.deepEquals(arr1, arr2);

    7. deepHashCode(): Returns the hash code based on the “deep contents” of an array.

    int hashCode = Arrays.deepHashCode(arr);

    8. deepToString(): Converts an array to a string representation, handling nested arrays.

    String arrStr = Arrays.deepToString(arr);

    9. equals(): Compares two arrays for equality.

    boolean isEqual = Arrays.equals(arr1, arr2);

    10. fill(): Fills an array with a specified value.

    Arrays.fill(arr, 100); // Fills all elements with 100

    11. hashCode(): Returns the hash code for an array.

    int hash = Arrays.hashCode(arr);

    12. mismatch(): Finds the first index where two arrays differ.

    int mismatchIndex = Arrays.mismatch(arr1, arr2);

    13. parallelSort(): Sorts the array in parallel for faster sorting.

    Arrays.parallelSort(arr);

    14. sort(): Sorts an array in ascending order.

    Arrays.sort(arr);

    15. spliterator(): Returns a Spliterator covering the array.

    Spliterator<Integer> spliterator = Arrays.spliterator(arr);

    16. stream(): Converts an array into a sequential stream.

    Stream<int[]> stream = Arrays.stream(arr);

    17. toString(): Converts an array to a string representation.

    String arrStr = Arrays.toString(arr);
    Multidimensional Arrays

    Multidimensional arrays, simply put, are arrays made up of arrays. Data within these arrays are stored in a tabular structure, typically in row-major order.

    Syntax:

    data_type[1st_dimension][2nd_dimension][]...[Nth_dimension] array_name = new data_type[size1][size2]...[sizeN];

    Where:

    • data_type: The type of data stored in the array (e.g., intchar, etc.).
    • dimension: Specifies the dimension of the array (e.g., 2D, 3D).
    • array_name: The name assigned to the array.
    • size1, size2,…, sizeN: Dimensions defining the size of the array.

    Examples:

    Two-dimensional array:

    int[][] twoD_arr = new int[10][20];

    The total number of elements a multidimensional array can store is the product of its dimensions. For example, an array int[][] x = new int[10][20] can hold a total of 10×20=20010 \times 20 = 20010×20=200 elements. Similarly, int[][][] x = new int[5][10][20] can store 5×10×20=10005 \times 10 \times 20 = 10005×10×20=1000 elements.

    Applications of Multidimensional Arrays
    • Tabular Data: These arrays are often used to store tabular data, such as a student’s roll number and marks. A more complex use is to store images in 3D arrays.
    • Dynamic Programming: Many dynamic programming problems leverage multidimensional arrays to store intermediate states.
    • Algorithms: Common applications include matrix multiplication, adjacency matrices in graphs, and grid-based search problems.
    Two-Dimensional Array (2D Array)

    A 2D array is the most basic form of a multidimensional array and can be viewed as an array of one-dimensional arrays.

    Declaration (Indirect Method):

    Example:

    int[][] arr = new int[10][20];

    Initialization:

    arr[0][0] = 1;

    Examples:

    public class TwoDArrayExample {
        public static void main(String[] args) {
            int[][] arr = new int[10][20];
            arr[0][0] = 1;
    
            System.out.println("arr[0][0] = " + arr[0][0]);
        }
    }

    Output:

    arr[0][0] = 1

    Example: 2D array with default values in a 4×4 matrix:

    public class TwoDArray {
        public static void main(String[] args) {
            int rows = 4;
            int columns = 4;
            int[][] array = new int[rows][columns];
    
            int value = 1;
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < columns; j++) {
                    array[i][j] = value++;
                }
            }
    
            System.out.println("The 2D array is:");
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < columns; j++) {
                    System.out.print(array[i][j] + " ");
                }
                System.out.println();
            }
        }
    }

    Output:

    The 2D array is:
    1 2 3 4
    5 6 7 8
    9 10 11 12
    13 14 15 16

    Declaration (Direct Method):

    int[][] arr = {{1, 2}, {3, 4}};

    Output:

    After adding: 8

    Example:

    public class DirectTwoDArray {
        public static void main(String[] args) {
            int[][] arr = { { 1, 2 }, { 3, 4 } };
    
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 2; j++) {
                    System.out.println("arr[" + i + "][" + j + "] = " + arr[i][j]);
                }
            }
        }
    }

    Output:

    arr[0][0] = 1
    arr[0][1] = 2
    arr[1][0] = 3
    arr[1][1] = 4

    Accessing Elements:

    To access elements in a 2D array, the syntax is:

    array[row_index][column_index];

    For example:

    arr[0][0] = 1;
    Three-Dimensional Array (3D Array)

    A 3D array can be seen as an array of 2D arrays.

    Declaration (Indirect Method):

    int[][][] arr = new int[10][20][30];

    Initialization:

    arr[0][0][0] = 1;

    Different Ways To Declare And Initialize 2-D Array

    A multi-dimensional array is an array with more than one dimension, commonly used as 2D or 3D arrays. Essentially, a multi-dimensional array is an array of arrays. A typical example of a 2D array is a chessboard, which consists of a grid of 64 square boxes arranged in 8 rows and 8 columns. Similarly, a 2D array can be visualized as a grid, where each element is identified by a row and column number. Accessing elements in a 2D array is similar to working with an Excel sheet, using row and column indices.

    Two-dimensional arrays (2D arrays) are useful for implementing structures like games (Tic-Tac-Toe, Chess) or storing image pixels.

    Declaring a 2D Array in Java

    A 2D array can be declared in two common ways:

    data_type array_name[][];   // OR
    data_type[][] array_name;
    • data_type: This defines the type of elements the array will store, such as intStringboolean, etc. Java, being statically typed, requires the data type to be declared.
    • array_name: This is the name you assign to the array.

    Example: Declaring Different Types of 2D Arrays

    data_type[][] array_Name = new data_type[no_of_rows][no_of_columns];

    Here, no_of_rows and no_of_columns define the number of rows and columns in the array. The total number of elements in a 2D array is calculated by multiplying the number of rows by the number of columns. For instance:

    int[][] myArray = new int[4][5];  // A 2D array with 4 rows and 5 columns

    By default, Java assigns default values to the array elements depending on the data type. Below are various approaches to initialize a 2D array.

    Different Approaches for Initializing 2D Arrays

    Approach 1: Declaration and Initialization

    In this approach, we declare the array and immediately initialize it.

    int[][][] arr = { {{1, 2}, {3, 4}}, {{5, 6}, {7, 8}} };

    Example:

    public class Example {
        public static void main(String[] args) {
            int[][] integer2DArray = new int[3][4];
            System.out.println("Default value of int array element: " + integer2DArray[0][0]);  // Outputs 0
    
            String[][] string2DArray = new String[2][3];
            System.out.println("Default value of String array element: " + string2DArray[0][0]);  // Outputs null
    
            boolean[][] boolean2DArray = new boolean[2][2];
            System.out.println("Default value of boolean array element: " + boolean2DArray[0][0]);  // Outputs false
        }
    }

    Approach 2: Initialization with Values

    Here, we initialize the array elements directly without specifying the number of rows and columns. Java automatically deduces the size.

    Example:

    public class Example {
        public static void main(String[] args) {
            String[][] courses = {
                { "Math", "Science", "History" },       // Row 1
                { "Biology", "Physics", "Chemistry" },  // Row 2
                { "English", "Art" }                    // Row 3
            };
    
            System.out.println("Course in first row: " + courses[0][0]);  // Math
            System.out.println("Course in second row: " + courses[1][2]);  // Chemistry
            System.out.println("Course in third row: " + courses[2][1]);  // Art
        }
    }

    Approach 3: Initializing Each Element Separately

    This method allows you to initialize elements individually.

    Example:

    public class Example {
        public static void main(String[] args) {
            int[][] marks = new int[2][2];
            marks[0][0] = 85;
            marks[0][1] = 90;
            marks[1][0] = 78;
            marks[1][1] = 88;
    
            System.out.println("marks[0][0] = " + marks[0][0]);
            System.out.println("marks[1][1] = " + marks[1][1]);
        }
    }

    Approach 4: Using Loops for Initialization

    When dealing with large arrays, initializing elements manually can be cumbersome. A more efficient approach is using loops.

    Example:

    public class Example {
        public static void main(String[] args) {
            int rows = 4, columns = 3;
            int[][] array = new int[rows][columns];
    
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < columns; j++) {
                    array[i][j] = i + j;
                }
            }
    
            // Printing array elements
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < columns; j++) {
                    System.out.print(array[i][j] + " ");
                }
                System.out.println();
            }
        }
    }

    Approach 5: Jagged Arrays (Different Number of Columns per Row)

    A jagged array allows rows to have different numbers of columns.

    Example:

    public class Example {
        public static void main(String[] args) {
            int[][] jaggedArray = new int[2][];
            jaggedArray[0] = new int[3];  // First row has 3 columns
            jaggedArray[1] = new int[2];  // Second row has 2 columns
    
            jaggedArray[0][0] = 1;
            jaggedArray[0][1] = 2;
            jaggedArray[0][2] = 3;
            jaggedArray[1][0] = 4;
            jaggedArray[1][1] = 5;
    
            // Printing the jagged array
            for (int i = 0; i < jaggedArray.length; i++) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    System.out.print(jaggedArray[i][j] + " ");
                }
                System.out.println();
            }
        }
    }

    Jagged Arrays in Java

    A jagged array is a type of multidimensional array where the number of columns varies from row to row. This makes the jagged array more flexible compared to a rectangular 2D array. Here’s a simplified representation of a jagged array in memory:

    Row 1: [ ]
    Row 2: [   ]
    Row 3: [         ]
    ...

    Declaring and Initializing a Jagged Array

    Syntax:

    data_type array_name[][] = new data_type[n][];
    array_name[0] = new data_type[n1];  // n1 = no. of columns in row-1
    array_name[1] = new data_type[n2];  // n2 = no. of columns in row-2
    ...

    Alternative Ways to Initialize a Jagged Array:

    int[][] arr = new int[][] {
        new int[] {10, 20, 30, 40},
        new int[] {50, 60, 70, 80, 90, 100},
        new int[] {110, 120}
    };

    or simply:

    int[][] arr = {
        {10, 20, 30, 40},
        {50, 60, 70, 80, 90, 100},
        {110, 120}
    };

    Example 1: Jagged Array with Uneven Rows

    public class Main {
        public static void main(String[] args) {
            // Declare a 2D array with 2 rows
            int[][] jaggedArray = new int[2][];
    
            // First row has 3 columns
            jaggedArray[0] = new int[3];
    
            // Second row has 2 columns
            jaggedArray[1] = new int[2];
    
            // Initializing the array
            int value = 0;
            for (int i = 0; i < jaggedArray.length; i++) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    jaggedArray[i][j] = value++;
                }
            }
    
            // Displaying the values of the jagged array
            System.out.println("Contents of the Jagged Array:");
            for (int i = 0; i < jaggedArray.length; i++) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    System.out.print(jaggedArray[i][j] + " ");
                }
                System.out.println();
            }
        }
    }

    Output:

    Contents of the Jagged Array:
    0 1 2
    3 4

    Example 2: Creating a Jagged Array with Incremental Row Sizes

    In this example, the first row contains one element, the second row contains two elements, and so on.

    public class Main {
        public static void main(String[] args) {
            int rows = 5;
    
            // Declaring a jagged array with 5 rows
            int[][] jaggedArray = new int[rows][];
    
            // Creating the jagged array with varying columns per row
            for (int i = 0; i < jaggedArray.length; i++) {
                jaggedArray[i] = new int[i + 1];  // ith row has i+1 columns
            }
    
            // Initializing the array
            int value = 0;
            for (int i = 0; i < jaggedArray.length; i++) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    jaggedArray[i][j] = value++;
                }
            }
    
            // Displaying the values of the jagged array
            System.out.println("Contents of the Jagged Array:");
            for (int i = 0; i < jaggedArray.length; i++) {
                for (int j = 0; j < jaggedArray[i].length; j++) {
                    System.out.print(jaggedArray[i][j] + " ");
                }
                System.out.println();
            }
        }
    }

    Output:

    Contents of the Jagged Array:
    0
    1 2
    3 4 5
    6 7 8 9
    10 11 12 13 14

    Final Arrays

    In Java, the final keyword prevents reassigning a reference to another object, but it doesn’t make the referenced object itself immutable. This is applicable to arrays as well. Once an array is declared as final, the reference to that array cannot be changed, but the elements within the array can be modified. This means we can change the state of the object (the contents of the array), but not the reference to the object itself.

    Illustration:

    // Java Program Demonstrating Final Arrays
    
    public class FinalArrayDemo {
        public static void main(String[] args) {
            final int[] arr = { 1, 2, 3, 4, 5 };
    
            // Modifying an element in the final array
            arr[3] = 10;
    
            // Displaying the updated array
            for (int i = 0; i < arr.length; i++) {
                System.out.println(arr[i]);
            }
        }
    }

    Output:

    1
    2
    3
    10
    5

    Implementation: Here’s another example showing how you can manipulate the contents of a final array:

    // Java Program Demonstrating Final Arrays
    
    public class FinalArrayExample {
        public static void main(String[] args) {
            final int[] arr = { 2, 4, 6, 8, 10 };
    
            // Modifying array elements
            for (int i = 0; i < arr.length; i++) {
                arr[i] = arr[i] * 2;
                System.out.println(arr[i]);
            }
        }
    }

    Output:

    4
    8
    12
    16
    20

    Explanation:

    Even though the array arr is declared as final, you can still change its individual elements. The final keyword simply means that the reference to the array cannot be reassigned to another array. This behavior is consistent with how object references work in Java: when you declare an object as final, the reference can’t be changed, but the object’s internal state can still be modified.

    Example 1:

    // Program demonstrating modification of object fields
    
    class Test {
        int value = 100;
    
        public static void main(String[] args) {
            final Test obj = new Test();
            obj.value = 200;  // Modifying the internal state
            System.out.println(obj.value);
        }
    }

    Output:

    200

    util.Arrays vs reflect.Array in Java with Examples

    The Array class in the java.lang.reflect package is part of Java Reflection and provides static methods to dynamically create and access Java arrays. This class is final, meaning it cannot be instantiated or extended. All its methods are static and accessed via the class name itself. On the other hand, the Arrays class in the java.util package is part of the Java Collection Framework and contains various utility methods for manipulating arrays, such as sorting and searching.

    While both classes deal with arrays, the key difference is their usage. The Array class ensures type safety and is mainly used for reflective access to arrays. The Arrays class, on the other hand, offers a variety of methods for array operations.

    Here is a breakdown of the differences between Array and Arrays:

    FactorArrayArrays
    PackageBelongs to java.lang.reflectBelongs to java.util
    Class Hierarchyjava.lang.Object → java.lang.reflect.Arrayjava.lang.Object → java.util.Arrays
    ImmutabilityImmutable and finalNot immutable
    Declarationpublic final class Array extends Objectpublic class Arrays extends Object
    UsageProvides methods to create and access arrays reflectively, ensuring type safetyContains utility methods for array manipulation (sorting, searching, etc.)

    Example: Illustrating the Usage of Array vs Arrays

    import java.lang.reflect.Array;
    import java.util.Arrays;
    
    public class ArrayVsArraysExample {
    
        public static void main(String[] args) {
    
            // Creating an integer array of size 5
            int[] intArray = new int[5];
    
            // Adding an element to the array using Array class
            Array.setInt(intArray, 0, 42);
    
            // Printing the array using Arrays class
            System.out.println(Arrays.toString(intArray));
        }
    }

    Output:

    [42, 0, 0, 0, 0]

  • Operators in Java

    Operators

    Operators are the foundation of any programming language, enabling us to perform various computations, logic evaluations, and functions. Java offers several types of operators that are categorized based on the functions they perform. These include:

    • Arithmetic Operators
    • Unary Operators
    • Assignment Operator
    • Relational Operators
    • Logical Operators
    • Ternary Operator
    • Bitwise Operators
    • Shift Operators

    This section focuses on Arithmetic Operators, which allow us to carry out mathematical operations on basic data types. These operators can either be unary (applied to one operand) or binary (applied to two operands). Let’s dive into each arithmetic operator in Java.

    Arithmetic Operators in Java

    1. Addition (+)

    This binary operator is used to add two operands.

    Syntax:

    num1 + num2

    Example:

    int num1 = 10, num2 = 20;
    int sum = num1 + num2;

    Output:

    num1 = 10
    num2 = 20
    The sum = 30

    Java Code Example:

    public class AdditionExample {
        public static void main(String[] args) {
            int num1 = 10, num2 = 20;
            int sum = num1 + num2;
            System.out.println("The sum = " + sum);
        }
    }

    2. Subtraction (-)

    This binary operator is used to subtract the second operand from the first operand.

    Syntax:

    num1 - num2

    Example:

    int num1 = 20, num2 = 10;
    int difference = num1 - num2;

    Output:

    num1 = 20
    num2 = 10
    The difference = 10

    Java Code Example:

    public class SubtractionExample {
        public static void main(String[] args) {
            int num1 = 20, num2 = 10;
            int difference = num1 - num2;
            System.out.println("The difference = " + difference);
        }
    }

    3. Multiplication (*)

    This binary operator multiplies two operands.

    Syntax:

    num1 * num2

    Example:

    int num1 = 20, num2 = 10;
    int product = num1 * num2;

    Output:

    num1 = 20
    num2 = 10
    The product = 200

    Java Code Example:

    public class MultiplicationExample {
        public static void main(String[] args) {
            int num1 = 20, num2 = 10;
            int product = num1 * num2;
            System.out.println("The product = " + product);
        }
    }

    4. Division (/)

    This binary operator divides the first operand (dividend) by the second operand (divisor) and returns the quotient.

    Syntax:

    num1 / num2

    Example:

    int num1 = 20, num2 = 10;
    int quotient = num1 / num2;

    Output:

    num1 = 20
    num2 = 10
    The quotient = 2

    Java Code Example:

    public class DivisionExample {
        public static void main(String[] args) {
            int num1 = 20, num2 = 10;
            int quotient = num1 / num2;
            System.out.println("The quotient = " + quotient);
        }
    }

    5. Modulus (%)

    This binary operator returns the remainder when the first operand (dividend) is divided by the second operand (divisor).

    Syntax:

    num1 % num2

    Example:

    int num1 = 5, num2 = 2;
    int remainder = num1 % num2;

    Output:

    num1 = 5
    num2 = 2
    The remainder = 1

    Java Code Example:

    public class ModulusExample {
        public static void main(String[] args) {
            int num1 = 5, num2 = 2;
            int remainder = num1 % num2;
            System.out.println("The remainder = " + remainder);
        }
    }

    Example Program Implementing All Arithmetic Operators

    The following Java program takes user input and performs addition, subtraction, multiplication, and division:

    import java.util.Scanner;
    
    public class ArithmeticOperators {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            System.out.print("Enter the first number: ");
            double num1 = sc.nextDouble();
    
            System.out.print("Enter the second number: ");
            double num2 = sc.nextDouble();
    
            double sum = num1 + num2;
            double difference = num1 - num2;
            double product = num1 * num2;
            double quotient = num1 / num2;
    
            System.out.println("The sum of the two numbers is: " + sum);
            System.out.println("The difference of the two numbers is: " + difference);
            System.out.println("The product of the two numbers is: " + product);
            System.out.println("The quotient of the two numbers is: " + quotient);
        }
    }

    Input:

    Enter the first number: 20
    Enter the second number: 10

    Output:

    The sum of the two numbers is: 30.0
    The difference of the two numbers is: 10.0
    The product of the two numbers is: 200.0
    The quotient of the two numbers is: 2.0

    Java Unary Operator

    Unary operators in Java operate on a single operand. These operators are used for tasks such as incrementing, decrementing, and negating values. Let’s explore the various unary operators and how they function.

    Operator 1: Unary Minus (-)

    This operator is used to reverse the sign of a value, converting a positive value into a negative one, or vice versa.

    Syntax:

    -(operand)

    Example:

    // Java Program demonstrating Unary Minus
    class UnaryMinus {
        public static void main(String[] args) {
            int num = 20;
            System.out.println("Number = " + num);
    
            // Applying unary minus
            num = -num;
            System.out.println("After applying unary minus = " + num);
        }
    }

    Output:

    Number = 20
    After applying unary minus = -20

    Operator 2: NOT Operator (!)

    This operator negates a boolean expression, flipping true to false and vice versa.

    Syntax:

    !(operand)

    Example:

    // Java Program demonstrating NOT Operator
    class NotOperator {
        public static void main(String[] args) {
            boolean flag = true;
            int a = 10, b = 1;
    
            System.out.println("Initial flag: " + flag);
            System.out.println("a = " + a + ", b = " + b);
    
            // Applying NOT operator
            System.out.println("Negated flag: " + !flag);
            System.out.println("!(a < b) = " + !(a < b));
            System.out.println("!(a > b) = " + !(a > b));
        }
    }

    Output:

    Initial flag: true
    a = 10, b = 1
    Negated flag: false
    !(a < b) = true
    !(a > b) = false

    Operator 3: Increment (++)

    The increment operator increases the value of an operand by one. It can be used in two forms:

    • Post-Increment: The operand is incremented after its current value is used.
    • Pre-Increment: The operand is incremented before its current value is used.

    Example:

    int num = 5;
    System.out.println("Post-increment: " + (num++)); // Uses current value, then increments
    System.out.println("Pre-increment: " + (++num));  // Increments, then uses new value

    Operator 4: Decrement (--)

    Similar to the increment operator, the decrement operator decreases the operand’s value by one and can also be used in two forms:

    • Post-Decrement: Decrements the operand after its current value is used.
    • Pre-Decrement: Decrements the operand before its current value is used.

    Example:

    int num = 5;
    System.out.println("Post-decrement: " + (num--)); // Uses current value, then decrements
    System.out.println("Pre-decrement: " + (--num));  // Decrements, then uses new value

    Operator 5: Bitwise Complement (~)

    This operator inverts all the bits of the operand. It converts 0s to 1s and 1s to 0s.

    Syntax:

    ~(operand)

    Example:

    // Java Program demonstrating Bitwise Complement Operator
    class BitwiseComplement {
        public static void main(String[] args) {
            int num = 5;
            System.out.println("Number: " + num);
    
            // Applying bitwise complement
            System.out.println("Bitwise complement: " + ~num);
        }
    }

    Output:

    Number: 5
    Bitwise complement: -6

    Example Program Demonstrating All Unary Operators

    Here’s a comprehensive program that demonstrates the use of all basic unary operators with user input:

    import java.util.Scanner;
    
    public class UnaryOperatorsExample {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            System.out.print("Enter a number: ");
            int num = sc.nextInt();
    
            // Unary plus
            int result = +num;
            System.out.println("Unary plus result: " + result);
    
            // Unary minus
            result = -num;
            System.out.println("Unary minus result: " + result);
    
            // Pre-increment
            result = ++num;
            System.out.println("Pre-increment result: " + result);
    
            // Post-increment
            result = num++;
            System.out.println("Post-increment result: " + result);
    
            // Pre-decrement
            result = --num;
            System.out.println("Pre-decrement result: " + result);
    
            // Post-decrement
            result = num--;
            System.out.println("Post-decrement result: " + result);
    
            sc.close();
        }
    }

    Input:

    Enter a number: 10

    Output:

    Unary plus result: 10
    Unary minus result: -10
    Pre-increment result: 11
    Post-increment result: 11
    Pre-decrement result: 11
    Post-decrement result: 10

    Java Assignment Operators

    In Java, operators form the basic building blocks of programming, allowing developers to perform various types of calculations, comparisons, and logical operations. Assignment operators specifically help assign values to variables. They have right-to-left associativity, meaning the value on the right side of the operator is assigned to the variable on the left. Let’s dive into the different types of assignment operators used in Java.

    Types of Assignment Operators:

    1. Simple Assignment Operator (=): The simple assignment operator is used to assign a value to a variable. The operand on the right-hand side must match the data type of the variable on the left-hand side.

    Syntax:

    variable = value;

    Example:

    public class AssignmentOperatorExample {
        public static void main(String[] args) {
            int num = 15;
            String name = "Java";
    
            System.out.println("num is assigned: " + num);
            System.out.println("name is assigned: " + name);
        }
    }

    Output:

    num is assigned: 15
    name is assigned: Java

    2. Add and Assign (+=): The compound += operator adds the value on the right to the value of the variable on the left and then assigns the result back to the variable on the left.

    Syntax:

    variable += value;

    Example:

    public class AddAssignExample {
        public static void main(String[] args) {
            int num1 = 5, num2 = 3;
            num1 += num2;
            System.out.println("After adding: " + num1);
        }
    }

    Output:

    After adding: 8

    Note: This operator performs implicit type conversion if necessary. For instance, adding a double to an int using += will result in automatic narrowing conversion.

    3. Subtract and Assign (-=): The compound -= operator subtracts the value on the right from the value on the left and then assigns the result back to the variable on the left.

    Syntax:

    variable -= value;

    Example:

    public class SubtractAssignExample {
        public static void main(String[] args) {
            int num1 = 10, num2 = 4;
            num1 -= num2;
            System.out.println("After subtracting: " + num1);
        }
    }

    Output:

    After subtracting: 6

    4. Multiply and Assign (*=): This operator multiplies the current value of the variable by the value on the right and assigns the result back to the variable on the left.

    Syntax:

    variable *= value;
    a *= 2;  // Equivalent to a = a * 2

    Example:

    public class MultiplyAssignExample {
        public static void main(String[] args) {
            int num1 = 4, num2 = 3;
            num1 *= num2;
            System.out.println("After multiplying: " + num1);
        }
    }

    Output:

    After multiplying: 12

    5. Divide and Assign (/=): This operator divides the current value of the variable by the value on the right and assigns the result back to the variable on the left.

    Syntax:

    variable /= value;

    Example:

    public class DivideAssignExample {
        public static void main(String[] args) {
            int num1 = 20, num2 = 4;
            num1 /= num2;
            System.out.println("After dividing: " + num1);
        }
    }

    Output:

    After dividing: 5

    6. Modulus and Assign (%=): This operator performs division and assigns the remainder back to the variable on the left.

    Syntax:

    variable %= value;

    Example:

    public class ModulusAssignExample {
        public static void main(String[] args) {
            int num1 = 17, num2 = 5;
            num1 %= num2;
            System.out.println("After modulus: " + num1);
        }
    }

    Output:

    After modulus: 2

    Java Relational Operators

    Relational operators in Java are binary operators used to compare two operands and return a boolean value indicating the result of the comparison. These operators are often used in control flow statements such as loops and conditionals.

    General Syntax:

    variable1 relation_operator variable2

    1. Equal to (==)

    The == operator checks if two operands are equal. If they are, it returns true; otherwise, it returns false.

    Syntax:

    var1 == var2

    Example:

    int var1 = 5, var2 = 10, var3 = 5;
    
    System.out.println("var1 == var2: " + (var1 == var2));  // false
    System.out.println("var1 == var3: " + (var1 == var3));  // true

    Output:

    var1 == var2: false
    var1 == var3: true

    2. Not Equal to (!=)

    The != operator checks if two operands are not equal. It returns true if the operands are unequal, and false if they are equal.

    Syntax:

    var1 != var2

    Loop Variables (Block Scope)

    Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.

    Example:

    int var1 = 5, var2 = 10, var3 = 5;
    
    System.out.println("var1 != var2: " + (var1 != var2));  // true
    System.out.println("var1 != var3: " + (var1 != var3));  // false

    Output:

    var1 != var2: true
    var1 != var3: false

    3. Greater than (>)

    The > operator checks if the left operand is greater than the right operand. If true, it returns true; otherwise, false.

    Syntax:

    var1 > var2

    Example:

    int var1 = 30, var2 = 20;
    
    System.out.println("var1 > var2: " + (var1 > var2));  // true

    Output:

    var1 > var2: true

    4. Less than (<)

    The < operator checks if the left operand is less than the right operand.

    Syntax:

    var1 < var2

    Example:

    int var1 = 10, var2 = 20;
    
    System.out.println("var1 < var2: " + (var1 < var2));  // true

    Output:

    var1 < var2: true

    5. Greater than or equal to (>=)

    The >= operator checks if the left operand is greater than or equal to the right operand.

    Syntax:

    var1 >= var2

    Example:

    int var1 = 20, var2 = 20;
    
    System.out.println("var1 >= var2: " + (var1 >= var2));  // true

    Output:

    var1 >= var2: true

    6. Less than or equal to (<=)

    The <= operator checks if the left operand is less than or equal to the right operand.

    Syntax:

    var1 <= var2

    Example:

    int var1 = 10, var2 = 10;
    
    System.out.println("var1 <= var2: " + (var1 <= var2));  // true

    Output:

    var1 <= var2: true

    Java Logical Operators

    Logical operators are used to perform logical operations such as “AND,” “OR,” and “NOT,” similar to the functions of AND and OR gates in digital electronics. They combine two or more conditions or reverse the outcome of a given condition. An important point to remember is that in the case of the AND operator, the second condition is not evaluated if the first is false, while in the case of the OR operator, the second condition is not evaluated if the first is true. This feature is known as short-circuiting. Logical operators are commonly used in decision-making when multiple conditions need to be checked.

    Logical Operators in Java

    Let’s go through an example with some common logical operators in Java. Assume we have the following variables:

    Syntax:

    int a = 10;
    int b = 20;
    int c = 30;

    AND Operator (&&):

    This operator returns true if both conditions are true. Otherwise, it returns false.

    Example:

    • Condition 1: c > a (true)
    • Condition 2: c > b (true)

    Since both conditions are true, the result will be true.

    Example:

    if (c > a && c > b) {
        System.out.println("Both conditions are true");
    } else {
        System.out.println("At least one condition is false");
    }

    Output:

    Both conditions are true

    OR Operator (||):

    This operator returns true if at least one of the conditions is true. If both conditions are false, the result is false.

    Example:

    • Condition 1: c > a (true)
    • Condition 2: c < b (false)

    Since one of the conditions is true, the result will be true.

    if (c > a || c < b) {
        System.out.println("At least one condition is true");
    } else {
        System.out.println("Both conditions are false");
    }

    Output:

    At least one condition is true

    NOT Operator (!):

    This unary operator returns the opposite of the condition. If the condition is true, it returns false, and vice versa.

    Example:

    • Condition: c > a (true)
    • Applying NOT: !(c > a) (false)
    System.out.println(!(c > a));  // false
    System.out.println(!(c < a));  // true

    Output:

    false
    true

    Short-Circuiting in AND Operator:

    In cases where the first condition of an AND operation is false, the second condition will not be evaluated.

    Example:

    int a = 10, b = 20, c = 15;
    
    if ((a > c) && (++b > c)) {
        System.out.println("Condition met");
    }
    System.out.println("Value of b: " + b);

    Output:

    Value of b: 20

    Short-Circuiting in AND Operator:

    In cases where the first condition of an AND operation is false, the second condition will not be evaluated.

    Example:

    int a = 10, b = 20, c = 15;
    
    if ((a > c) && (++b > c)) {
        System.out.println("Condition met");
    }
    System.out.println("Value of b: " + b);

    Output:

    Value of b: 20

    Short-Circuiting in OR Operator:

    In cases where the first condition of an OR operation is true, the second condition will not be evaluated.

    Example:

    int a = 10, b = 20, c = 15;
    
    if ((a < c) || (++b < c)) {
        System.out.println("Condition met");
    }
    System.out.println("Value of b: " + b);

    Output:

    Condition met
    Value of b: 20

    Boolean Values and Logical Operators:

    Logical operators can also be applied directly to boolean values. For example:

    Example:

    boolean a = true;
    boolean b = false;
    
    System.out.println("a && b: " + (a && b)); // false
    System.out.println("a || b: " + (a || b)); // true
    System.out.println("!a: " + !a);           // false
    System.out.println("!b: " + !b);           // true

    Output:

    a && b: false
    a || b: true
    !a: false
    !b: true

    Java Ternary Operator

    The ternary operator is the only operator in Java that takes three operands. It serves as a concise alternative to the traditional if-else statement, allowing conditional logic in a single line. Although it operates similarly to if-else, it helps to reduce code size and improve readability.

    Syntax:

    variable = (condition) ? expression1 : expression2;

    This syntax translates to:

    • If condition is trueexpression1 is executed.
    • If condition is falseexpression2 is executed.

    Here’s the equivalent structure using an if-else statement:

    if(condition) {
        variable = expression1;
    } else {
        variable = expression2;
    }

    Example:

    int num1 = 10;
    int num2 = 20;
    int result = (num1 > num2) ? (num1 + num2) : (num1 - num2);

    Since num1 < num2, the second expression is executed, so:

    Syntax:

    result = num1 - num2 = -10;

    Example:

    class TernaryExample {
        public static void main(String[] args) {
            int n1 = 5, n2 = 10, max;
    
            System.out.println("First number: " + n1);
            System.out.println("Second number: " + n2);
    
            // Using ternary operator to find the maximum
            max = (n1 > n2) ? n1 : n2;
    
            System.out.println("The maximum number is: " + max);
        }
    }

    Output:

    First number: 5
    Second number: 10
    The maximum number is: 10

    Bitwise operators

    Bitwise operators are used to manipulate individual bits of a number. They are particularly useful when optimizing performance in certain cases, as they directly operate on the binary representation of numbers. Bitwise operators can be used with any integral type (e.g., charshortint). They are often employed when performing operations on Binary Indexed Trees (BITs).

    Here are the common bitwise operators in Java:

    1. Bitwise OR (|)

    The Bitwise OR operator is represented by the symbol |. It compares the corresponding bits of two operands, and if either of the bits is 1, the result is 1; otherwise, the result is 0.
    Example:

    a = 6 = 0110 (In Binary)
    b = 9 = 1001 (In Binary)
    
    Bitwise OR Operation:
      0110
    | 1001
    _________
      1111  = 15 (In decimal)

    2. Bitwise AND (&)

    The Bitwise AND operator is represented by &. It compares the corresponding bits of two operands, and if both bits are 1, the result is 1; otherwise, the result is 0.
    Example:

    a = 6 = 0110 (In Binary)
    b = 9 = 1001 (In Binary)
    
    Bitwise AND Operation:
      0110
    & 1001
    _________
      0000  = 0 (In decimal)

    3. Bitwise XOR (^)

    The Bitwise XOR operator is represented by ^. It compares the corresponding bits of two operands, and if the bits are different, the result is 1; otherwise, the result is 0.
    Example:

    a = 6 = 0110 (In Binary)
    b = 9 = 1001 (In Binary)
    
    Bitwise XOR Operation:
      0110
    ^ 1001
    _________
      1111  = 15 (In decimal)

    4. Bitwise Complement (~)

    The Bitwise NOT (complement) operator is represented by ~. It inverts all the bits of the operand, changing every 1 to 0 and every 0 to 1.
    Example:

    a = 6 = 0110 (In Binary)
    
    Bitwise NOT Operation:
    ~ 0110
    _________
      1001  = -7 (In decimal, as it returns the two's complement)

    Code Example:

    import java.util.Scanner;
    
    public class BitwiseOperators {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
    
            System.out.print("Enter first number: ");
            int num1 = input.nextInt();
    
            System.out.print("Enter second number: ");
            int num2 = input.nextInt();
    
            System.out.println("Bitwise AND: " + (num1 & num2));
            System.out.println("Bitwise OR: " + (num1 | num2));
            System.out.println("Bitwise XOR: " + (num1 ^ num2));
            System.out.println("Bitwise NOT: " + (~num1));
            System.out.println("Bitwise Left Shift: " + (num1 << 2));
            System.out.println("Bitwise Right Shift: " + (num1 >> 2));
            System.out.println("Bitwise Unsigned Right Shift: " + (num1 >>> 2));
    
            input.close();
        }
    }

    Input:

    Enter first number: 4
    Enter second number: 10

    Output:

    Bitwise AND: 0
    Bitwise OR: 14
    Bitwise XOR: 14
    Bitwise NOT: -5
    Bitwise Left Shift: 16
    Bitwise Right Shift: 1
    Bitwise Unsigned Right Shift: 1
  • Flow Control in java

    Decision Making in Java (if, if-else, switch, break, continue, jump).

    Decision-making in programming is like making decisions in real life. When coding, we often need to execute certain blocks of code only if specific conditions are met.

    Java provides several control statements to control the flow of a program based on conditions. These statements direct the flow of execution, allowing it to branch and continue based on the program’s state.

    Java’s Selection Statements:
    • if
    • if-else
    • nested-if
    • if-else-if
    • switch-case
    • jump (break, continue, return)

    1. if Statement:

    The simplest decision-making statement. It is used to decide whether a certain block of code will be executed or not, depending on whether the condition is true.

    Syntax:

    if(condition) {
       // Statements to execute if the condition is true
    }

    Here, the condition evaluates to either true or false. If true, the block of statements inside the if block is executed.

    If we do not use curly braces ({}), only the first statement after the if will be considered part of the if block.

    Example:

    class IfDemo {
        public static void main(String args[]) {
            int i = 10;
    
            if (i < 15)
                System.out.println("Inside If block"); // Part of if block
            System.out.println("10 is less than 15");  // Outside of if block
            System.out.println("I am not in if block");
        }
    }

    Output:

    Inside If block
    10 is less than 15
    I am not in if block

    2. if-else Statement:

    The if statement alone can execute code when a condition is true. But what if we want to execute something else when the condition is false? This is where the else statement comes in.

    Syntax:

    if (condition) {
        // Executes if condition is true
    } else {
        // Executes if condition is false
    }

    Example:

    class IfElseDemo {
        public static void main(String args[]) {
            int i = 10;
    
            if (i < 15)
                System.out.println("i is smaller than 15");
            else
                System.out.println("i is greater than 15");
        }
    }

    Output:

    i is smaller than 15

    3. nested-if Statement:

    nested-if is an if statement inside another if. This allows you to perform more complex decision-making scenarios.

    Syntax:

    if (condition1) {
       if (condition2) {
          // Executes when both conditions are true
       }
    }

    Example:

    class NestedIfDemo {
        public static void main(String args[]) {
            int i = 10;
    
            if (i == 10 || i < 15) {
                if (i < 15)
                    System.out.println("i is smaller than 15");
    
                if (i < 12)
                    System.out.println("i is smaller than 12 too");
            } else {
                System.out.println("i is greater than 15");
            }
        }
    }

    Output:

    i is smaller than 15
    i is smaller than 12 too

    4. if-else-if Ladder:

    The if-else-if ladder allows you to test multiple conditions. The conditions are evaluated from top to bottom, and as soon as one of them is true, its corresponding block is executed, and the rest are skipped.

    Syntax:

    if (condition1) {
        // Executes if condition1 is true
    } else if (condition2) {
        // Executes if condition2 is true
    } else {
        // Executes if none of the above conditions are true
    }

    Example:

    class IfElseIfDemo {
        public static void main(String args[]) {
            int i = 20;
    
            if (i == 10)
                System.out.println("i is 10");
            else if (i == 15)
                System.out.println("i is 15");
            else if (i == 20)
                System.out.println("i is 20");
            else
                System.out.println("i is not present");
        }
    }

    Output:

    i is 20

    5. switch-case Statement:

    The switch statement allows you to branch execution based on the value of an expression. It’s like having multiple if-else blocks for a single expression.

    Syntax:

    switch (expression) {
      case value1:
        // Code to be executed if expression equals value1
        break;
      case value2:
        // Code to be executed if expression equals value2
        break;
      // Add more cases as needed
      default:
        // Code to be executed if none of the cases match
    }

    Example:

    class SwitchDemo {
        public static void main(String[] args) {
            int num = 20;
            switch (num) {
              case 5:
                System.out.println("It is 5");
                break;
              case 10:
                System.out.println("It is 10");
                break;
              case 15:
                System.out.println("It is 15");
                break;
              case 20:
                System.out.println("It is 20");
                break;
              default:
                System.out.println("Not present");
            }
        }
    }

    Output:

    It is 20

    6. Jump Statements:

    Java has three main jump statements:

    • break: Used to exit a loop or a switch statement.
    • continue: Skips the remaining code in the current iteration of a loop and starts the next iteration.
    • return: Exits from the current method and passes control back to the caller.

    Example of continue:

    class ContinueDemo {
        public static void main(String args[]) {
            for (int i = 0; i < 10; i++) {
                if (i % 2 == 0)
                    continue;
    
                System.out.print(i + " ");
            }
        }
    }

    Output:

    1 3 5 7 9

    If Statements with Examples

    Decision Making in Java allows you to execute a specific block of code based on certain conditions. It’s a key part of controlling the flow of a program, similar to how we make decisions in real life.

    Java’s if Statement:

    The if statement is the simplest form of decision-making. It allows you to execute a block of code if a specific condition evaluates to true.

    Syntax:

    if (condition) {
       // Statements to execute if the condition is true
    }

    How It Works:

    1. Control enters the if block.
    2. The condition is evaluated.

    • If the condition is true, the block of code within the if statement is executed.
    • If the condition is false, the control moves to the next part of the program.

    Example:

    class IfDemo {
        public static void main(String args[]) {
            int i = 10;
    
            if (i < 15)
                System.out.println("10 is less than 15");
    
            System.out.println("Outside if-block");
        }
    }

    Output:

    10 is less than 15
    Outside if-block
    Java if-else Statement

    Decision-making in Java allows for the execution of certain blocks of code based on specific conditions. The if statement tells us that if a condition is true, it will execute a block of statements; otherwise, it won’t. By combining if and else, you can handle both outcomes—what happens when the condition is true and when it’s false.

    Understanding if-else in Java:

    The if-else statement is used to control the flow of your program by executing code based on whether a condition is true or false.

    Syntax of if-else Statement:

    if (condition) {
        // Executes this block if the condition is true
    } else {
        // Executes this block if the condition is false
    }

    Example Program:

    // Java program to demonstrate if-else statement
    
    class IfElseDemo {
        public static void main(String args[]) {
            int i = 20;
    
            if (i < 15) {
                System.out.println("i is smaller than 15");
            } else {
                System.out.println("i is greater than 15");
            }
    
            System.out.println("Outside if-else block");
        }
    }

    Output:

    i is greater than 15
    Outside if-else block

    Java if-else-if Ladder

    Decision-making in Java allows us to write condition-based statements that execute particular blocks of code depending on specific conditions. The if-else-if ladder is used to handle multiple conditions by checking each one sequentially. As soon as a condition evaluates to true, its corresponding block is executed, and the rest of the ladder is ignored. If none of the conditions are true, the final else block is executed.

    Syntax:

    if (condition) {
        // Executes if condition 1 is true
    } else if (condition) {
        // Executes if condition 2 is true
    }
    .
    .
    else {
        // Executes if no conditions are true
    }

    Working of if-else-if Ladder:

    1. Control enters the if block.
    2. The first condition is evaluated:If true, the associated block is executed, and the rest of the ladder is skipped.
    If false, the flow moves to the next condition.
    3. This process repeats for each condition in the ladder.
    4. If none of the conditions are met, the else block is executed.

    Example :

    // Java program to demonstrate if-else-if ladder
    
    class IfElseIfLadderDemo {
        public static void main(String[] args) {
            // Initializing expression
            int i = 20;
    
            // Condition 1
            if (i == 10) {
                System.out.println("i is 10");
            }
            // Condition 2
            else if (i == 15) {
                System.out.println("i is 15");
            }
            // Condition 3
            else if (i == 20) {
                System.out.println("i is 20");
            }
            // Default case
            else {
                System.out.println("i is not present");
            }
    
            System.out.println("Outside if-else-if ladder");
        }
    }

    Output:

    i is 20
    Outside if-else-if ladder

    Loops in Java

    Looping is an essential feature in programming that allows a set of instructions to be executed repeatedly as long as a specified condition evaluates to true. In Java, loops are implemented in three different ways, each with a unique syntax and method of checking conditions.

    while Loop

    Looping is an essential feature in programming that allows a set of instructions to be executed repeatedly as long as a specified condition evaluates to true. In Java, loops are implemented in three different ways, each with a unique syntax and method of checking conditions.

    while (boolean condition) {
        // Loop body
    }

    Example:

    public class WhileLoopExample {
        public static void main(String[] args) {
            int i = 0;
            while (i <= 10) {
                System.out.println(i);
                i++;
            }
        }
    }

    Output:

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    Working of while loop:

    • The loop starts by checking the boolean condition.
    • If the condition is true, the loop body is executed.
    • After each execution, the condition is rechecked before the next iteration.
    • The loop terminates when the condition evaluates to false.

    This is an entry control loop, meaning the condition is checked before the loop body is executed.

    Java do-while loop with Examples

    Loops are a fundamental concept in programming, used when we need to execute a block of code repeatedly. The do-while loop is an example of an Exit Control Loop in Java, meaning the loop body will always execute at least once, as the condition is checked after the loop body has been executed, unlike in for and while loops where the condition is checked beforehand.

    Syntax of do-while Loop:

    do {
        // Loop body
        update_expression;
    } while (test_expression);

    Output:

    Print statement

    For-each loop in Java

    The for-each loop in Java, introduced in Java 5, is a simplified way to traverse arrays and collections. It provides a cleaner and more readable syntax when you need to access each element of an array or a collection like ArrayList.

    Key Features of the For-Each Loop:
    • It begins with the keyword for, similar to a regular for-loop.
    • Instead of initializing and maintaining a loop counter, you declare a variable (of the same type as the array elements) that iterates through each element.
    • The loop body uses this variable directly, without needing to reference an array index.

    The for-each loop is particularly useful for iterating through arrays or classes from the Java Collection Framework, such as ArrayList.

    Syntax:

    for (type var : array) {
        // Statements using var
    }

    Example: Simple Array Traversal using For-Each Loop

    public class Easy {
        public static void main(String[] args) {
            // Array declaration
            int[] ar = {10, 50, 60, 80, 90};
    
            // For-each loop to iterate through array
            for (int element : ar) {
                System.out.print(element + " ");
            }
        }
    }

    Output:

    10 50 60 80 90

    Equivalent Syntax with Regular For Loop:

    for (int i = 0; i < ar.length; i++) {
        int element = ar[i];
        // Statements using element
    }

    Example: Finding the Highest Score using For-Each Loop

    // Java program to illustrate for-each loop
    public class ForEachExample {
        public static void main(String[] args) {
            int[] marks = {125, 132, 95, 116, 110};
    
            int highestMarks = maximum(marks);
            System.out.println("The highest score is " + highestMarks);
        }
    
        public static int maximum(int[] numbers) {
            int maxSoFar = numbers[0];
    
            // For-each loop to find the maximum value
            for (int num : numbers) {
                if (num > maxSoFar) {
                    maxSoFar = num;
                }
            }
            return maxSoFar;
        }
    }

    Output:

    The highest score is 132
    Limitations of the For-Each Loop

    1. Modifying Array Elements: For-each loops don’t allow modification of array elements. Changing the loop variable does not affect the array:

    for (int num : marks) {
        num = num * 2;  // Only changes num, not the actual array element
    }

    2. No Access to  Index: You can’t get the index of the current element using a for-each loop:

    for (int num : numbers) {
        if (num == target) {
            return ???;  // No index available
        }
    }

    3. Only Forward Iteration: For-each loops can only iterate forward, making it impossible to iterate in reverse order:

    for (int i = numbers.length - 1; i >= 0; i--) {
        System.out.println(numbers[i]);  // Cannot be done using for-each
    }

    4. Handling Multiple Decision Statements: For-each loops struggle to process multiple decision-making conditions:

    for (int i = 0; i < numbers.length; i++) {
        if (numbers[i] == arr[i]) {
            // Hard to convert this to a for-each loop
        }
    }

    Break Statement in Java

    The break statement in Java is a control statement used to terminate the loop prematurely. Once the break statement is encountered, the loop terminates immediately, and the control moves to the next statement following the loop.

    Syntax:

    break;
    When to Use the Break Statement:

    1. When the exact number of iterations is not known in advance.
    2. When you want to exit the loop based on some condition during iteration.

    Use Cases for Break:

    1. Terminating a sequence in a switch statement.
    2. Exiting a loop.
    3. Serving as a structured alternative to goto.

    Example: Break in a Switch Statement

    // Example of using break statement in switch
    public class SwitchBreakExample {
        public static void main(String[] args) {
            // Assigning n an integer value
            int n = 1;
    
            // Passing n to switch
            // The case matching n will execute and terminate due to break
            switch (n) {
                case 1:
                    System.out.println("Hello World");
                    break;
                case 2:
                    System.out.println("Second Case");
                    break;
                default:
                    System.out.println("Default Case");
            }
        }
    }

    Output:

    Hello World
    Using Break to Exit a Loop

    With the break statement, you can force the loop to terminate immediately, skipping the remaining iterations. It’s commonly used when you want to stop the loop based on a specific condition.

    Example: Breaking out of a Loop

    // Java program to illustrate using break to exit a loop
    public class BreakLoopDemo {
        public static void main(String[] args) {
            // The loop runs from 0 to 9
            for (int i = 0; i < 10; i++) {
                // Terminate loop when i equals 5
                if (i == 5)
                    break;
    
                System.out.println("i: " + i);
            }
            System.out.println("Loop complete.");
        }
    }

    Output:

    i: 0
    i: 1
    i: 2
    i: 3
    i: 4
    Loop complete.
    • Time Complexity: O(1)
    • Auxiliary Space: O(1)

    Using Break as a Form of Goto

    Java doesn’t support the goto statement because it allows jumping in an unstructured manner, leading to complex and unreadable code. Instead, Java uses labels to identify a block of code. You can use the break statement to jump out of a labeled block.

    Syntax:

    label:
    {
      // Code block
      statement1;
      statement2;
      // Break can be used to exit the block
      break label;
    }

    Example: Break with a Label

    // Java program to illustrate using break with label
    public class BreakLabelDemo {
        public static void main(String[] args) {
            boolean condition = true;
    
            // Label first
            first: {
                second: {
                    third: {
                        // Before break
                        System.out.println("Before the break statement");
    
                        // If condition is true, break out of the second block
                        if (condition)
                            break second;
    
                        System.out.println("This won't execute.");
                    }
                    System.out.println("This won't execute.");
                }
    
                // After exiting the second block
                System.out.println("This is after second block.");
            }
        }
    }

    Output:

    Before the break statement
    This is after second block

    return keyword in Java

    In Java, the scope of a variable refers to the region in the code where the variable is accessible. Java has lexical (static) scoping, meaning the scope of a variable is determined at compile time and is not dependent on the function call stack. The scope rules in Java can be broadly classified into three categories based on where the variables are declared.

    1. Member Variables (Class-Level Scope)
    2. Local Variables (Method-Level Scope)
    3. Block Variables (Loop or Block-Level Scope)

    1. Member Variables (Class-Level Scope)

    Member variables are declared inside a class but outside any method, constructor, or block. They can be accessed anywhere within the class and can have different access levels (e.g., publicprivateprotected, or default). Access to member variables outside the class depends on the access modifier used.

    Example:

    public class Test {
        // Member variables
        int a;                  // Default access modifier
        private String b;        // Private member variable
        char c;                  // Default access modifier
    
        void method1() {
            // Member variables can be accessed here
            System.out.println(a);
            System.out.println(b);
        }
    
        int method2() {
            return a;
        }
    }
    • Public: Accessible within the class, in subclasses, and outside the class.
    • Protected: Accessible within the class and in subclasses but not outside the package.
    • Default (no modifier): Accessible within the same package but not outside it.
    • Private: Only accessible within the class.


    2. Local Variables (Method-Level Scope)

    Local variables are declared inside a method or constructor and are only accessible within that method. They must be initialized before use, and their lifetime is limited to the method’s execution. Once the method finishes, local variables are destroyed.

    Example:

    public class Test {
        void method1() {
            // Local variable
            int x = 10;
            System.out.println(x);  // Accessible inside the method
        }
    
        public static void main(String[] args) {
            Test t = new Test();
            t.method1();
        }
    }

    Local variables do not retain their values once the method completes, and they are recreated each time the method is invoked.

    3. Block Variables (Loop or Block-Level Scope)

    Variables declared inside a block (within curly braces {}) are only accessible within that block. Once the block is exited, these variables are out of scope and cannot be accessed. This applies to variables declared inside loops or conditionals.

    Example of Block-Level Scope:

    public class Test {
        public static void main(String[] args) {
            {
                int x = 10;  // x is only accessible inside this block
                System.out.println(x);
            }
    
            // Uncommenting the following line will cause an error
            // System.out.println(x);  // x is out of scope here
        }
    }

    Loop Variables (Block Scope)

    Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.

    Example:

    class Test {
        public static void main(String[] args) {
            for (int x = 0; x < 4; x++) {
                System.out.println(x);  // x is accessible inside the loop
            }
    
            // Uncommenting the following line will result in an error
            // System.out.println(x);  // x is out of scope here
        }
    }

    If you need to access a loop variable outside the loop, declare it before the loop:

    class Test {
        public static void main(String[] args) {
            int x;
            for (x = 0; x < 4; x++) {
                System.out.println(x);
            }
            System.out.println(x);  // x is accessible outside the loop
        }
    }

    Output:

    0
    1
    2
    3
    4

    Loop Variable Scope with Overlapping Names

    In Java, you cannot declare two variables with the same name within the same scope. However, in languages like C++, it’s possible to have the same variable name in nested scopes, which is not allowed in Java.

    Incorrect Example in Java (compilation error):

    class Test {
        public static void main(String[] args) {
            int a = 5;
            for (int a = 0; a < 5; a++) {  // Error: Variable 'a' is already defined
                System.out.println(a);
            }
        }
    }

    Output:

    Error: variable 'a' is already defined

    Valid Example with Loop Variable Declaration After Loop

    To avoid such errors, you can declare a variable outside the loop and use it after the loop finishes.

    Example:

    class Test {
        public static void main(String[] args) {
            for (int i = 1; i <= 10; i++) {
                System.out.println(i);  // Loop variable i
            }
    
            int i = 20;  // Declare i after the loop
            System.out.println(i);  // Access new i outside the loop
        }
    }

    Output:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    20
  • Input/Output in Java

    How to Take Input from User in Java

    Java provides multiple ways to take input from users through its I/O (Input/Output) package. These streams facilitate the reading of characters, data types, and objects from input devices such as keyboards or files. The most common ways to capture user input in Java are through the BufferedReader class and the Scanner class.

    Methods to Take Input in Java

    There are two primary ways to get input from the user or a file in Java:

    1. Using BufferedReader Class
    2. Using Scanner Class

    1. Using BufferedReader Class to Take Input in Java

    The BufferedReader class is part of Java’s I/O package and is used for reading streams of characters. The readLine() method of this class reads input as a string. InputStreamReader is often used in conjunction with BufferedReader to convert byte streams into character streams, enabling character-based input reading.

    Note: BufferedReader can throw checked exceptions, which need to be handled using try-catch blocks or by declaring them with throws.

    Example of Taking Input Using BufferedReader:

    import java.io.*;
    
    public class InputExample {
        public static void main(String[] args) throws IOException {
            // Creating a BufferedReader object
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
            // Reading string input
            System.out.println("Enter a string:");
            String str = reader.readLine();
    
            // Reading integer input
            System.out.println("Enter an integer:");
            int num = Integer.parseInt(reader.readLine());
    
            // Output the values
            System.out.println("Entered String: " + str);
            System.out.println("Entered Integer: " + num);
        }
    }

    Output:

    Enter a string:
    John Doe
    Enter an integer:
    123
    Entered String: John Doe
    Entered Integer: 123

    Alternative Example of BufferedReader Input:

    import java.io.*;
    
    public class Example {
        public static void main(String[] args) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            try {
                System.out.println("Enter your name:");
                String name = reader.readLine();  // Reading string input
                System.out.println("Name: " + name);
            } catch (IOException e) {
                System.out.println("An error occurred: " + e.getMessage());
            }
        }
    }

    Sample Output:

    Enter your name:
    John
    Name: John

    2. Using Scanner Class for Taking Input in Java

    The Scanner class is an advanced and user-friendly input class that is part of Java’s util package. It simplifies input handling by providing various methods like nextInt()nextFloat()next(), and nextLine(). These methods allow you to directly capture input without explicit parsing.

    Advantages of Scanner:

    • Easier to use than BufferedReader.
    • Supports multiple data types (integers, floats, strings, etc.) directly.
    • No need for throws declarations as no checked exceptions are thrown.
    • Provides methods to read formatted input easily.

    Example of Taking Input Using Scanner:

    import java.util.Scanner;
    
    class Main {
        public static void main(String[] args) {
            // Create Scanner object
            Scanner sc = new Scanner(System.in);
    
            // Input a String (single word)
            String word = sc.next();
            System.out.println("Entered word: " + word);
    
            // Input a String (full sentence)
            sc.nextLine();  // Clear the buffer
            String sentence = sc.nextLine();
            System.out.println("Entered sentence: " + sentence);
    
            // Input an Integer
            int num = sc.nextInt();
            System.out.println("Entered Integer: " + num);
    
            // Input a floating-point number
            float f = sc.nextFloat();
            System.out.println("Entered Float: " + f);
        }
    }

    Output:

    John
    Hello World
    123
    45.67
    Entered word: John
    Entered sentence: Hello World
    Entered Integer: 123
    Entered Float: 45.67

    Another Example:

    import java.util.Scanner;
    
    class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
    
            System.out.println("Enter your name:");
            String name = sc.nextLine();
    
            System.out.println("Enter your roll number:");
            int rollNo = sc.nextInt();
    
            System.out.println("Enter your marks:");
            float marks = sc.nextFloat();
    
            // Output the entered data
            System.out.println("Name: " + name);
            System.out.println("Roll Number: " + rollNo);
            System.out.println("Marks: " + marks);
        }
    }

    Output:

    Enter your name:
    Alice
    Enter your roll number:
    10
    Enter your marks:
    89.5
    Name: Alice
    Roll Number: 10
    Marks: 89.5
    Differences Between BufferedReader and Scanner

    1. BufferedReader is a basic way to read input, typically used for reading streams of characters. It is faster than Scanner as it doesn’t perform any post-processing or parsing.
    2. Scanner is more user-friendly for simple input, especially when you need to read different data types. However, Scanner is slower because it performs input parsing internally (like nextInt(), nextFloat()).
    3. BufferedReader allows you to specify the size of the input stream to be read, making it more flexible when handling large input.
    4. BufferedReader is synchronized, making it suitable for multi-threaded applications, while Scanner is not.
    5. Scanner is typically preferred for smaller inputs due to its simplicity, while BufferedReader is favored for larger inputs due to better performance.

    Scanner Class in Java

    The Scanner class in Java is part of the java.util package and is used to obtain input from the user, including primitive data types like intdouble, and boolean, as well as strings.

    While the Scanner class is the simplest way to read input, it’s not the most efficient when performance is critical, such as in competitive programming, due to additional overhead.

    Input Types in Java Scanner

    The Scanner class can take various types of input from the user. Some of the commonly used methods for extracting data from an input stream are listed below:

    MethodDescription
    nextBoolean()Reads a Boolean value
    nextByte()Reads a Byte value
    nextDouble()Reads a Double value
    nextFloat()Reads a Float value
    nextInt()Reads an Integer value
    nextLine()Reads an entire line as a String
    nextLong()Reads a Long value
    nextShort()Reads a Short value

    Example 1: Reading Data of Various Types

    Below is a sample code that demonstrates how to read different types of data using the Scanner class.

    // Java program to read data of various types using Scanner class.
    import java.util.Scanner;
    
    public class ScannerDemo1 {
        public static void main(String[] args) {
            // Creating a Scanner object for input
            Scanner sc = new Scanner(System.in);
    
            // Reading a String input
            String name = sc.nextLine();
    
            // Reading a Character input
            char gender = sc.next().charAt(0);
    
            // Reading numerical data
            int age = sc.nextInt();
            long mobileNo = sc.nextLong();
            double cgpa = sc.nextDouble();
    
            // Outputting the values to check input
            System.out.println("Name: " + name);
            System.out.println("Gender: " + gender);
            System.out.println("Age: " + age);
            System.out.println("Mobile Number: " + mobileNo);
            System.out.println("CGPA: " + cgpa);
        }
    }

    Input:

    Alice
    F
    25
    9876543210
    8.9

    Output:

    Name: Alice
    Gender: F
    Age: 25
    Mobile Number: 9876543210
    CGPA: 8.9
    Checking Input Type with hasNextXYZ() Methods

    In some cases, we need to verify the type of the next input or whether the input has ended (e.g., when encountering the EOF marker). The hasNextXYZ() methods allow us to check if the next token is of the desired type. Here, XYZ represents the data type of interest.

    For instance, we can check for an integer using hasNextInt() or a string using hasNextLine(). Similarly, to check for a single character, we can use hasNext().charAt(0).

    Example 2: Calculating the Mean of Numbers

    // Java program to read values using Scanner and calculate their mean.
    import java.util.Scanner;
    
    public class ScannerDemo2 {
        public static void main(String[] args) {
            // Initialize Scanner object
            Scanner sc = new Scanner(System.in);
    
            // Initialize sum and count variables
            int sum = 0, count = 0;
    
            // Read integers until non-integer input is encountered
            while (sc.hasNextInt()) {
                int num = sc.nextInt();
                sum += num;
                count++;
            }
    
            // Calculate and print the mean
            if (count > 0) {
                int mean = sum / count;
                System.out.println("Mean: " + mean);
            } else {
                System.out.println("No integers were input. Mean cannot be calculated.");
            }
        }
    }

    Input:

    1 2 3 4 5

    Output:

    Mean: 3

    Key Points About the Scanner Class

    1. Creating a Scanner Object: To create a Scanner object, we usually pass the predefined System.in object, which represents standard input. We can also pass a File object to read input from a file.
    2. Reading Numerical Values: For each primitive data type, there is a corresponding nextXYZ() method to read its value. For example, nextShort() reads a short value, and nextInt() reads an int.
    3. Reading Strings: To read strings, we use nextLine(). This method reads the entire line until a newline character is encountered.
    4. Reading a Single Character: To read a single character, we can use next().charAt(0). The next() method reads the next token (a word or symbol), and charAt(0) returns the first character of that token.
    5. How Scanner Reads Input: The Scanner class reads an entire line and divides it into tokens. Each token represents a meaningful piece of the input. For example, if the input string is “Hello world”, the Scanner object will treat “Hello” and “world” as two separate tokens, and we can iterate over these tokens using its various methods.

    Ways to read input from console in Java

    In Java, there are several ways to read input from the user in the command-line environment. Here are five methods:

    1. Using BufferedReader Class

    The BufferedReader class is the traditional way to take input, introduced in JDK 1.0. It wraps the standard input stream (System.in) in an InputStreamReader, which is further wrapped in a BufferedReader for efficient reading of input.

    Key Points:

    • Input is buffered for performance.
    • Syntax can be a bit more complex compared to newer methods.

    Example:

    // Java program to demonstrate BufferedReader
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    public class Test {
        public static void main(String[] args) throws IOException {
            // Using BufferedReader to get input
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
            // Reading a string input
            String name = reader.readLine();
    
            // Printing the input
            System.out.println(name);
        }
    }

    Input:

    John

    Output:

    John
    2. Using Scanner Class

    The Scanner class, introduced in JDK 1.5, is one of the most commonly used methods to read input. It can parse primitive types and strings using regular expressions.

    Advantages:

    • Simplifies reading primitive types like intfloat, and more.
    • Regular expressions can be used to tokenize input.

    Example:

    import java.util.Scanner;
    
    public class InputExample {
    
        public static void main(String[] args) {
            // Create Scanner object
            Scanner scn = new Scanner(System.in);
    
            // Read a single word as a string
            System.out.println("Enter a word:");
            String word = scn.next();
    
            // Read a full line as a string
            System.out.println("Enter a sentence:");
            scn.nextLine(); // consume the leftover newline
            String sentence = scn.nextLine();
    
            // Read an integer
            System.out.println("Enter an integer:");
            int number = scn.nextInt();
    
            // Read a float value
            System.out.println("Enter a floating point number:");
            float decimal = scn.nextFloat();
    
            // Display the inputs
            System.out.println("Word: " + word);
            System.out.println("Sentence: " + sentence);
            System.out.println("Integer: "

    Input:

    Alice
    25
    4.5

    Output:

    You entered string: Alice
    You entered integer: 25
    You entered float: 4.5
    3. Using Console Class

    Introduced in JDK 1.6, the Console class is useful for reading input from the command line, especially for secure inputs like passwords (where input isn’t displayed). However, it may not work in non-interactive environments like IDEs.

    Advantages:

    • Can hide input (useful for password entry).
    • Supports formatted input and output.

    Example:

    // Java program to demonstrate Console class
    public class Sample {
        public static void main(String[] args) {
            // Using Console to get input
            String name = System.console().readLine();
            System.out.println("You entered string: " + name);
        }
    }

    Input:

    Michael

    Output:

    You entered string: Michael
    4. Using Command-Line Arguments

    This method uses the command-line arguments passed to the program at runtime. The arguments are stored as strings in the args[] array, and can be converted to other data types using methods like Integer.parseInt().

    Example:

    // Program to demonstrate command-line arguments
    class Hello {
        public static void main(String[] args) {
            // Check if arguments were passed
            if (args.length > 0) {
                System.out.println("The command line arguments are:");
                // Loop through the args array
                for (String val : args)
                    System.out.println(val);
            } else {
                System.out.println("No command line arguments found.");
            }
        }
    }

    Command Line Arguments:

    java Hello John Doe

    Output:

    The command line arguments are:
    John
    Doe
    5. Using DataInputStream Class

    The DataInputStream class allows reading primitive data types and strings from an input stream in a machine-independent way. This class is useful when working with binary input/output, and it was introduced in JDK 1.0.

    Key Points:

    • Reads binary data in a machine-independent format.
    • Often used with DataOutputStream for consistent data handling.

    Example:

    // Java program to demonstrate DataInputStream
    import java.io.*;
    
    public class Main {
        public static void main(String[] args) throws IOException {
            DataInputStream reader = new DataInputStream(System.in);
    
            // Reading an integer input
            System.out.print("Enter an integer: ");
            int inputInt = Integer.parseInt(reader.readLine());
    
            // Reading a string input
            System.out.print("Enter a string: ");
            String inputString = reader.readLine();
    
            // Output the input values
            System.out.println("You entered integer: " + inputInt);
            System.out.println("You entered string: " + inputString);
        }
    }

    Input:

    Enter an integer: 30
    Enter a string: Java Programming

    Output:

    You entered integer: 30
    You entered string: Java Programming

    Java System.out.println()

    The System.out.println() method is used in Java to print a message or value to the console. It is a commonly used function that prints any argument passed to it, followed by a new line.

    Breakdown of System.out.println()

    The statement can be split into three parts for better understanding:

    1. System: This is a final class from the java.lang package.
    2. out: A static member of the System class, which is an instance of the PrintStream class.
    3. println(): A method of the PrintStream class that prints the passed argument and adds a newline character at the end. It’s an enhanced version of print() that automatically moves the cursor to the next line.

    Syntax:

    System.out.println(parameter);

    Example of System.out.println()

    Example : Basic Output

    public class Example {
        public static void main(String[] args) {
            System.out.println("Hello");
            System.out.println("World");
            System.out.println("Java Programming");
        }
    }

    Output:

    Hello
    World
    Java Programming
    Java’s Other Standard Streams
    • System.in: The standard input stream used for reading input from the keyboard.
    • System.err: The standard error stream used to display error messages.

    Example:

    System.err.print("This is an error message");
    Overloads of println() Method

    Java supports method overloading, allowing multiple methods with the same name but different parameter types. PrintStream provides various overloads of the println() method for different data types.

    Example of Overloaded println() Methods

    public class Example {
        public static void main(String[] args) {
            int num = 15;
            char letter = 'A';
            String text = "Java";
            double decimal = 25.78;
            float floatNum = 10.5f;
            boolean flag = true;
    
            // Various overloaded versions of println()
            System.out.println(); // Prints an empty line
            System.out.println(num);
            System.out.println(letter);
            System.out.println(text);
            System.out.println(decimal);
            System.out.println(floatNum);
            System.out.println(flag);
        }
    }

    Output:

    15
    A
    Java
    25.78
    10.5
    true
    Difference Between System.out.print() and System.out.println()
    • System.out.print(): Prints the provided text or value on the console and keeps the cursor on the same line.
    • System.out.println(): Prints the provided text or value, and moves the cursor to the next line.

    Example:

    public class Example {
        public static void main(String[] args) {
            System.out.println("Using print():");
    
            // Using print()
            System.out.print("Hello ");
            System.out.print("World ");
            System.out.print("Java");
    
            System.out.println(); // Moving to the next line
            System.out.println("Using println():");
    
            // Using println()
            System.out.println("Hello");
            System.out.println("World");
            System.out.println("Java");
        }
    }

    Output:

    Using print():
    Hello World Java
    Using println():
    Hello
    World
    Java

    Formatted Output in Java using printf()

    In programming, it is often necessary to display output in a specific format. Java’s printf() method, similar to the C language’s printf, allows formatting of output using format specifiers. In this article, we’ll cover different ways to format output in Java using printf().

    Formatting Using printf()

    printf() uses format specifiers to format different data types. The commonly used data types for formatting are:

    1. Number Formatting
    2. Decimal Number Formatting
    3. Boolean Formatting
    4. Character Formatting
    5. String Formatting
    6. Date and Time Formatting

    1. Number Formatting

    For formatting integers (like intlong), the format specifier used is %d.

    Example:

    public class Example {
        public static void main(String[] args) {
            int number = 10000;
    
            // Format with commas separating thousands
            System.out.printf("%,d%n", number);
        }
    }

    Output:

    10,000

    2. Decimal Number Formatting

    To format decimal numbers, we use the %f specifier.

    Example:

    public class Example {
        public static void main(String[] args) {
            double pi = 3.14159265359;
    
            // Formatting decimal numbers
            System.out.printf("%f\n", pi);
            System.out.printf("%5.3f\n", pi);
            System.out.printf("%5.2f\n", pi);
        }
    }

    Output:

    3.141593
    3.142
     3.14

    3. Boolean Formatting

    Boolean values can be formatted using %b or %B.

    Example:

    public class Example {
        public static void main(String[] args) {
            boolean boolTrue = true;
            boolean boolFalse = false;
            Integer nullValue = null;
    
            System.out.printf("%b\n", boolTrue);  // true
            System.out.printf("%B\n", boolTrue);  // TRUE
            System.out.printf("%b\n", boolFalse); // false
            System.out.printf("%B\n", nullValue); // FALSE
        }
    }

    Output:

    true
    TRUE
    false
    FALSE

    4. Character Formatting

    Character formatting is done using the %c or %C specifiers.

    Example:

    public class Example {
        public static void main(String[] args) {
            char character = 'a';
    
            System.out.printf("%c\n", character); // a
            System.out.printf("%C\n", character); // A (uppercase)
        }
    }

    Output:

    a
    A

    5. String Formatting

    Strings are formatted using %s or %S.

    Example:

    public class Example {
        public static void main(String[] args) {
            String text = "java programming";
    
            System.out.printf("%s\n", text);  // java programming
            System.out.printf("%S\n", text);  // JAVA PROGRAMMING
        }
    }

    Output:

    java programming
    JAVA PROGRAMMING

    6. Date and Time Formatting

    Formatting date and time is more complex and requires specific knowledge of format specifiers such as %tT%tH%tM, etc.

    Example:

    import java.util.Date;
    
    public class Example {
        public static void main(String[] args) {
            Date currentTime = new Date();
    
            System.out.printf("Current Time: %tT\n", currentTime); // Full time format
            System.out.printf("Hours: %tH  Minutes: %tM Seconds: %tS\n",
                              currentTime, currentTime, currentTime); // Individual components
    
            // Time with AM/PM, milliseconds, nanoseconds, and time zone
            System.out.printf("%1$tH:%1$tM:%1$tS %1$tp %1$tL %1$tN %1$tz%n", currentTime);
        }
    }

    Output:

    Current Time: 11:32:36
    Hours: 11  Minutes: 32  Seconds: 36
    11:32:36 am 198 198000000 +0000
    Other Methods for Formatting

    1. Decimal Formatting using DecimalFormat

    DecimalFormat can be used to format numbers with various patterns.

    Example:

    import java.text.DecimalFormat;
    
    public class DecimalFormatting {
        public static void main(String[] args) {
            double num = 123.4567;
    
            // Formatting without fraction part
            DecimalFormat df = new DecimalFormat("####");
            System.out.println("Without fraction part: " + df.format(num));
    
            // Formatting to 2 decimal places
            df = new DecimalFormat("#.##");
            System.out.println("Formatted to 2 decimal places: " + df.format(num));
    
            // Formatting with appended zeroes
            df = new DecimalFormat("#.000000");
            System.out.println("With appended zeroes: " + df.format(num));
    
            // Formatting with leading zeroes
            df = new DecimalFormat("00000.00");
            System.out.println("With leading zeroes: " + df.format(num));
    
            // Formatting currency
            double income = 23456.789;
            df = new DecimalFormat("$###,###.##");
            System.out.println("Formatted income: " + df.format(income));
        }
    }

    Output:

    Without fraction part: 123
    Formatted to 2 decimal places: 123.46
    With appended zeroes: 123.456700
    With leading zeroes: 00123.46
    Formatted income: $23,456.79

    2. Formatting Dates using SimpleDateFormat

    SimpleDateFormat allows date formatting based on custom patterns.

    Example:

    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class DateFormatting {
        public static void main(String[] args) {
            // Formatting date to 'dd-MM-yyyy'
            SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
            String formattedDate = sdf.format(new Date());
            System.out.println("Formatted Date: " + formattedDate);
    
            // Parsing a string date
            String dateStr = "02/18/1995";
            sdf = new SimpleDateFormat("MM/dd/yyyy");
            try {
                Date date = sdf.parse(dateStr);
                System.out.println("Parsed Date: " + date);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    Output:

    Formatted Date: 03-10-2024
    Parsed Date: Sat Feb 18 00:00:00 UTC 1995

    3. Static Variables

    Static variables are shared across all instances of a class and are declared with the static keyword. Only one copy of a static variable exists, regardless of how many objects are created.

    // Example of static variables
    public class StaticVariableExample {
        public static String company = "TechCorp";  // Static variable
    
        public static void main(String[] args) {
            System.out.println("Company: " + StaticVariableExample.company);  // Accessing without object
        }
    }

    Output:

    Company: TechCorp

    Java Variables

    In Java, the scope of a variable refers to the region in the code where the variable is accessible. Java has lexical (static) scoping, meaning the scope of a variable is determined at compile time and is not dependent on the function call stack. The scope rules in Java can be broadly classified into three categories based on where the variables are declared.

    1. Member Variables (Class-Level Scope)
    2. Local Variables (Method-Level Scope)
    3. Block Variables (Loop or Block-Level Scope)

    1. Member Variables (Class-Level Scope)

    Member variables are declared inside a class but outside any method, constructor, or block. They can be accessed anywhere within the class and can have different access levels (e.g., publicprivateprotected, or default). Access to member variables outside the class depends on the access modifier used.

    Example:

    public class Test {
        // Member variables
        int a;                  // Default access modifier
        private String b;        // Private member variable
        char c;                  // Default access modifier
    
        void method1() {
            // Member variables can be accessed here
            System.out.println(a);
            System.out.println(b);
        }
    
        int method2() {
            return a;
        }
    }
    • Public: Accessible within the class, in subclasses, and outside the class.
    • Protected: Accessible within the class and in subclasses but not outside the package.
    • Default (no modifier): Accessible within the same package but not outside it.
    • Private: Only accessible within the class.

    2. Local Variables (Method-Level Scope)

    Local variables are declared inside a method or constructor and are only accessible within that method. They must be initialized before use, and their lifetime is limited to the method’s execution. Once the method finishes, local variables are destroyed.

    Example:

    public class Test {
        void method1() {
            // Local variable
            int x = 10;
            System.out.println(x);  // Accessible inside the method
        }
    
        public static void main(String[] args) {
            Test t = new Test();
            t.method1();
        }
    }

    Local variables do not retain their values once the method completes, and they are recreated each time the method is invoked.

    3. Block Variables (Loop or Block-Level Scope)

    Variables declared inside a block (within curly braces {}) are only accessible within that block. Once the block is exited, these variables are out of scope and cannot be accessed. This applies to variables declared inside loops or conditionals.

    Example of Block-Level Scope:

    public class Test {
        public static void main(String[] args) {
            {
                int x = 10;  // x is only accessible inside this block
                System.out.println(x);
            }
    
            // Uncommenting the following line will cause an error
            // System.out.println(x);  // x is out of scope here
        }
    }
    Loop Variables (Block Scope)

    Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.

    Example:

    class Test {
        public static void main(String[] args) {
            for (int x = 0; x < 4; x++) {
                System.out.println(x);  // x is accessible inside the loop
            }
    
            // Uncommenting the following line will result in an error
            // System.out.println(x);  // x is out of scope here
        }
    }

    If you need to access a loop variable outside the loop, declare it before the loop:

    class Test {
        public static void main(String[] args) {
            int x;
            for (x = 0; x < 4; x++) {
                System.out.println(x);
            }
            System.out.println(x);  // x is accessible outside the loop
        }
    }

    Output:

    0
    1
    2
    3
    4
    Loop Variable Scope with Overlapping Names

    In Java, you cannot declare two variables with the same name within the same scope. However, in languages like C++, it’s possible to have the same variable name in nested scopes, which is not allowed in Java.

    Incorrect Example in Java (compilation error):

    class Test {
        public static void main(String[] args) {
            int a = 5;
            for (int a = 0; a < 5; a++) {  // Error: Variable 'a' is already defined
                System.out.println(a);
            }
        }
    }

    Output:

    Error: variable 'a' is already defined
    Valid Example with Loop Variable Declaration After Loop

    To avoid such errors, you can declare a variable outside the loop and use it after the loop finishes.

    Example:

    class Test {
        public static void main(String[] args) {
            for (int i = 1; i <= 10; i++) {
                System.out.println(i);  // Loop variable i
            }
    
            int i = 20;  // Declare i after the loop
            System.out.println(i);  // Access new i outside the loop
        }
    }

    Output:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    20
  • Basic Concepts of Java

    Java Basic Syntax

    Java is an object-oriented programming language, which means that it consists of objects that interact with each other through method calls to perform various tasks. Here’s an overview of some essential concepts in Java:

    Basic Terminologies in Java:

    1. Class:A class is a blueprint for objects. It defines a logical template that shares common properties and methods.

    2. ObjectAn object is an instance of a class. It represents an entity with a behavior and state.

    3. Method: A method defines the behavior of an object.

    4. Instance Variables: Each object has its own unique set of instance variables. These variables represent the state of an object, defined by the values assigned to them.

    Example: Compiling and Running a Java Program in a Console

    import java.util.*;
    public class Main {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }

    Output:

    Hello, World!

    5. Comments in Java: There are three types of comments in Java:

    • Single-line Comment:
    // This is a single-line comment
    • Multi-line Comment:
    /*
        This is a multi-line comment
    */
    • Documentation Comment:
    /** This is a documentation comment */

    6. Source File Name: The source file name should exactly match the public class name with the extension .java. If there is no public class, the file name can differ.

    Example:

    GFG.java  // valid
    gfg.java  // invalid if public class is GFG

    7.  Case Sensitivity:
    Java is case-sensitive, meaning identifiers like ABAbaB, and ab are considered different.

    Example:

    System.out.println("Hello");  // valid
    system.out.println("Hello");  // invalid

    8. Class Names: The first letter of a class name should be uppercase.If multiple words are used, each word should start with an uppercase letter.

    Example:

    class MyClass      // valid
    class 1Program     // invalid
    class My1Program   // valid
    class $Program     // valid but discouraged

    9. Main Method: The main() method is the entry point of every Java program:

    public static void main(String[] args) {
        // program logic
    }

    10. Method Names: Method names should start with a lowercase letter.If multiple words are used, the first letter of each word (after the first one) should be uppercase.
    Example:

    public void calculateSum() // valid

    11. Identifiers in Java: Identifiers are names given to classes, methods, variables, etc. They must follow certain rules:Can begin with a letter, underscore (_), or currency symbol. Subsequent characters can be letters, digits, or underscores. Java keywords cannot be used as identifiers. Legal identifiers: myVar, hello_world, $amount.
    Illegal identifiers: 1Var, -amount.

    12. White Spaces in Java: Blank lines, spaces, and comments are ignored by the Java compiler.

    13. Access Modifiers: Java provides access control to classes and methods through access modifiers:

    Access ModifierWithin ClassWithin PackageOutside Package by SubclassOutside Package
    PrivateYesNoNoNo
    DefaultYesYesNoNo
    ProtectedYesYesYesNo
    PublicYesYesYesYes

    14. Java Keywords:
    Keywords in Java have predefined meanings and cannot be used as identifiers. Examples include classinterfacevoidintpublicstatic, etc.

    Java Hello World Program

    Java is one of the most popular and widely-used programming languages, known for its speed, reliability, and security. Java applications can be found everywhere—from desktop software to web applications, scientific supercomputers to gaming consoles, and mobile phones to the Internet. In this guide, we’ll explore how to write a simple Java program.

    Steps to Implement a Java Program

    To implement a Java application, follow these key steps:

    • Creating the Program
    • Compiling the Program
    • Running the Program

    If you’re looking to dive deeper into Java and gain a strong understanding of the entire development process, consider enrolling in a structured Java programming course. These courses provide hands-on experience and cover everything from basic to advanced topics, allowing you to develop efficient and scalable applications.

    Example of a Simple Java Program

    public class Main {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }

    Output:

    Hello, World!

    Primitive data type vs. Object data type in Java with Examples

    Java is known as a statically and strongly typed language because all data types (such as integers, characters, etc.) are predefined. Additionally, every constant or variable must be explicitly declared with a data type.

    Data Types in Java

    Java’s data types vary in size and in the values they can store. These types are categorized into two main groups:

    • Primitive Data Types: Includes booleancharintshortbytelongfloat, and double. For example, Boolean is a wrapper class for the primitive boolean type.
    • Non-Primitive Data Types (Reference types): Examples include StringArray, and more.

    Effectively understanding and using these data types is crucial for writing efficient and error-free Java code. If you’re aiming to become proficient in Java, it’s worth exploring detailed learning materials or taking courses to deepen your knowledge of data types and other core Java concepts.

    Primitive Data Types

    Primitive data types represent basic values and lack any special properties. Java supports eight primitive data types, as shown in the table below:

    TypeDescriptionDefaultSizeExample LiteralsRange
    1. booleanRepresents true or falsefalse8 bitstruefalseN/A
    byte8-bit signed integer08 bits(none)-128 to 127
    char16-bit Unicode character\u000016 bits'a''\u0041''β'0 to 65,535
    short16-bit signed integer016 bits(none)-32,768 to 32,767
    int32-bit signed integer032 bits-212-2,147,483,648 to 2,147,483,647
    long64-bit signed integer064 bits-2L0L1L-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
    float32-bit floating-point0.032 bits1.23e10f-1.23e-100fUp to 7 decimal digits
    double64-bit floating-point0.064 bits1.2345e300d1e1dUp to 16 decimal digits

    Below is a detailed breakdown of each data type:

    1. boolean Data Type: Represents logical values (true or false). Actual size depends on the virtual machine implementation.

    Syntax:

    boolean isAvailable;

    2. byte Data Type: An 8-bit signed integer, often used to save memory when working with large arrays.

    Syntax:

    byte age;

    3. short Data Type: A 16-bit signed integer. This is similar to byte, but used when larger ranges are required.

    Syntax:

    short population;

    4. int Data Type: A 32-bit signed integer and one of the most commonly used data types for numerical values.

    Syntax:

    int salary;

    5. long Data Type: A 64-bit signed integer, suitable for larger numerical values.

    Syntax:

    long distance;

    6. float Data Type: A 32-bit single-precision floating-point, typically used when saving memory is a priority for large floating-point arrays.

    Syntax:

    long distance;

    7. double Data Type: A 64-bit double-precision floating-point, typically the default choice for decimal values.

    Syntax

    double price;

    8. char Data Type: A 16-bit Unicode character. Java uses the Unicode system rather than ASCII, which allows it to represent a wide range of characters.

    Syntax:

    char initial;
    Non-Primitive (Reference) Data Types

    Non-Primitive data types store references to memory locations where data is stored. These include strings, arrays, and objects.

    1. String: A string is a sequence of characters. In Java, strings are objects, not primitive data types. They can be declared either with or without the new keyword.

    Example:

    String message = "Hello, World!";

    2. Class: A class in Java is a blueprint used to create objects. A class can contain fields (attributes) and methods to describe the behavior of the objects it represents.

    3. Object: An object is an instance of a class, representing real-world entities with states (fields) and behaviors (methods).

    4. Interface: An interface defines a set of methods that a class must implement. Interfaces provide a way to achieve abstraction in Java.

    5. Array: Arrays are used to store multiple values of the same type in a single variable. Java arrays are objects, and their size is fixed upon creation.

    Example:

    int[] numbers = {1, 2, 3, 4, 5};

    Java Identifiers

    In Java, identifiers are used to name various entities like classes, methods, variables, or labels. These names help in uniquely identifying different elements within a Java program.

    Example of Java Identifiers

    public class Test {
        public static void main(String[] args) {
            int a = 20;
        }
    }

    In the above code, we have 5 identifiers:

    • Test: This is the class name.
    • main: This is the method name.
    • String: This is a predefined class name.
    • args: This is a variable name.
    • a: This is also a variable name.
    Rules for Defining Java Identifiers

    There are specific rules for defining valid Java identifiers. Violating these rules will lead to a compile-time error. These rules are also similar in other programming languages like C and C++.

    1. Allowed Characters: Identifiers can contain letters (both uppercase and lowercase), digits ([0-9]), the dollar sign ($), and the underscore (_). Special characters such as @, %, or & are not allowed.
    Example: “my@name” is not a valid identifier because @ is not allowed.
    2. Starting Character: Identifiers cannot begin with a digit.
    Example: “123variable” is invalid.
    Case Sensitivity: Java is case-sensitive, so identifiers like MyVariable and myvariable are treated as distinct.
    3. Length: There is no restriction on the length of an identifier, but it’s recommended to keep it between 4 and 15 characters for readability.
    Reserved Words: Keywords or reserved words in Java cannot be used as identifiers.
    Example: int while = 20; is invalid because while is a reserved keyword in Java.

    Examples of Valid Identifiers:

    • MyVariable
    • MYVARIABLE
    • myvariable
    • x
    • i
    • x1
    • i1
    • _myvariable
    • $myvariable
    • sum_of_array
    • name123
    Examples of Invalid Identifiers:
    • My Variable // Contains a space.
    • 123name // Begins with a digit.
    • a+c // Contains a special character (+).
    • variable-2 // Contains a hyphen (-).
    • sum_&_difference // Contains an ampersand (&).
    Reserved Words in Java

    Programming languages reserve certain words to represent built-in functionalities. These are known as reserved words, and in Java, they fall into two categories: keywords (50) and literals (3). Keywords represent functions, while literals represent values. Identifiers are utilized by compilers during various phases of program analysis like lexical, syntax, and semantic analysis.

    Here are some reserved words in Java:

    KeywordKeywordKeywordKeyword
    abstractdefaultpackagesuper
    continuegotoprivatecase
    forpublicclassenum
    protectedtrybyteextends
    transientbooleandoubleinterface
    assertdoimplementsshort
    staticifstrictfpswitch
    throwsbreakelsecatch
    returnvoidlongfinally
    charfinalintsynchronized
    volatilefloatnativethis
    constthrowinstanceOfwhile

    These reserved words cannot be used as identifiers.

    int myVariable = 10;
    String $myString = "Hello";
    double _myDouble = 20.5;

    Operators in Java

    Java Operators: A Comprehensive Guide

    Java provides various operators that are categorized based on their functionality, making it easier to perform tasks like arithmetic operations, logical comparisons, and bitwise manipulations. In this guide, we will explore the different types of Java operators and their uses.

    What are Java Operators?

    Operators in Java are symbols that trigger specific operations on operands. They simplify complex tasks such as arithmetic operations, logical evaluations, and bitwise manipulations, enhancing the efficiency of the code.

    Types of Java Operators

    There are several types of operators in Java, each serving a unique purpose:

    1. Arithmetic Operators
    2. Unary Operators
    3. Assignment Operators
    4. Relational Operators
    5. Logical Operators
    6. Ternary Operator
    7. Bitwise Operators
    8. Shift Operators
    9. instanceof Operator

    1. Arithmetic Operators: Arithmetic operators perform basic mathematical operations such as addition, subtraction, multiplication, and division.

    • * : Multiplication
    • / : Division
    • % : Modulus (remainder)
    • + : Addition
    •  : Subtraction

    Example:

    public class ArithmeticOperators {
        public static void main(String[] args) {
            int x = 15;
            int y = 4;
    
            System.out.println("x + y = " + (x + y));
            System.out.println("x - y = " + (x - y));
            System.out.println("x * y = " + (x * y));
            System.out.println("x / y = " + (x / y));
            System.out.println("x % y = " + (x % y));
        }
    }

    Output:

    x + y = 19
    x - y = 11
    x * y = 60
    x / y = 3
    x % y = 3

    2. Unary Operators: Unary operators operate on a single operand. They are used to increment, decrement, or negate a value.

    • - : Unary minus (negates a value)
    • + : Unary plus (retains the positive value)
    • ++ : Increment operator (increases the value by 1)
    • -- : Decrement operator (decreases the value by 1)
    • ! : Logical NOT operator (inverts a boolean value)

    Example:

    public class UnaryOperators {
        public static void main(String[] args) {
            int a = 5;
            int b = 5;
    
            System.out.println("Post-Increment: " + (a++));
            System.out.println("Pre-Increment: " + (++a));
            System.out.println("Post-Decrement: " + (b--));
            System.out.println("Pre-Decrement: " + (--b));
        }
    }

    Output:

    Post-Increment: 5
    Pre-Increment: 7
    Post-Decrement: 5
    Pre-Decrement: 3

    3. Assignment Operators: Assignment operators assign values to variables. You can combine them with other operations to simplify code, such as += or -=.

    • = : Assign
    • +=-=*=/=%= : Compound assignment operators

    Example:

    public class AssignmentOperators {
        public static void main(String[] args) {
            int a = 10;
            a += 5;
            System.out.println("a after += 5: " + a);
            a *= 2;
            System.out.println("a after *= 2: " + a);
        }
    }

    Output:

    a after += 5: 15
    a after *= 2: 30

    4. Relational Operators: Relational operators compare two values and return a boolean result (true or false).

    • == : Equal to
    • != : Not equal to
    • < : Less than
    • > : Greater than
    • <= : Less than or equal to
    • >= : Greater than or equal to

    Example:

    public class RelationalOperators {
        public static void main(String[] args) {
            int a = 10, b = 5;
            System.out.println("a > b: " + (a > b));
            System.out.println("a == b: " + (a == b));
        }
    }

    5. Logical Operators: Logical operators are used to combine multiple boolean expressions.

    • && : Logical AND
    • || : Logical OR
    • ! : Logical NOT

    Example:

    public class LogicalOperators {
        public static void main(String[] args) {
            boolean x = true, y = false;
            System.out.println("x && y: " + (x && y));
            System.out.println("x || y: " + (x || y));
        }
    }

    Output:

    x && y: false
    x || y: true

    6. Ternary Operator: The ternary operator is a shorthand for an if-else statement.

    Syntax: condition ? value_if_true : value_if_false

    Example:

    public class TernaryOperator {
        public static void main(String[] args) {
            int a = 10, b = 20;
            int max = (a > b) ? a : b;
            System.out.println("Max value: " + max);
        }
    }

    Output:

    Max value: 20

    7. Bitwise Operators: Bitwise operators operate on binary representations of integers.

    • & : Bitwise AND
    • | : Bitwise OR
    • ^ : Bitwise XOR
    • ~ : Bitwise NOT

    Example:

    public class BitwiseOperators {
        public static void main(String[] args) {
            int a = 5; // 0101 in binary
            int b = 3; // 0011 in binary
            System.out.println("a & b: " + (a & b)); // AND operation
            System.out.println("a | b: " + (a | b)); // OR operation
        }
    }

    Output:

    a & b: 1
    a | b: 7

    8. Shift Operators: Shift operators shift bits left or right.

    • << : Left shift
    • >> : Right shift
    • >>> : Unsigned right shift

    Example:

    public class ShiftOperators {
        public static void main(String[] args) {
            int a = 8;
            System.out.println("Left Shift: " + (a << 1));
            System.out.println("Right Shift: " + (a >> 1));
        }
    }

    Output:

    Left Shift: 16
    Right Shift: 4

    9. instanceof Operator:The instanceof operator checks whether an object is an instance of a class or an interface.

    Example:

    class Animal {}
    class Dog extends Animal {}
    
    public class InstanceOfExample {
        public static void main(String[] args) {
            Animal a = new Dog();
            System.out.println(a instanceof Dog); // true
            System.out.println(a instanceof Animal); // true
        }
    }

    Output:

    true
    true

    Java Variables

    In Java, variables serve as containers to hold data values during the execution of a program. Each variable is assigned a specific data type that determines the kind and amount of data it can store. Essentially, a variable is a reference to a memory location that stores the data.

    Variables are crucial for storing and manipulating data in a program, and their values can be altered during program execution. Operations on the variable impact the referenced memory location. It’s important to note that all variables in Java must be declared before use.

    Declaring Variables in Java

    Variables in Java can be declared by specifying the data type followed by the variable name. The following two key elements must be considered during declaration:

    • datatype: The type of data that the variable can hold.
    • variable_name: The name given to the memory location.

    Example:

    // Example of variable declaration:
    float interestRate;  // Declaring a float variable
    int time = 10, speed = 20;  // Declaring and initializing integer variables
    char grade = 'A';  // Declaring and initializing a character variable
    Types of Variables in Java

    1. Local Variables
    2. Instance Variables
    3. Static Variables

    1. Local Variables: A local variable is declared within a method, constructor, or block, and its scope is limited to that block or method. Local variables must be initialized before use.

    // Example of local variables
    public class LocalVariableExample {
        public static void main(String[] args) {
            int x = 10;  // Local variable
            String message = "Hello, world!";  // Another local variable
    
            System.out.println("x = " + x);
            System.out.println("Message: " + message);
    
            if (x > 5) {
                String result = "x is greater than 5";  // Local variable within 'if' block
                System.out.println(result);
            }
    
            for (int i = 0; i < 3; i++) {
                String loopMessage = "Iteration " + i;  // Local variable within 'for' loop
                System.out.println(loopMessage);
            }
        }
    }

    Output:

    x = 10
    Message: Hello, world!
    x is greater than 5
    Iteration 0
    Iteration 1
    Iteration 2

    2. Instance Variables: Instance variables are non-static and are declared outside of any method, constructor, or block. These variables are created when an object is instantiated and are destroyed when the object is destroyed. They can have access specifiers and do not need to be initialized explicitly.

    // Example of instance variables
    public class InstanceVariableExample {
        public String name;
        public int age;
    
        public InstanceVariableExample(String name) {
            this.name = name;  // Initializing instance variable
        }
    
        public static void main(String[] args) {
            InstanceVariableExample person = new InstanceVariableExample("Alice");
            System.out.println("Name: " + person.name);
            System.out.println("Age: " + person.age);  // Default value for int is 0
        }
    }

    Output:

    Name: Alice
    Age: 0

    3. Static Variables: Static variables are shared across all instances of a class and are declared with the static keyword. Only one copy of a static variable exists, regardless of how many objects are created.

    // Example of static variables
    public class StaticVariableExample {
        public static String company = "TechCorp";  // Static variable
    
        public static void main(String[] args) {
            System.out.println("Company: " + StaticVariableExample.company);  // Accessing without object
        }
    }

    Output:

    Company: TechCorp

    Scope of a Variables

    In Java, the scope of a variable refers to the region in the code where the variable is accessible. Java has lexical (static) scoping, meaning the scope of a variable is determined at compile time and is not dependent on the function call stack. The scope rules in Java can be broadly classified into three categories based on where the variables are declared.

    1. Member Variables (Class-Level Scope)
    2. Local Variables (Method-Level Scope)
    3. Block Variables (Loop or Block-Level Scope)

    1. Member Variables (Class-Level Scope)

    Member variables are declared inside a class but outside any method, constructor, or block. They can be accessed anywhere within the class and can have different access levels (e.g., publicprivateprotected, or default). Access to member variables outside the class depends on the access modifier used.

    Example:

    public class Test {
        // Member variables
        int a;                  // Default access modifier
        private String b;        // Private member variable
        char c;                  // Default access modifier
    
        void method1() {
            // Member variables can be accessed here
            System.out.println(a);
            System.out.println(b);
        }
    
        int method2() {
            return a;
        }
    }
    • Public: Accessible within the class, in subclasses, and outside the class.
    • Protected: Accessible within the class and in subclasses but not outside the package.
    • Default (no modifier): Accessible within the same package but not outside it.
    • Private: Only accessible within the class.
    2. Local Variables (Method-Level Scope)

    Local variables are declared inside a method or constructor and are only accessible within that method. They must be initialized before use, and their lifetime is limited to the method’s execution. Once the method finishes, local variables are destroyed.

    Example:

    public class Test {
        void method1() {
            // Local variable
            int x = 10;
            System.out.println(x);  // Accessible inside the method
        }
    
        public static void main(String[] args) {
            Test t = new Test();
            t.method1();
        }
    }
    3. Block Variables (Loop or Block-Level Scope)

    Variables declared inside a block (within curly braces {}) are only accessible within that block. Once the block is exited, these variables are out of scope and cannot be accessed. This applies to variables declared inside loops or conditionals.

    Example of Block-Level Scope:

    public class Test {
        public static void main(String[] args) {
            {
                int x = 10;  // x is only accessible inside this block
                System.out.println(x);
            }
    
            // Uncommenting the following line will cause an error
            // System.out.println(x);  // x is out of scope here
        }
    }

    Loop Variables (Block Scope)

    Variables declared inside a loop have scope limited to the loop. They cannot be accessed outside the loop.

    Example:

    class Test {
        public static void main(String[] args) {
            for (int x = 0; x < 4; x++) {
                System.out.println(x);  // x is accessible inside the loop
            }
    
            // Uncommenting the following line will result in an error
            // System.out.println(x);  // x is out of scope here
        }
    }

    If you need to access a loop variable outside the loop, declare it before the loop:

    class Test {
        public static void main(String[] args) {
            int x;
            for (x = 0; x < 4; x++) {
                System.out.println(x);
            }
            System.out.println(x);  // x is accessible outside the loop
        }
    }

    Output:

    0
    1
    2
    3
    4

    Loop Variable Scope with Overlapping Names

    In Java, you cannot declare two variables with the same name within the same scope. However, in languages like C++, it’s possible to have the same variable name in nested scopes, which is not allowed in Java.

    Incorrect Example in Java (compilation error):

    class Test {
        public static void main(String[] args) {
            int a = 5;
            for (int a = 0; a < 5; a++) {  // Error: Variable 'a' is already defined
                System.out.println(a);
            }
        }
    }

    Output:

    Error: variable 'a' is already defined

    Valid Example with Loop Variable Declaration After Loop

    To avoid such errors, you can declare a variable outside the loop and use it after the loop finishes.

    Example:

    class Test {
        public static void main(String[] args) {
            for (int i = 1; i <= 10; i++) {
                System.out.println(i);  // Loop variable i
            }
    
            int i = 20;  // Declare i after the loop
            System.out.println(i);  // Access new i outside the loop
        }
    }

    Output:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    20
  • Overview​ of Java

    Introduction to 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. Java applications are typically compiled to bytecode that can run on any Java Virtual Machine (JVM) regardless of the underlying computer architecture.

    Key Features of Java:
    • Object-Oriented: Encourages the development of modular and reusable code.
    • Platform-Independent: The compiled bytecode can run on any platform with a JVM.
    • Simple and Familiar:Easier to learn and use compared to some other languages.
    • Secure: Provides a secure execution environment and prevents many security threats.
    • Robust: Strong memory management and exception handling.
    • Multithreaded:Supports concurrent execution of two or more parts of a program for maximum utilization of CPU.
    • High Performance:Includes Just-In-Time (JIT) compiler for improved performance.

    C++ vs Java vs Python

    FeatureC++JavaPython
    TypeCompiled languageCompiled to bytecode, runs on JVMInterpreted language
    MemoryManual memory managementAutomatic garbage collectionAutomatic garbage collection
    SyntaxComplex, supports multiple paradigmsCleaner, more consistent than C++Very clean, highly readable
    PerformanceHigh performance, close to hardwareSlower than C++ but highly portableSlower than C++ and Java
    Use CasesSystem/embedded programming, game devWeb applications, enterprise appsWeb development, data science
    LibrariesStandard Template Library (STL)Rich standard library and frameworksExtensive standard library
    Multi-threadingSupported but complexBuilt-in support with synchronizationSupported with Global Interpreter Lock (GIL)

    Just-In-Time (JIT) Compiler

    The Just-In-Time (JIT) compiler is a component of the Java Runtime Environment (JRE) that improves the performance of Java applications by compiling bytecode into native machine code at runtime. This allows Java programs to run faster as they are executed directly by the CPU rather than being interpreted by the JVM.

    Advantages:
    • Improved PerformanceConverts frequently executed bytecode to native code.
    • OptimizationsApplies various optimizations to the native code for better performance.
    • Adaptive Compilation: Compiles only the code that is executed frequently, reducing the overhead.

    Difference between JIT and JVM in Java

    JIT (Just-In-Time Compiler):
    • Part of the JVM.
    • Converts bytecode into native machine code at runtime.
    • Improves performance by compiling frequently executed bytecode.
    • Applies runtime optimizations to the code.
    JVM (Java Virtual Machine):
    • An abstract machine that enables Java bytecode to be executed on any platform.
    • Responsible for interpreting bytecode, managing memory, and providing runtime environment.
    • Includes components like the class loader, runtime data areas, and the execution engine (which includes the JIT compiler).

    Difference between Bytecode and Machine Code

    Bytecode:
    • Intermediate code generated by the Java compiler.
    • Platform-independent and can be executed on any system with a JVM.
    • Needs to be interpreted or compiled (JIT) to machine code for execution
    Machine Code:
    • Low-level code executed directly by the CPU.
    • Platform-specific and generated from bytecode by the JIT compiler.
    • Does not require further interpretation and runs directly on the hardware.

    How is Java Platform Independent?

    Java is platform-independent due to its use of the JVM and bytecode. Here’s how:

    1. Source Code Compilation:Java source code (.java files) is compiled by the Java compiler (javac) into bytecode (.class files). Bytecode is an intermediate, platform-independent code.
    2. Java Virtual Machine (JVM): The JVM is a platform-specific execution environment that runs Java bytecode. Every platform (Windows, macOS, Linux, etc.) has its own JVM implementation.
    3. Write Once, Run Anywhere: Since the bytecode is platform-independent and the JVM is platform-specific, Java applications can run on any device or operating system that has a JVM. This allows developers to write Java programs once and run them anywhere without modification.

  • Java Tutorial Roadmap

    Introduction to Java

    Overview of Java

    Java is a high-level, object-oriented, platform-independent programming language widely used for building enterprise applications, web applications, mobile apps, and backend systems.

    Java vs C++ vs Python

    • Java: Platform-independent, OOP-focused, strong memory management
    • C++: High performance, low-level memory control
    • Python: Simple syntax, rapid development, scripting-friendly

    Java Platform and Execution

    • Just-In-Time (JIT) Compiler
    • Difference between JIT and JVM
    • Bytecode vs Machine Code
    • How Java achieves platform independence

    Java Basic Concepts

    Java Basic Syntax

    • Structure of a Java program
    • Writing a Hello World program

    Data Types in Java

    • Primitive data types
    • Object (reference) data types

    Identifiers

    • Java identifier naming rules

    Variables in Java

    • Variable declaration and initialization
    • Scope of variables

    Input and Output in Java

    Console Input

    • Taking user input in Java
    • Scanner class
    • Different ways to read input from the console

    Output in Java

    • Using System.out.println()
    • Formatted output using printf()

    Operators in Java

    Types of Operators

    • Unary operators
    • Assignment operators
    • Relational operators
    • Logical operators
    • Ternary operator

    Flow Control in Java

    Decision-Making Statements

    • if statement
    • if-else statement
    • if-else-if ladder

    Loops

    • while loop
    • do-while loop
    • for-each loop

    Control Statements

    • break statement
    • continue statement
    • return keyword

    Arrays in Java

    Arrays Overview

    • Declaring and initializing arrays

    Types of Arrays

    • One-dimensional arrays
    • Multidimensional arrays
    • Jagged arrays
    • Final arrays

    Arrays Utility Classes

    • Arrays class
    • reflect.Array
    • Difference between util.Arrays and reflect.Array

    Object-Oriented Programming (OOP) in Java

    Java Naming Conventions

    • Class, method, and variable naming rules

    Classes and Objects

    • Understanding classes and objects
    • Object class in Java
    • Singleton design pattern

    Constructors

    • Default and parameterized constructors
    • Copy constructor
    • Constructor overloading
    • Constructor chaining
    • Private constructors and singleton classes

    Inheritance in Java

    Inheritance Concepts

    • Inheritance and constructors
    • Types of inheritance
    • Interfaces and inheritance

    Multiple Inheritance

    • Achieved using interfaces

    Abstraction in Java

    Abstraction Concepts

    • Abstract classes
    • Abstract methods
    • Control abstraction

    Data Hiding vs Abstraction

    • Key differences

    Encapsulation in Java

    Encapsulation Concepts

    • Data hiding using access modifiers

    Abstraction vs Encapsulation

    • Key differences and use cases

    Polymorphism in Java

    Polymorphism Concepts

    • Compile-time polymorphism
    • Runtime polymorphism

    Dynamic Method Dispatch

    • Method overriding

    Inheritance vs Polymorphism

    • Conceptual differences

    Methods in Java

    Methods Overview

    • Defining and calling methods

    Method Overloading

    • Compile-time polymorphism

    Method Overriding

    • Runtime polymorphism

    Memory Management in Java

    Memory Allocation

    • Stack vs Heap memory

    JVM Memory Areas

    • Types of memory areas allocated by JVM

    Garbage Collection

    • Garbage collection basics
    • Types of JVM garbage collectors

    Memory Leaks

    • Causes and prevention

    Java Virtual Machine (JVM)

    JVM Stack Area

    • Stack frames and execution

    Wrapper Classes

    Wrapper Classes Overview

    • Character class
    • Byte, Short, Long, Float classes

    Keywords in Java

    Java Keywords

    • List of Java keywords

    Important Keywords

    • super
    • final
    • static
    • enum
    • transient
    • volatile

    final vs finally vs finalize

    • Differences and use cases

    Access Modifiers

    Types of Access Modifiers

    • Public
    • Protected
    • Package-private
    • Private

    Access vs Non-Access Modifiers

    • Key differences

    Inner Classes in Java

    Inner Class Concepts

    • Types of inner classes

    Packages in Java

    Package Basics

    • Creating packages

    Common Packages

    • java.util
    • java.lang
    • java.io

    Exception Handling in Java

    Exception Basics

    • Types of exceptions
    • Checked vs unchecked exceptions

    Exception Handling Mechanism

    • try, catch, finally
    • Flow control in exception handling

    throw and throws

    • Custom exception handling

    Advanced Exception Topics

    • User-defined exceptions
    • Chained exceptions

    Multithreading in Java

    Thread Basics

    • Lifecycle and states of a thread
    • Main thread

    Thread Creation

    • Thread class
    • Runnable interface

    Thread Management

    • Thread priority
    • Naming threads
    • start() method behavior

    Synchronization and Concurrency

    Thread Synchronization

    • Importance of synchronization
    • Method-level and block-level synchronization

    Locks and Concurrency

    • Lock framework vs synchronization
    • Atomic vs volatile vs synchronized

    Deadlocks

    • Deadlock concepts
    • Prevention and avoidance

    Advanced Locks

    • Lock vs monitor
    • ReentrantLock

    File Handling in Java

    File Handling Basics

    • File class
    • Creating files

    Reading Files

    • Different ways to read text files

    Writing Files

    • Writing data into files
    • FileWriter class

    File Operations

    • Deleting files
    • File permissions

    Advanced File Handling

    • FileDescriptor
    • RandomAccessFile