Java Main Method Overloading, Static Block Execution, and TypeScript Null/Undefined Checks

This Java and TypeScript tutorial explores several key concepts: main method overloading in Java (and why only one specific signature is executed), static block execution order, and how to effectively check for null and undefined values in TypeScript to prevent runtime errors. A useful guide for intermediate-level developers.



Data Structures and Algorithms: More Advanced Concepts

Overloading the `main()` Method

Question 39: Overloading the `main()` Method

In Java, you can overload the `main()` method. However, the Java Virtual Machine (JVM) will only run the `main` method with the signature `public static void main(String[] args)`. Other `main` methods are ignored.

Java Code

class OverloadMain {
    public static void main(int a) {
        System.out.println(a); // Output: 6
    }
    public static void main(String args[]) {
        System.out.println("main method invoked"); // Output: main method invoked
        main(6);
    }
}

Static Block Execution Order

Question 40: Static Block vs. `main()` Method

Static blocks in Java are executed *before* the `main()` method. This is useful for initializing static variables or performing setup tasks.

Java Code

class Demo {
    static {
        System.out.println("Static block"); // Output: Static block
    }
    public static void main(String args[]) {
        System.out.println("Main method"); // Output: Main method
    }
}

Checking for Null and Undefined

Question 36: Checking for `null` and `undefined`

In TypeScript:

  • Loose equality (`==`) checks for value equality (including type coercion).
  • Strict equality (`===`) checks for both value and type equality.
  • `typeof x === 'undefined'` explicitly checks if a variable is `undefined`.

Double Brace Initialization

Question 15: Double Brace Initialization

Double brace initialization in Java creates an anonymous inner class and immediately instantiates it. The first pair of braces defines the anonymous class, and the second pair of braces creates an instance initializer block.

Java Code

import java.util.HashMap;
import java.util.Set;

public class TestHashMap {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<String, String>() {
            {
                put("1", "ONE");
                put("2", "TWO");
                put("3", "THREE");
            }
        };
        Set<String> keySet = map.keySet();
        for (String string : keySet) {
            System.out.println(string + " -> " + map.get(string)); // Output: 1 -> ONE, 2 -> TWO, 3 -> THREE
        }
    }
}

Infinite Loops

Question 16: Infinite Loops

These `for` loops run indefinitely:

  • for(;;) { ... }
  • for(; true; ) { ... }
  • for(; 2 == 2; ) { ... }

The loop for(int i = 1; i >= 1; i++) { ... } also runs indefinitely because the condition `i >= 1` is always true.

Static Block Execution

Question 17: Static Block Execution

Java Code

public class Block {
    static {
        System.out.println("Static Block-1"); // Output: Static Block-1
    }
    public static void main(String args[]) {
        System.out.println("Main Method"); // Output: Main Method
    }
    static {
        System.out.println("Static Block-2"); // Output: Static Block-2
    }
}

Splitting Strings

Question 18: Splitting Strings

Java Code

import java.util.Arrays;
public class SplitString {
    public static void main(String args[]) {
        String str = "Java|Python|Hadoop";
        String[] array = str.split("\\|");
        System.out.println(Arrays.toString(array)); // Output: [Java, Python, Hadoop]
    }
}

`System.exit()` and `finally` Blocks

Question 19: System.exit() and finally Blocks

Calling `System.exit(0)` within a `try` or `catch` block might prevent the `finally` block from executing. The `finally` block is only guaranteed to execute if the program exits normally.

ArrayStoreException

Question 20: ArrayStoreException

Java Code

public class ExceptionDemo {
    public static void main(String args[]) {
        Object x[] = new String[3];
        x[0] = new Integer(0); // Throws ArrayStoreException
    }
}
Output

Exception in thread "main" java.lang.ArrayStoreException

Merging Unsorted Arrays

Question 6: Merging Unsorted Arrays

To merge two unsorted arrays into a single sorted array, you can use the following steps:

  1. Concatenate the two arrays into a single array.
  2. Sort the combined array using a sorting algorithm (like merge sort or quicksort).
