Advanced Java August 05 ,2025

Generics Part- 2

10. Inheritance and Subtyping with Generics

10.1. Do Generics Follow Inheritance?

This is a common confusion among Java developers.
Let’s start with a basic inheritance fact:

Integer is a subtype of Number

But this does NOT mean:

List is a subtype of List

In Java, generic types are invariant. That means:

  • List and List are completely unrelated types, even though Integer is a subtype of Number.

10.2. Invariance in Java Generics

What Is Invariance?

Invariance means that:

  • Box is not a subtype of Box, nor vice versa, even though Child is a subtype of Parent.

This is done to preserve type safety.

Example: Compilation Error

import java.util.*;

public class InvarianceDemo {
    public static void addNumbers(List numbers) {
        numbers.add(1);
        numbers.add(2.5);
    }

    public static void main(String[] args) {
        List intList = new ArrayList<>();
        // addNumbers(intList); // Compile-time error
    }
}

Even though Integer is a subtype of Number, you cannot pass List to a method expecting List.

10.3. How to Handle This? Use Wildcards

To make your method flexible, you can use wildcards ( or ).

Example: Use of

public static void printNumbers(List numbers) {
    for (Number num : numbers) {
        System.out.println(num);
    }
}

Now you can pass:

  • List
  • List
  • List etc.

Usage:

public static void main(String[] args) {
    List intList = Arrays.asList(1, 2, 3);
    List doubleList = Arrays.asList(1.1, 2.2, 3.3);

    printNumbers(intList);    // OK
    printNumbers(doubleList); // OK
}

10.4. Covariance and Contravariance in Java

These terms come from type theory. Here's what they mean in Java Generics:

Covariance:

  • Used when the method only reads from the collection.
  • You cannot write to it.
List list = new ArrayList();
Number n = list.get(0); // OK
// list.add(10); // Error

Contravariance:

  • Used when the method writes into the collection.
  • You cannot safely read specific types from it.
List list = new ArrayList();
list.add(10); // OK
// Integer n = list.get(0); // Error: type is Object

Invariant: List

  • Exact type only.
  • List can only accept List.

10.5. Generics and Class Hierarchies

Let’s say you have:

class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }

Generic Class Example

class Cage {
    T animal;

    public Cage(T animal) {
        this.animal = animal;
    }

    public T getAnimal() {
        return animal;
    }
}
Cage dogCage = new Cage<>(new Dog());
Cage catCage = new Cage<>(new Cat());
// Cage animalCage = dogCage; // ❌ Compile-time error

Cage is not a subtype of Cage, even though Dog is a subtype of Animal.

10.6. Arrays vs Generics (Important Distinction)

In Java:

  • Arrays are covariant:

    Integer[] intArr = new Integer[5];
    Number[] numArr = intArr; // Allowed (but unsafe)
    
  • Generics are invariant:

    List intList = new ArrayList<>();
    List numList = intList; // Not allowed
    

This is why arrays can throw ArrayStoreException, while generics ensure type safety at compile-time.

10.7. Wildcards vs Subtyping

StatementAllowed?Explanation
List list = new ArrayList();Invariant
List list = new ArrayList();Covariant
List list = new ArrayList();Contravariant

10.8. Practical Use Case: Copying from One List to Another

public class CopyExample {
    public static  void copy(List dest, List src) {
        for (T item : src) {
            dest.add(item);
        }
    }

    public static void main(String[] args) {
        List numbers = new ArrayList<>();
        List integers = Arrays.asList(1, 2, 3);
        copy(numbers, integers);
        System.out.println(numbers);
    }
}

Output:

[1, 2, 3]

This uses both (for writing) and (for reading) — a practical application of PECS.

Absolutely. Below is the continuation from Chapter 11 to 15 of your Java Generics educational series, followed by a complete summary of all chapters.

11. Limitations of Generics in Java

Generics provide strong benefits, but they come with certain limitations due to type erasure and how Java was designed for backward compatibility.

11.1 Cannot Use Primitive Types Directly

List list = new ArrayList<>(); // ❌ Compile-time error

You must use wrapper classes like Integer, Double, etc.

11.2 Cannot Instantiate Generic Type

class Box {
    T value = new T(); // ❌ Compile-time error
}

Java doesn't know what constructor to call due to type erasure.

11.3 Cannot Create Generic Arrays

T[] arr = new T[10]; // ❌ Compile-time error
List[] listArray = new ArrayList[10]; // ❌

Use Object[] with casting (unsafe) or List.

 

11.4 Cannot Use instanceof with Parameterized Type

if (obj instanceof List) { } // ❌ Compile-time error

Use raw types or bounded wildcards:

if (obj instanceof List) { }

11.5 Cannot Use Generics in Static Context

class MyClass {
    static T value; // ❌ Compile-time error
}

Because static members belong to the class, not to any specific type.

12. Generic vs Object

Without Generics (Using Object)

List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0); // Casting required

With Generics

List list = new ArrayList<>();
list.add("Hello");
String s = list.get(0); // No casting

Advantages of Generics over Object

FeatureGenericsObject
Type Safety✅ Yes❌ No
Compile-time Check✅ Yes❌ No
Type Casting❌ No✅ Yes
Reusability✅ High✅ High
Runtime Errors❌ Less✅ More likely

13. Custom Generic Data Structures

Let’s create a simple Generic Stack.

class Stack {
    private List elements = new ArrayList<>();

    public void push(T value) {
        elements.add(value);
    }

    public T pop() {
        if (elements.isEmpty()) throw new EmptyStackException();
        return elements.remove(elements.size() - 1);
    }

    public boolean isEmpty() {
        return elements.isEmpty();
    }
}

