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:
- Concatenate the two arrays into a single array.
- 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:
- The
build_tree
function recursively constructs the tree. - The base case is when the inorder traversal is empty, indicating no more nodes.
- The first element in the
preorder
list is the root. - 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:
- Concatenate the two arrays.
- 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) |