Java Code

import java.util.*;
public class MergeUnsortedArrays {
    public static void mergeAndSort(int array1[], int array2[], int resArray[]) {
        int len1 = array1.length;
        int len2 = array2.length;
        int i = 0, j = 0, k = 0;
        while (i < len1) {
            resArray[k++] = array1[i++];
        }
        while (j < len2) {
            resArray[k++] = array2[j++];
        }
        Arrays.sort(resArray);
        System.out.print("Sorted merged array: ");
        for (int p = 0; p < len1 + len2; p++)
            System.out.print(" " + resArray[p]); //Output: (Example: Sorted merged array:  1 2 3 4 5 6 7 8 9 10 )
    }
    public static void main(String[] args) {
        int[] array1 = {1, 3, 5, 7, 9};
        int[] array2 = {2, 4, 6, 8, 10};
        int resArray[] = new int[array1.length + array2.length];
        mergeAndSort(array1, array2, resArray);
    }
}

Adding Linked Lists

Question 7: Adding Numbers Represented by Linked Lists

This function adds two numbers represented by linked lists. Each node in the linked list represents a digit. The function handles carry-overs between digits.

Java Code

class Node {
    int data;
    Node next;
    Node(int d) { data = d; next = null; }
}
class LinkedListAddition {
    Node combineLists(Node first, Node second) {
        Node head = null, prev = null, temp = null;
        int carry = 0, sum;
        while (first != null || second != null) {
            sum = carry + (first != null ? first.data : 0) + (second != null ? second.data : 0);
            carry = (sum >= 10) ? 1 : 0;
            sum = sum % 10;
            temp = new Node(sum);
            if (head == null) head = temp;
            else prev.next = temp;
            prev = temp;
            if (first != null) first = first.next;
            if (second != null) second = second.next;
        }
        if (carry > 0) temp.next = new Node(carry);
        return head;
    }
    void printList(Node node) {
        while (node != null) {
            System.out.print(node.data + " ");
            node = node.next;
        }
        System.out.println();
    }
    public static void main(String[] args) {
        LinkedListAddition list = new LinkedListAddition();
        Node first = new Node(9);
        first.next = new Node(9);
        first.next.next = new Node(9);
        Node second = new Node(1);
        System.out.print("First List is ");
        list.printList(first); //Output: First List is 9 9 9 
        System.out.print("Second List is ");
        list.printList(second); //Output: Second List is 1 
        Node rs = list.combineLists(first, second);
        System.out.print("Resultant List is ");
        list.printList(rs); //Output: Resultant List is 0 0 0 1 
    }
}

Building a Tree from Inorder and Preorder Traversals

Question 8: Building a Tree from Inorder and Preorder Traversals

Constructing a binary tree from its inorder and preorder traversals involves a recursive algorithm. The preorder traversal helps identify the root node at each step, while the inorder traversal helps divide the remaining elements into the left and right subtrees. The algorithm utilizes the property that the root node in preorder traversal is always the first element. Correspondingly, in inorder traversal, all elements to the left of the root belong to the left subtree, and all elements to the right belong to the right subtree.

Java Code

    class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

def build_tree(preorder, inorder):
    if not inorder:  # Base case: empty inorder traversal
        return None

    root_val = preorder.pop(0)  # Root is the first element in preorder
    root = Node(root_val)
    inorder_root_index = inorder.index(root_val)

    root.left = build_tree(preorder, inorder[:inorder_root_index])  # Recursively build left subtree
    root.right = build_tree(preorder, inorder[inorder_root_index + 1:]) # Recursively build right subtree

    return root


# Example usage:
preorder = [3, 9, 20, 15, 7]
inorder = [9, 3, 15, 20, 7]

root = build_tree(preorder, inorder)

# Function to print inorder traversal (for verification)
def print_inorder(node):
    if node:
        print_inorder(node.left)
        print(node.data, end=" ")
        print_inorder(node.right)

print_inorder(root)  # Output: 9 3 15 20 7 (matches the original inorder traversal)

