Spex3
    

Java Generics


    

    

Java Generics
Generics in Java provide type safety and code reusability by allowing classes, interfaces, and methods to operate on parameterized types. This means you can create classes and methods that work with different data types without losing type safety.

1. Why Use Generics?
Without Generics (Using Object)
Before generics, Java used the Object class to store different types. However, this required explicit type casting, which could lead to runtime errors.

✅ Example (Without Generics)


import java.util.ArrayList;

public class WithoutGenerics {
public static void main(String[] args) {
ArrayList list = new ArrayList(); // No type safety
list.add("Hello");
list.add(100); // No error at compile time

String str = (String) list.get(0); // Type casting required
System.out.println(str);

// This will cause a runtime error
// String num = (String) list.get(1); // ClassCastException
}
}


🚨 Problems with the above approach:

No Type Safety – Different types can be added to the list.

Explicit Type Casting – Risk of ClassCastException.

2. Generics in Java
With generics, we can define a parameterized type that ensures compile-time type safety.

✅ Example (With Generics)



import java.util.ArrayList;

public class WithGenerics {
public static void main(String[] args) {
ArrayList list = new ArrayList<>(); // Type-safe
list.add("Hello");
// list.add(100); // Compile-time error

String str = list.get(0); // No type casting needed
System.out.println(str);
}
}


✅ Advantages of Generics:
✔ Type Safety – Only allowed types can be added.
✔ No Explicit Type Casting – Type conversion is handled automatically.
✔ Code Reusability – The same class/method can be used for different types.

3. Generic Classes
A generic class allows defining a class that can operate on any data type.

✅ Example: Creating a Generic Class


// Generic class with a type parameter
class Box {
private T value;

public void setValue(T value) {
this.value = value;
}

public T getValue() {
return value;
}
}

public class GenericClassExample {
public static void main(String[] args) {
Box intBox = new Box<>();
intBox.setValue(10);
System.out.println("Integer Value: " + intBox.getValue());

Box strBox = new Box<>();
strBox.setValue("Hello Generics");
System.out.println("String Value: " + strBox.getValue());
}
}


💡 Output:


Integer Value: 10
String Value: Hello Generics

4. Generic Methods
A generic method allows defining a method that can operate on different data types.

✅ Example: Creating a Generic Method


class Utility {
// Generic method with
public static void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}

public class GenericMethodExample {
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4, 5};
String[] strArray = {"Hello", "World"};

Utility.printArray(intArray);
Utility.printArray(strArray);
}
}


💡 Output:


1 2 3 4 5
Hello World

5. Bounded Type Parameters
A bounded type parameter restricts the types that can be used as arguments.

✅ Example: Restricting Generics to Number Types


class MathOperations { // T must be a subclass of Number
private T number;

public MathOperations(T number) {
this.number = number;
}

public double square() {
return number.doubleValue() * number.doubleValue();
}
}

public class BoundedGenericsExample {
public static void main(String[] args) {
MathOperations intOp = new MathOperations<>(5);
System.out.println("Square of 5: " + intOp.square());

MathOperations doubleOp = new MathOperations<>(5.5);
System.out.println("Square of 5.5: " + doubleOp.square());

// MathOperations strOp = new MathOperations<>("Hello"); // Compile-time error
}
}


💡 Output:


Square of 5: 25.0
Square of 5.5: 30.25

6. Wildcards (? in Generics)
Wildcards allow flexibility by representing unknown types.

Wildcard Description

Unbounded wildcard (any type allowed)
Upper-bounded wildcard (T and subclasses)
Lower-bounded wildcard (T and superclasses)
✅ Example: Unbounded Wildcard ()


import java.util.List;
import java.util.Arrays;

public class WildcardExample {
public static void printList(List list) { // Accepts any type
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}

public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
List strList = Arrays.asList("A", "B", "C");

printList(intList);
printList(strList);
}
}


💡 Output:


1 2 3
A B C

✅ Example: Upper-Bounded Wildcard ()



import java.util.Arrays;
import java.util.List;

public class BoundedWildcardExample {
public static double sum(List numbers) {
double sum = 0.0;
for (Number num : numbers) {
sum += num.doubleValue();
}
return sum;
}

public static void main(String[] args) {
List intList = Arrays.asList(1, 2, 3);
List doubleList = Arrays.asList(1.5, 2.5, 3.5);

System.out.println("Sum of Integers: " + sum(intList));
System.out.println("Sum of Doubles: " + sum(doubleList));
}
}


💡 Output:


Sum of Integers: 6.0
Sum of Doubles: 7.5

7. Summary of Java Generics

Feature Description

Generic Classes Define classes that work with any type (class Box {})

Generic Methods Define methods that work with any type ( void method(T obj))

Bounded Types Restrict generics to a specific type (T extends Number)

Wildcards (?) Represent unknown types (List, List)

Type Safety Prevents runtime errors (ClassCastException)


    Date: 2025-03-28 00:00:00.000000