Write a note on Bounded Wildcards, Erasure

4.B] Write a note on:
i) Bounded Wildcards
ii) Erasure

Answer:

i) Bounded Wildcards

Bounded Wildcards in Java generics are a way to restrict the types that can be passed as arguments to a generic method or class.

They allow you to specify an upper or lower bound for the type parameter, making the code more flexible while still enforcing some type safety.

Types of Bounded Wildcards:

  1. Upper Bounded Wildcards (<? extends T>):
  • Restricts the type to be a subtype of T.
  • Useful when you want to read from a generic structure but not modify it.
  • Example: List<? extends Number> means the list can hold objects of type Number or its subclasses like Integer, Double, etc. Example:
   public static void printNumbers(List<? extends Number> list) {
       for (Number num : list) {
           System.out.println(num);
       }
   }
  1. Lower Bounded Wildcards (<? super T>):
  • Restricts the type to be a supertype of T.
  • Useful when you want to write to a generic structure but not read from it.
  • Example: List<? super Integer> means the list can hold Integer and any of its supertypes like Number or Object. Example:
   public static void addNumbers(List<? super Integer> list) {
       list.add(10);
       list.add(20);
   }

Summary: Bounded wildcards are a powerful feature in Java generics that provide more control over what types can be used in generic classes and methods. They enhance flexibility while maintaining type safety.


ii) Erasure

Type Erasure is the process by which the Java compiler removes generic type information during the compilation of code.

This means that after compilation, the bytecode contains only non-generic versions of classes, methods, and interfaces. This process ensures backward compatibility with older versions of Java that did not support generics.

How Erasure Works:

  1. Replace Type Parameters: During compilation, the compiler replaces all generic type parameters with their bound types (or Object if no bound is specified). For example, List<T> might become List<Object>.
  2. Insert Casts: Where necessary, the compiler inserts type casts to ensure type safety. For instance, when retrieving elements from a generic collection, it adds the appropriate cast to convert the object back to the expected type.
  3. Remove Generic Information: Finally, the compiler removes all generic type information from the compiled bytecode, meaning the runtime has no knowledge of the generic types.

Example Before Erasure:

public class Box<T> {
    private T value;

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

    public T get() {
        return value;
    }
}

Example After Erasure:

public class Box {
    private Object value;

    public void set(Object value) {
        this.value = value;
    }

    public Object get() {
        return value;
    }
}

Implications of Erasure:

  1. No Runtime Type Information: Because type information is erased, you cannot perform certain operations at runtime, such as checking the type of a generic parameter (if (obj instanceof T) is not allowed).
  2. Type Safety via Casts: The compiler adds type casts where necessary, but this can lead to ClassCastException at runtime if the code is not used correctly.
  3. Overloading Restrictions: Since type erasure removes generic information, methods that differ only by generic type parameters cannot be overloaded. For example, void print(List<String> list) and void print(List<Integer> list) cannot coexist.

Summary: Type erasure ensures that generics are a compile-time feature in Java, providing backward compatibility while also maintaining type safety. However, it introduces some limitations, such as the loss of type information at runtime.

Leave a Reply

Your email address will not be published. Required fields are marked *