Explanation:

  1. The build_tree function recursively constructs the tree.
  2. The base case is when the inorder traversal is empty, indicating no more nodes.
  3. The first element in the preorder list is the root.
  4. The inorder list is split based on the root's position to recursively build the left and right subtrees.

The included Python code provides a clear implementation of this algorithm, making the concept easier to grasp and apply.

Longest Substring Without Repeating Characters

Question 3: Longest Substring Without Repeating Characters

Find the longest substring within a given string that contains no repeating characters. A `LinkedHashMap` can efficiently track character positions.

Java Code

package tutorialsarena.MicrosoftJava;
import java.util.LinkedHashMap;
import java.util.Scanner;

public class LongestSubString {
    static void longestSubString(String str) {
        char[] charArray = str.toCharArray();
        String subStr = null;
        int length = 0;
        LinkedHashMap<Character, Integer> positionMap = new LinkedHashMap<Character, Integer>();
        for (int i = 0; i < charArray.length; i++) {
            char c = charArray[i];
            if (!positionMap.containsKey(c)) {
                positionMap.put(c, i);
            } else {
                i = positionMap.get(c);
                positionMap.clear();
            }
            if (positionMap.size() > length) {
                length = positionMap.size();
                subStr = positionMap.keySet().toString();
            }
        }
        System.out.println("The longest substring is " + subStr + " with length " + length + "."); 
    }
    public static void main(String args[]) {
        String inputString;
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter a string: ");
        inputString = sc.nextLine();
        sc.close();
        longestSubString(inputString);
    }
}
Output (Example: abcabcbb)

The longest substring is [a, b, c] with length 3.

Reversing a Linked List

Question 4: Reversing a Linked List

Reversing a linked list involves changing the direction of the links between nodes. You can do this iteratively or recursively.

(Code for reversing a linked list would be placed here. This would likely involve traversing the linked list and adjusting the `next` pointers in each node to point to the previous node. The output should show the reversed linked list.)

Removing Duplicates from a String

Question 5: Removing Duplicates from a String

Several approaches exist for removing duplicate characters from a String. Efficient methods would use a Set or a hash table to track the unique characters.

Java Code

package tutorialsarena.MicrosoftJava;
import java.util.*;
public class RemoveDuplicates {
    static String removeChars(char charArray[], int length) {
        int pos = 0;
        for (int i = 0; i < length; i++) {
            int j;
            for (j = 0; j < i; j++) {
                if (charArray[i] == charArray[j]) break;
            }
            if (j == i) charArray[pos++] = charArray[i];
        }
        return String.valueOf(Arrays.copyOf(charArray, pos));
    }
    public static void main(String args[]) {
        String inputString;
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter a string: ");
        inputString = sc.nextLine();
        sc.close();
        char charArray[] = inputString.toCharArray();
        System.out.println("String after removing duplicates: " + removeChars(charArray, charArray.length)); 
    }
}
Output (Example: abcabcbb)

String after removing duplicates: abc

Merging Unsorted Arrays

Question 6: Merging Unsorted Arrays

To merge two unsorted arrays into a single sorted array:

  1. Concatenate the two arrays.
  2. Sort the combined array using a suitable sorting algorithm (e.g., merge sort, quicksort).
Java Code

package tutorialsarena.MicrosoftJava;
import java.util.*;
public class MergeUnsortedArrays {
    public static void mergeAndSort(int array1[], int array2[], int resArray[]) {
        int len1 = array1.length;
        int len2 = array2.length;
        int i = 0, j = 0, k = 0;
        while (i < len1) resArray[k++] = array1[i++];
        while (j < len2) resArray[k++] = array2[j++];
        Arrays.sort(resArray);
        System.out.print("Sorted merged array: ");
        for (int p = 0; p < len1 + len2; p++) System.out.print(" " + resArray[p]); // Example output: Sorted merged array:  1 2 3 4 5 6 7 8 9 10
    }
    public static void main(String[] args) {
        int[] array1 = {1, 3, 5, 7, 9};
        int[] array2 = {2, 4, 6, 8, 10};
        int resArray[] = new int[array1.length + array2.length];
        mergeAndSort(array1, array2, resArray);
    }
}