Usage:

public class StackExample {
    public static void main(String[] args) {
        Stack intStack = new Stack<>();
        intStack.push(10);
        intStack.push(20);
        System.out.println(intStack.pop()); // 20
    }
}

14. Advanced Examples and Case Studies

Type-Safe API

class Response {
    private T data;
    public Response(T data) { this.data = data; }
    public T getData() { return data; }
}

Use for designing return types from APIs or services.

Reusable Utilities with Generics

public class Utils {
    public static  boolean isEqual(T a, T b) {
        return a.equals(b);
    }
}

Case Study: Sorting Using Comparator

List names = Arrays.asList("Zara", "Mohan", "Aman");

Collections.sort(names, new Comparator() {
    public int compare(String s1, String s2) {
        return s1.compareTo(s2);
    }
});

 

Conceptual Questions

1. What is type erasure in Java?

Answer:
Type erasure is the process by which the Java compiler removes all generic type information during compilation and replaces them with their raw types (e.g., List<T> becomes List).
This ensures backward compatibility with older Java versions that did not support generics.

2. Difference between List, List<?>, and List<Object>?

TypeDescription
ListRaw type – can hold any type of object, but using it loses type safety. Avoid using raw types.
List<?>List of unknown type – you can read elements as Object but cannot add anything except null.
List<Object>A list that can hold any type of object, but you can only pass another List<Object> (not List<String>).

Note:
List<?> ≠ List<Object> in practice — because generics are invariant.

3. Can we create an array of generics? Why not?

Answer:
No, you cannot directly create arrays of generic types (e.g., new List<String>[10]).
Because:

  • Arrays are reifiable (their runtime type is known).
  • Generics are non-reifiable (type info erased at runtime).
    → Mixing them leads to heap pollution and type safety issues.

4. What are the benefits of using generics?

Benefits:

  • Type safety (detects type errors at compile time).
  • Eliminates need for explicit casting.
  • Code reusability and cleaner code.
  • Improves readability and maintainability.

5. Can we use primitives with generics?

Answer:
No. Generics only work with objects, not primitives.
But Java provides autoboxing (e.g., int → Integer, double → Double) so you can use wrapper classes in generics.

Sample MCQs

Q1. Which of the following declarations is invalid?

A. List<Integer> list = new ArrayList<>();
B. List<int> list = new ArrayList<>();
C. List<?> list = new ArrayList<>();

👉 Answer: B
✅ Because generics do not support primitive types like int.

Q2. What does ? super T mean?

A. Type T or its superclass
B. Type T or its subclass
C. Only type T

👉 Answer: A

Explanation:

  • ? super T → Lower bounded wildcard (T or any superclass of T).
  • ? extends T → Upper bounded wildcard (T or any subclass of T).

Q3. Which of these statements is true about generics in Java?

A. Generics are implemented using type erasure
B. Generics increase runtime overhead
C. Generics allow primitive types directly
D. Generics were introduced in Java 1.2

👉 Answer: A
✅ Because generics are compile-time only and implemented through type erasure (introduced in Java 5).

 

 Key Takeaways on Java Generics

1. Inheritance & Subtyping

  • Integer is a subtype of Number.
  • But List<Integer> is not a subtype of List<Number> → Generics are invariant.

2. Invariance

  • Box<Child> ≠ Box<Parent> even if Child extends Parent.
  • Ensures compile-time type safety.

3. Wildcards Usage (? extends, ? super)

  • ? extends T → CovariantProducer, read-only (safe to read).
  • ? super T → ContravariantConsumer, write-only (safe to add).

🔹 PECS Rule:
Producer Extends, Consumer Super

4. Covariance vs Contravariance

  • Arrays → Covariant → Unsafe (ArrayStoreException).
  • Generics → Invariant → Safer (checked at compile time).

5. Wildcards vs Subtyping

  • List<Integer> ≠ List<Number>.
  • But List<? extends Number> can accept List<Integer>, List<Float>, etc.

6. Generic Class Hierarchies

  • Cage<Integer> ≠ Cage<Number>
    → Each parameterized type is a distinct type.

7. Limitations of Generics

❌ Cannot use primitives (List<int> → invalid).
❌ Cannot instantiate type parameter (new T() → invalid).
❌ Cannot create generic arrays (new List<String>[10] → invalid).
❌ Cannot use instanceof with parameterized types (obj instanceof List<String> → invalid).
❌ Cannot use generic types in static context (type parameter not available).

8. Generics vs Object

  • Without generics → need explicit casting, risk of ClassCastException.
  • With generics → compile-time type safety, no casting needed.

9. Custom Data Structures

Generics enable reusable, type-safe structures like Stack<T>, Queue<T>, or Response<T>.

10. Practical Utilities

  • Generic methods:

    public static <T> boolean isEqual(T a, T b) { return a.equals(b); }
    
  • Copying collections safely:
    Use both ? extends (producer) and ? super (consumer) wildcards.

11. Core Rule

ConceptDescription
ArraysCovariant (checked at runtime → unsafe)
GenericsInvariant (checked at compile-time → safer)

Final Check Summary

SectionStatus
Type Erasure✅ Correct
Difference between Lists✅ Correct, reformatted
Array of Generics✅ Correct
Benefits of Generics✅ Correct
Primitives with Generics✅ Correct
MCQs✅ Fixed syntax & confirmed correctness
Takeaways✅ All accurate and conceptually sound
Missing Questions❌ None missing

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Funct...
Advanced Java August 08 ,2025

Java Functional Inte...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Prototype...
Advanced Java September 09 ,2025

Prototype Design Pat...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

How Concur...
Advanced Java October 10 ,2025

How ConcurrentHashMa...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com