Adding Numbers Represented by Linked Lists

Question 7: Adding Numbers Represented by Linked Lists

This involves traversing both linked lists, adding digits from corresponding nodes, and handling carry-overs.

Java Code (Illustrative - Error Handling Omitted)

class Node { int data; Node next; Node(int d) {data = d; next = null;}}
class LinkedListAddition {
    Node combineLists(Node first, Node second) {
        Node head = null, prev = null, temp = null;
        int carry = 0, sum;
        while (first != null || second != null) {
            sum = carry + (first != null ? first.data : 0) + (second != null ? second.data : 0);
            carry = (sum >= 10) ? 1 : 0;
            sum = sum % 10;
            temp = new Node(sum);
            if (head == null) head = temp;
            else prev.next = temp;
            prev = temp;
            if (first != null) first = first.next;
            if (second != null) second = second.next;
        }
        if (carry > 0) temp.next = new Node(carry);
        return head;
    }
    void printList(Node node) {
        while (node != null) {
            System.out.print(node.data + " ");
            node = node.next;
        }
        System.out.println();
    }
    public static void main(String[] args) {
        LinkedListAddition list = new LinkedListAddition();
        Node first = new Node(9);
        first.next = new Node(9);
        first.next.next = new Node(9);
        Node second = new Node(1);
        System.out.print("First List is ");
        list.printList(first); // Output: First List is 9 9 9 
        System.out.print("Second List is ");
        list.printList(second); // Output: Second List is 1 
        Node rs = list.combineLists(first, second);
        System.out.print("Resultant List is ");
        list.printList(rs); // Output: Resultant List is 0 0 0 1 
    }
}

Building a Binary Tree

Question 8: Building a Binary Tree from Inorder and Preorder Traversal

(This would involve describing a recursive algorithm that constructs a binary tree from its inorder and preorder traversals. The algorithm would use the preorder traversal to determine the root node and the inorder traversal to partition the remaining nodes into left and right subtrees.)

Longest Consecutive Substring

Question 9: Longest Consecutive Substring

Find the length of the longest substring of consecutive characters (e.g., "abc" or "xyz").

Java Code

package tutorialsarena.MicrosoftJava;
import java.util.Scanner;

class FindConsSubString {
    static int getLastIndex(String str, int n, int i) {
        i++;
        while (i < n) {
            char curr = str.charAt(i);
            char prev = str.charAt(i - 1);
            if ((curr == 'a' && prev == 'z') || (curr - prev == 1)) {
                i++;
            } else {
                break;
            }
        }
        return i - 1;
    }
    static int getLength(String inputStr, int length) {
        int len = 0;
        int i = 0;
        while (i < length) {
            int last = getLastIndex(inputStr, length, i);
            len = Math.max(last - i + 1, len);
            i = last + 1;
        }
        return len;
    }
    public static void main(String args[]) {
        String inputString;
        Scanner sc = new Scanner(System.in);
        System.out.print("Enter a string: ");
        inputString = sc.nextLine();
        sc.close();
        System.out.print(getLength(inputString, inputString.length())); //Example output for "abbcde": 3
    }
}

Finding Two Unique Elements

Question 10: Finding Two Unique Elements

Given an array where every element appears twice except two, find those two unique elements.

Java Code

package tutorialsarena.MicrosoftJava;
import java.util.Scanner;
public class FindUniqueElements {
    public static void getUniqueElements(int array[], int length) {
        for (int i = 0; i < length; i++) {
            int j;
            for (j = 0; j < length; j++) {
                if (i != j && array[i] == array[j]) {
                    break;
                }
            }
            if (j == length)
                System.out.println(array[i]); // Example output for input [1, 2, 3, 4, 2, 1, 3, 4, 5, 6]: 5, 6
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter size of the array");
        int size = sc.nextInt();
        int[] array = new int[size];
        System.out.println("Enter the elements of the array: ");
        for (int i = 0; i < array.length; i++) {
            array[i] = sc.nextInt();
        }
        sc.close();
        getUniqueElements(array, size);
    }
}

Finding Common Elements in Three Arrays

Question 11: Finding Common Elements in Three Arrays

Find common elements across three sorted arrays.

Java Code

package tutorialsarena.MicrosoftJava;
import java.util.Scanner;
public class FindCommonElements {
    public static void getCommonElements(int array1[], int array2[], int array3[], int length) {
        int i = 0, j = 0, k = 0;
        while (i < array1.length && j < array2.length && k < array3.length) {
            if (array1[i] == array2[j] && array2[j] == array3[k]) {
                System.out.print(array1[i] + " ");
                i++; j++; k++;
            } else if (array1[i] < array2[j]) {
                i++;
            } else if (array2[j] < array3[k]) {
                j++;
            } else {
                k++;
            }
        }
    }
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter size of the array");
        int size = sc.nextInt();
        int[] array1 = new int[size];
        int[] array2 = new int[size];
        int[] array3 = new int[size];
        System.out.println("Enter the elements of the 1st array: ");
        for (int i = 0; i < array2.length; i++) {
            array1[i] = sc.nextInt();
        }
        System.out.println("Enter the elements of the 2nd array: ");
        for (int i = 0; i < array2.length; i++) {
            array2[i] = sc.nextInt();
        }
        System.out.println("Enter the elements of the 3rd array: ");
        for (int i = 0; i < array3.length; i++) {
            array3[i] = sc.nextInt();
        }
        sc.close();
        getCommonElements(array1, array2, array3, size); //Example output for input arrays {1,2,3,4,5}, {2,3,4,5,6}, {2,3,4,5,7}: 2 3 4 5
    }
}

Object Typecasting

Question 12: Object Typecasting

Object typecasting in Java involves converting an object from one type to another. Upcasting (casting a child class object to a parent class object) is always safe. Downcasting (casting a parent class object to a child class object) is only safe if the object is actually an instance of the child class.

Detecting Loops in Linked Lists

Question 13: Detecting Loops in Linked Lists

Use two pointers (slow and fast) that move through the linked list at different speeds. If a loop exists, the fast pointer will eventually overtake the slow pointer.

Double-Checked Locking

Question 14: Double-Checked Locking

Double-checked locking is a design pattern used to create thread-safe singleton classes efficiently. It involves checking for an existing instance twice—once without synchronization and then again with synchronization to avoid unnecessary locking overhead.

Transient Variables

Question 15: Transient Variables

A `transient` variable in Java is not serialized. Its value is not saved when the object is serialized.

`volatile` Keyword

Question 16: `volatile` Keyword

The `volatile` keyword in Java ensures that changes to a variable are immediately visible to all threads. This helps with thread synchronization but does not guarantee thread safety on its own.

Overriding Private Methods

Question 17: Overriding Private Methods

You cannot override private methods in Java because private methods are not accessible outside the class they are declared in.

`HashTable` vs. `HashMap`

Question 18: `HashTable` vs. `HashMap`

Key differences:

Feature `HashTable` `HashMap`
Synchronization Synchronized (thread-safe) Not synchronized (not thread-safe)
Performance Slower Faster
Null Keys/Values No null keys or values allowed One null key and multiple null values allowed

Overriding `equals()` and `hashCode()`

Question 19: Overriding `equals()` and `hashCode()`

To use a custom object as a key in a `HashMap`, you must override both the `equals()` and `hashCode()` methods. The `hashCode()` method should return a consistent hash value for equal objects.

`LinkedList` vs. `ArrayList`

Question 20: `LinkedList` vs. `ArrayList`

Differences:

Feature `LinkedList` `ArrayList`
Implementation Doubly linked list Dynamic array
Data Access Random access is slower Random access is fast
Insertion/Deletion Efficient Less efficient (requires shifting elements)