Generics, Collections, and Core Data Structures

Introduction to Generics and Type Safety

ReadingPreview

You are viewing a free preview lesson.

Lesson Overview

আগের module-এ আমরা polymorphic collection ব্যবহার করেছি:

List<ContentItem> contentItems =
        List.of(
                videoLesson,
                articleLesson,
                quizLesson
        );

এখানে:

ContentItem

শুধু একটি class name নয়।

এটি List-এর type argument।

এই type argument compiler-কে বলে:

এই list-এ শুধু ContentItem বা তার valid subtype রাখা যাবে।

Generics ছাড়া Java collection যেকোনো ধরনের object accept করতে পারত।

তখন ভুল type collection-এ ঢুকে runtime-এ failure তৈরি করতে পারত।

Generics আমাদের দেয়:

  • Compile-time type safety
  • Explicit data contracts
  • Fewer casts
  • Reusable classes এবং methods
  • Clearer APIs
  • Safer collections

এই lesson-এ আমরা শিখব:

  • Generics কেন প্রয়োজন
  • Raw type-এর সমস্যা
  • Generic type syntax
  • Type parameter এবং type argument
  • List<String> এবং List<ContentItem>
  • Compile-time type safety
  • Casting কমানো
  • Diamond operator
  • Generic class
  • Generic method
  • Multiple type parameters
  • Primitive types এবং wrapper classes
  • Generic type inheritance-এর একটি গুরুত্বপূর্ণ rule
  • কখন generics useful এবং কখন unnecessary

Learning Objectives

এই lesson শেষ করার পর আপনি পারবেন:

  • Generics-এর purpose explain করতে
  • Raw collections-এর risk identify করতে
  • Generic type declare এবং use করতে
  • Type parameter এবং type argument distinguish করতে
  • Generic class তৈরি করতে
  • Generic method লিখতে
  • Diamond operator ব্যবহার করতে
  • Primitive-এর পরিবর্তে wrapper type ব্যবহার করতে
  • List<VideoLesson> এবং List<ContentItem>-এর relationship বুঝতে
  • Compile-time এবং runtime type failure-এর difference explain করতে

The Problem Before Generics

ধরা যাক আমরা learner names store করতে চাই।

Generics ছাড়া old-style raw list:

List learners =
        new ArrayList();

এটি যেকোনো object accept করতে পারে।

learners.add(
        "Subu"
);

learners.add(
        "Sumu"
);

learners.add(
        100
);

List-এর মধ্যে এখন:

String
String
Integer

সব একসঙ্গে আছে।

Compiler আমাদের থামায়নি।


Runtime Failure with a Raw List

Suppose আমরা ধরে নিচ্ছি সব elements String

for (
        Object learner
        : learners
) {
    String name =
            (String) learner;

    System.out.println(
            name.toUpperCase()
    );
}

প্রথম দুইটি element কাজ করবে।

তৃতীয় element:

100

একটি Integer

Cast:

(String) learner

runtime-এ fail করবে।

ClassCastException

Problemটি collection creation-এর সময় detect হয়নি।

Program চলার পরে detect হয়েছে।


Type-Safe Collection

Generics ব্যবহার করে:

List<String> learners =
        new ArrayList<>();

এখন valid:

learners.add(
        "Subu"
);

Invalid:

learners.add(
        100
);

Compiler error দেবে।

Wrong value collection-এ ঢোকার আগেই problem ধরা পড়ে।


Compile-Time Safety

Generics-এর primary benefit:

Incorrect type usage program run হওয়ার আগেই compiler detect করে।

Without generics:

Wrong data accepted
↓
Application runs
↓
Cast happens later
↓
Runtime failure

With generics:

Wrong data attempted
↓
Compiler rejects code

Earlier failure generally safer এবং cheaper।


Generic Type Syntax

List<String>

Breakdown:

List    → Generic type
String  → Type argument

Another example:

List<ContentItem>
List        → Generic type
ContentItem → Type argument

Type argument বলে generic structure কোন type-এর values নিয়ে কাজ করবে।


The Angle Brackets

Generic type arguments angle brackets-এর মধ্যে লেখা হয়।

<Type>

Examples:

List<String>
List<Integer>
List<Course>
List<ContentItem>

Different type argument same generic classকে different type-safe forms দেয়।


Same Generic Type, Different Contracts

List<String> learnerNames;

Accepts:

String
List<Course> courses;

Accepts:

Course
List<ContentItem> contentItems;

Accepts:

ContentItem
VideoLesson
ArticleLesson
QuizLesson

কারণ child objects ContentItem হিসেবে substitutable।


Type Parameter vs Type Argument

এই দুইটি term আলাদা।

Type Parameter

Generic class বা method declaration-এর placeholder।

public class Box<T> {

}

এখানে:

T

type parameter।

Type Argument

Generic type use করার সময় actual type।

Box<String>

এখানে:

String

type argument।

Another:

Box<Course>

Course actual type argument।


Common Type Parameter Names

Common conventions:

NameTypical Meaning
TType
EElement
KKey
VValue
RResult
NNumber

Examples:

List<E>
Map<K, V>
Optional<T>

These are conventions, Java keywords নয়।

You can write:

public class Box<ItemType> {

}

কিন্তু short conventional names common।


Why Not Use Object Everywhere?

Without generics:

public final class Box {

    private Object value;

    public Box(
            Object value
    ) {
        this.value = value;
    }

    public Object getValue() {
        return value;
    }
}

Usage:

Box box =
        new Box(
                "Java"
        );

Retrieve:

String value =
        (String) box.getValue();

Callerকে cast করতে হচ্ছে।

Wrong cast compile করতে পারে:

Course course =
        (Course) box.getValue();

Runtime-এ fail করবে।


Generic Box<T>

public final class Box<T> {

    private final T value;

    public Box(
            T value
    ) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

Usage:

Box<String> titleBox =
        new Box<String>(
                "Java Generics"
        );

Retrieve:

String title =
        titleBox.getValue();

No cast প্রয়োজন।

Compiler জানে:

Box<String> contains a String

The Diamond Operator

Java constructor call-এর type argument infer করতে পারে।

Verbose:

Box<String> titleBox =
        new Box<String>(
                "Java Generics"
        );

Preferred:

Box<String> titleBox =
        new Box<>(
                "Java Generics"
        );

<>-কে diamond operator বলা হয়।

Compiler left side থেকে String infer করে।


Generic Class with Mutable State

public final class Holder<T> {

    private T value;

    public Holder(
            T value
    ) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }

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

Usage:

Holder<String> learner =
        new Holder<>(
                "Subu"
        );

learner.setValue(
        "Sumu"
);

Invalid:

learner.setValue(
        100
);

Compiler rejects।


Generic Type Safety Applies Throughout the API

For:

Holder<Course> courseHolder

Constructor:

new Holder<>(
        course
);

Setter accepts:

Course

Getter returns:

Course

The type contract remains consistent throughout the object।


Generic Class Example: Result<T>

Application methods often return a value with status information।

public final class Result<T> {

    private final boolean successful;
    private final T value;
    private final String errorMessage;

    private Result(
            boolean successful,
            T value,
            String errorMessage
    ) {
        this.successful = successful;
        this.value = value;
        this.errorMessage =
                errorMessage;
    }

    public static <T> Result<T> success(
            T value
    ) {
        return new Result<>(
                true,
                value,
                null
        );
    }

    public static <T> Result<T> failure(
            String errorMessage
    ) {
        if (
                errorMessage == null
                || errorMessage.isBlank()
        ) {
            throw new IllegalArgumentException(
                    "Error message is required."
            );
        }

        return new Result<>(
                false,
                null,
                errorMessage.strip()
        );
    }

    public boolean isSuccessful() {
        return successful;
    }

    public T getValue() {
        return value;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}

এই example success/failure modeling-এর basic demonstration।

Production design-এ nullable value এবং error access carefully manage করতে হয়।


Using Result<Course>

Result<Course> result =
        Result.success(
                course
        );

Getter:

Course savedCourse =
        result.getValue();

No cast।

Failure:

Result<Course> result =
        Result.failure(
                "Course was not found."
        );

Same generic structure different value types support করতে পারে।


Static Methods and Generic Type Parameters

Class-level T static context-এ directly available নয়।

Why?

Each object type may differ:

Box<String>
Box<Course>

Static method entire class-এর, specific object type-এর নয়।

Generic static method নিজের type parameter declare করে।

Syntax:

public static <T> T methodName(
        T value
) {
    return value;
}

Notice:

<T>

return type-এর আগে।


A Generic Method

public static <T> T first(
        T first,
        T second
) {
    return first;
}

Usage:

String name =
        first(
                "Subu",
                "Sumu"
        );

Compiler infers:

T = String

Another call:

Course selected =
        first(
                javaCourse,
                backendCourse
        );

Compiler infers:

T = Course

Same method multiple types support করে।


Generic Method in a Non-Generic Class

Class generic না হলেও method generic হতে পারে।

public final class SelectionUtils {

    private SelectionUtils() {
    }

    public static <T> T first(
            T first,
            T second
    ) {
        return first;
    }
}

Class declaration:

SelectionUtils

generic নয়।

Method:

<T> T first(...)

generic।


A More Useful Generic Method

public static <T> boolean contains(
        T[] values,
        T expected
) {
    if (values == null) {
        return false;
    }

    for (
            T value
            : values
    ) {
        if (
                expected == null
                ? value == null
                : expected.equals(
                        value
                )
        ) {
            return true;
        }
    }

    return false;
}

Usage:

String[] names = {
        "Subu",
        "Sumu",
        "Nur"
};

boolean found =
        contains(
                names,
                "Nur"
        );

Same method Course[], Integer[], বা অন্য object array-এর সঙ্গে কাজ করতে পারে।


Why Generic Methods Are Better Than Object

Object-based method:

public static Object first(
        Object first,
        Object second
) {
    return first;
}

Caller:

String name =
        (String) first(
                "Subu",
                "Sumu"
        );

Generic method:

public static <T> T first(
        T first,
        T second
) {
    return first;
}

Caller:

String name =
        first(
                "Subu",
                "Sumu"
        );

Generics preserve type information।

Object erases useful compile-time relationship।


Multiple Type Parameters

A generic type একাধিক type parameter রাখতে পারে।

public final class Pair<K, V> {

    private final K key;
    private final V value;

    public Pair(
            K key,
            V value
    ) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return key;
    }

    public V getValue() {
        return value;
    }
}

Usage:

Pair<Long, String> learner =
        new Pair<>(
                101L,
                "Nur"
        );

Here:

K = Long
V = String

Another Pair Example

Pair<String, Course> courseByCode =
        new Pair<>(
                "JAVA-OOP",
                javaCourse
        );

Getter types:

String code =
        courseByCode.getKey();

Course course =
        courseByCode.getValue();

No casts।


Primitive Types Cannot Be Generic Arguments

Invalid:

List<int>

Invalid:

Box<double>

Generics work with reference types।

Use wrapper classes:

List<Integer>
Box<Double>

Common primitive-wrapper pairs:

PrimitiveWrapper
intInteger
longLong
doubleDouble
booleanBoolean
charCharacter
byteByte
shortShort
floatFloat

Autoboxing

Java often primitive এবং wrapper-এর conversion automatically করে।

List<Integer> scores =
        new ArrayList<>();

Add primitive:

scores.add(
        80
);

Java conceptually converts:

int → Integer

এটিকে autoboxing বলা হয়।

Retrieve:

int score =
        scores.get(0);

Conceptually:

Integer → int

এটিকে unboxing বলা হয়।


Wrapper Types Can Be Null

Primitive:

int score;

cannot hold null

Wrapper:

Integer score;

can hold null

Danger:

Integer score =
        null;

int value =
        score;

Unboxing-এর সময়:

NullPointerException

তাই wrapper types generics-এর জন্য required হলেও null handling important।


Raw Types

Generic class type argument ছাড়া use করলে raw type হয়।

List values =
        new ArrayList();
Box box =
        new Box(
                "Java"
        );

Raw types backward compatibility-এর জন্য Java-তে আছে।

Modern application code-এ avoid করুন।


Raw Type Loses Safety

Box<String> stringBox =
        new Box<>(
                "Java"
        );

Box rawBox =
        stringBox;

Raw reference দিয়ে wrong value set করা possible হতে পারে।

rawBox.setValue(
        100
);

Later:

String value =
        stringBox.getValue();

Runtime failure হতে পারে।

Compiler warning দিতে পারে, কিন্তু raw type safety bypass করেছে।


Compiler Warnings Matter

Messages such as:

uses unchecked or unsafe operations

ignore করা উচিত নয়।

Common causes:

  • Raw types
  • Unsafe casts
  • Unchecked generic conversions
  • Mixing legacy non-generic APIs

Warning মানেই application immediately broken নয়।

কিন্তু compiler আর complete type safety guarantee করতে পারছে না।


Parameterized Types Are Different Types

List<String>

এবং:

List<Integer>

same raw class List use করলেও different parameterized types।

This is invalid:

List<String> names =
        new ArrayList<Integer>();

Because element contracts incompatible।


A Critical Inheritance Rule

From Module 3:

VideoLesson is a ContentItem

But this does not mean:

List<VideoLesson> is a List<ContentItem>

This assignment is invalid:

List<VideoLesson> videos =
        new ArrayList<>();

List<ContentItem> contentItems =
        videos;

Java does not allow it।


Why List<VideoLesson> Is Not List<ContentItem>

Suppose assignment were allowed:

List<VideoLesson> videos =
        new ArrayList<>();

List<ContentItem> contentItems =
        videos;

Then this would be valid through contentItems:

contentItems.add(
        new ArticleLesson(...)
);

But original list promises:

Only VideoLesson objects

Now it contains ArticleLesson

Type safety broken।

Therefore Java rejects the assignment।


Generic Types Are Invariant

This behavior is called invariance।

Simple mental model:

Child extends Parent

does not imply:

Generic<Child> extends Generic<Parent>

Examples:

List<VideoLesson> is not List<ContentItem>
Box<VideoLesson> is not Box<ContentItem>

Wildcards later this problem-এর controlled solutions provide করে।

এই lesson-এ শুধু ruleটি remember করুন।


What Still Works?

A List<ContentItem> can directly receive child objects।

List<ContentItem> contentItems =
        new ArrayList<>();

Then:

contentItems.add(
        videoLesson
);

contentItems.add(
        articleLesson
);

contentItems.add(
        quizLesson
);

Because each individual object is a ContentItem

Difference:

Adding child object to parent-typed list → Valid
Assigning child-typed list to parent-typed list → Invalid

Generic Types and Polymorphic Objects

This is valid:

ContentItem content =
        new VideoLesson(...);

This is valid:

List<ContentItem> contents =
        new ArrayList<>();

contents.add(
        new VideoLesson(...)
);

This is invalid:

List<VideoLesson> videos =
        new ArrayList<>();

List<ContentItem> contents =
        videos;

Generics object polymorphism remove করে না।

It adds collection-level type safety rules।


Type Inference

Compiler অনেক সময় generic type infer করতে পারে।

Box<String> box =
        new Box<>(
                "Java"
        );

Method:

String value =
        SelectionUtils.first(
                "Subu",
                "Sumu"
        );

Compiler arguments থেকে T = String infer করে।

Sometimes explicit type argument দেওয়া possible:

String value =
        SelectionUtils
                .<String>first(
                        "Subu",
                        "Sumu"
                );

Usually unnecessary।


Type Inference Has Limits

Mixed arguments:

Object value =
        SelectionUtils.first(
                "Java",
                100
        );

Compiler একটি common compatible type infer করার চেষ্টা করতে পারে, often Object বা অন্য common supertype।

এতে method call compile করলেও result-specific type information দুর্বল হয়।

Generics meaningful যখন arguments logically same role এবং compatible type share করে।


A Bad Generic Abstraction

public final class Everything<T> {

    private T value;

    public void process() {
        // Unknown behavior
    }
}

শুধু <T> add করলে class useful abstraction হয় না।

Generic type useful যখন:

  • Same structure multiple value types support করে
  • Operations type-independent
  • Type relationship preserve করা দরকার
  • Caller concrete type safely receive করতে চায়

When Not to Use Generics

Generics unnecessary হতে পারে যখন class domain-specific এবং one type only।

public final class CourseTitle {

    private final String value;
}

Turning it into:

Title<T>

likely unnecessary।

Another example:

public final class Learner {

}

Learnerকে generic করার real reason নেই।


Generic Domain Wrapper: Use with Care

Possible:

public final class Identifier<T> {

    private final long value;
}

Usage:

Identifier<Course> courseId;
Identifier<Learner> learnerId;

এটি IDs accidentally mix হওয়া prevent করতে পারে।

কিন্তু complexityও বাড়ায়।

Beginner application-এ simple dedicated value objects clearer হতে পারে:

CourseId
LearnerId

Generics and domain design deliberateভাবে combine করতে হয়।


Type Erasure: High-Level Mental Model

Java generics primarily compile-time type safety দেয়।

Compiler generic type information ব্যবহার করে code verify করে।

Runtime implementation historically type erasure নামে একটি model ব্যবহার করে।

Beginner mental model:

Compiler checks List<String>
Runtime list stores object references

এর practical consequences আছে, যেমন:

new T()

directly করা যায় না।

T.class

সাধারণভাবে available নয়।

এই limitations advanced generics discussion-এর অংশ।

এখন main focus:

Generics compile-time contract preserve করে।


You Cannot Directly Create new T()

Invalid:

public class Box<T> {

    public T create() {
        return new T();
    }
}

Compiler জানে না runtime-এ T কোন class এবং কোন constructor আছে।

Object creation-এর জন্য factory, constructor reference, বা supplied value প্রয়োজন হতে পারে।

এগুলো পরে advanced Java-তে শেখা যাবে।


You Cannot Use a Generic Type Parameter in Static State

Invalid:

public class Box<T> {

    private static T sharedValue;
}

Why?

Static field পুরো Box class-এর জন্য shared।

But different parameterizations exist:

Box<String>
Box<Course>

Shared field-এর type কোনটি হবে?

Therefore class-level type parameter static field-এ use করা যায় না।


Generic APIs Should Preserve Meaning

Weak:

public static <T> T convert(
        T input
) {
    return input;
}

Technically generic, কিন্তু value add কম।

Stronger:

public static <T> T requireNonNull(
        T value,
        String message
) {
    if (value == null) {
        throw new IllegalArgumentException(
                message
        );
    }

    return value;
}

Type relationship preserved:

Input T → Output same T

Complete Example: Generic Selection<T>

Selection.java

public final class Selection<T> {

    private final T primary;
    private final T alternative;

    public Selection(
            T primary,
            T alternative
    ) {
        if (primary == null) {
            throw new IllegalArgumentException(
                    "Primary value is required."
            );
        }

        if (alternative == null) {
            throw new IllegalArgumentException(
                    "Alternative value is required."
            );
        }

        this.primary = primary;
        this.alternative = alternative;
    }

    public T getPrimary() {
        return primary;
    }

    public T getAlternative() {
        return alternative;
    }

    public T select(
            boolean useAlternative
    ) {
        return useAlternative
                ? alternative
                : primary;
    }
}

Using Selection<String>

Selection<String> learnerSelection =
        new Selection<>(
                "Subu",
                "Sumu"
        );

String selectedLearner =
        learnerSelection.select(
                true
        );

System.out.println(
        selectedLearner
);

Output:

Sumu

Using Selection<Course>

Selection<Course> courseSelection =
        new Selection<>(
                javaCourse,
                backendCourse
        );

Course selectedCourse =
        courseSelection.select(
                false
        );

Same generic class।

Different type argument।

No casts।


Complete Example: Generic Method with Content

public final class ContentSelection {

    private ContentSelection() {
    }

    public static <T> T choose(
            T primary,
            T alternative,
            boolean useAlternative
    ) {
        if (primary == null) {
            throw new IllegalArgumentException(
                    "Primary value is required."
            );
        }

        if (alternative == null) {
            throw new IllegalArgumentException(
                    "Alternative value is required."
            );
        }

        return useAlternative
                ? alternative
                : primary;
    }
}

Usage:

VideoLesson firstVideo =
        new VideoLesson(...);

VideoLesson secondVideo =
        new VideoLesson(...);

VideoLesson selected =
        ContentSelection.choose(
                firstVideo,
                secondVideo,
                true
        );

Compiler infers:

T = VideoLesson

Mixed Parent and Child Arguments

ContentItem selected =
        ContentSelection.choose(
                videoLesson,
                articleLesson,
                true
        );

Compiler may infer a common type:

ContentItem

because:

VideoLesson is a ContentItem
ArticleLesson is a ContentItem

Result type becomes common abstraction।

This can be useful, but explicit variable type helps readers understand intent।


Generic Type Safety Does Not Validate Business Rules

List<Integer> passingScores;

Generics guarantees elements are Integer

It does not guarantee values are:

0 to 100

This still needs domain validation।

if (
        passingScore < 0
        || passingScore > 100
) {
    throw new IllegalArgumentException(
            "Passing score is invalid."
    );
}

Generics solve type correctness, not complete business correctness।


Generics Do Not Guarantee Non-Null Values

List<String> names =
        new ArrayList<>();

Technically:

names.add(
        null
);

possible for many mutable collection implementations।

Type contract says:

Element is String-compatible

null is compatible with reference types।

Null policy separately enforce করতে হয়।


Generics and Immutability Are Separate

List<String>

says element type String

It does not say list mutable না immutable।

Examples:

new ArrayList<String>()

mutable।

List.of(
        "Subu",
        "Sumu"
)

immutable structure।

Generic type and mutability different concerns।

Detailed list behavior next lesson-এ শেখানো হবে।


Common Mistakes

Using Raw Collections

List values =
        new ArrayList();

Type safety হারায়।


Adding Unnecessary Casts

String name =
        (String) names.get(0);

If names is List<String>, cast unnecessary।


Using Primitive Type Arguments

List<int>

Invalid।

Use:

List<Integer>

Assuming Generic Child Assignment Works

List<VideoLesson>

is not assignable to:

List<ContentItem>

Ignoring Unchecked Warnings

Warnings often indicate raw type বা unsafe conversion।


Making a Class Generic Without a Real Type Relationship

<T> should solve a reusable type problem, not decorate the class।


Expecting Generics to Enforce Domain Values

Integer type safety does not validate score range।


Assuming Generic Collections Reject Null Automatically

They generally do not।


Repeating Type Arguments Unnecessarily

Prefer diamond operator:

new ArrayList<>()

Returning Object from a Generic Context

This loses type information।

Prefer:

T getValue()

instead of:

Object getValue()

Practice Exercises

Exercise 1: Fix a Raw List

Refactor:

List learnerNames =
        new ArrayList();

Requirements:

  • Only String values allowed
  • Diamond operator use করতে হবে
  • Retrieval-এ cast করা যাবে না

Exercise 2: Create Container<T>

Fields:

value

Methods:

getValue()
replaceValue(T value)

Use with:

String
Course
ContentItem

Exercise 3: Create KeyValue<K, V>

Fields:

key
value

Use:

KeyValue<Long, String>

and:

KeyValue<String, Course>

Exercise 4: Write a Generic Method

Create:

static <T> T choose(
        T first,
        T second,
        boolean chooseSecond
)

Test with:

String
Integer
VideoLesson

Exercise 5: Fix Primitive Type Arguments

Refactor:

List<int> scores;
Box<boolean> published;

Use appropriate wrapper types।


Exercise 6: Explain Invariance

Explain why this is invalid:

List<VideoLesson> videos =
        new ArrayList<>();

List<ContentItem> contents =
        videos;

Show what unsafe operation would become possible if Java allowed it।


Exercise 7: Identify What Generics Do Not Validate

Given:

List<Integer> scores

List may still contain:

-100
500
null

Explain which problems are type errors and which are domain/null validation problems।


Predict the Result

Question 1

List<String> names =
        new ArrayList<>();

names.add(
        "Subu"
);

names.add(
        100
);

Will it compile?


Question 2

Box<String> box =
        new Box<>(
                "Java"
        );

String value =
        box.getValue();

Is a cast required?


Question 3

Box<Integer> box =
        new Box<>(
                100
        );

Is 100 accepted even though generics cannot use primitive int?


Question 4

List<VideoLesson> videos =
        new ArrayList<>();

List<ContentItem> contentItems =
        videos;

Will it compile?


Question 5

List<ContentItem> contentItems =
        new ArrayList<>();

contentItems.add(
        new VideoLesson(...)
);

Will it compile?


Question 6

List<Integer> scores =
        new ArrayList<>();

scores.add(
        null
);

int score =
        scores.get(0);

What happens during retrieval?


Predict the Result Answers

Answer 1

না।

List<String> only String-compatible values accept করে।

Answer 2

না।

Getter return type already String

Answer 3

হ্যাঁ।

Java autoboxing করে:

int → Integer

Answer 4

না।

Generic types invariant।

Answer 5

হ্যাঁ।

A VideoLesson is a ContentItem

Answer 6

Retrieval-এর সময় unboxing হবে।

null to int convert করতে গিয়ে:

NullPointerException

Knowledge Check

Question 1

Generics-এর primary purpose কী?

Question 2

Raw type কী?

Question 3

Type parameter কী?

Question 4

Type argument কী?

Question 5

List<String>-এ String কী?

Question 6

Diamond operator কী?

Question 7

Generic class কী?

Question 8

Generic method কীভাবে declare করা হয়?

Question 9

Why does a generic method write <T> before its return type?

Question 10

Primitive types generic argument হতে পারে কি?

Question 11

Autoboxing কী?

Question 12

List<VideoLesson> কি List<ContentItem>?

Question 13

A VideoLesson কি List<ContentItem>-এ add করা যায়?

Question 14

Generics কি null prevent করে?

Question 15

Generics কি business rules validate করে?


Knowledge Check Answers

Answer 1

Compile-time type safety এবং reusable type-preserving APIs তৈরি করা।

Answer 2

Type argument ছাড়া generic class use করা।

Example:

List values

Answer 3

Generic declaration-এর placeholder type।

Example:

<T>

Answer 4

Generic type use করার সময় supplied actual type।

Example:

String

in:

Box<String>

Answer 5

Type argument।

Answer 6

Constructor call-এ type inference-এর জন্য empty angle brackets:

<>

Answer 7

একটি class যা এক বা একাধিক type parameter ব্যবহার করে different value types safely support করে।

Answer 8

Method return type-এর আগে type parameter declare করে।

public static <T> T first(...)

Answer 9

কারণ method-এর নিজের generic type parameter declaration return type এবং parameters-এর আগে introduce করতে হয়।

Answer 10

না।

Wrapper classes ব্যবহার করতে হয়।

Answer 11

Primitive value automatically wrapper object-এ convert হওয়া।

Answer 12

না।

Generic types invariant।

Answer 13

হ্যাঁ।

Individual child object parent-typed list-এ add করা যায়।

Answer 14

না।

Reference type collection null contain করতে পারে।

Answer 15

না।

Generics type correctness enforce করে; domain rules separately validate করতে হয়।


Lesson Summary

এই lesson-এ আমরা শিখেছি:

  • Generics compile-time type safety দেয়
  • Raw collections যেকোনো object accept করে runtime casting failure তৈরি করতে পারে
  • List<String> element type explicitly declare করে
  • Generic structure wrong types collection-এ ঢোকার আগে reject করে
  • Type parameter declaration-এর placeholder
  • Type argument actual supplied type
  • T, E, K, এবং V common conventions
  • Generic classes same structure multiple types-এর জন্য reuse করতে দেয়
  • Generic getters correct type return করে
  • Generic setters correct type accept করে
  • Generics unnecessary casts remove করে
  • Diamond operator type argument infer করে
  • Generic method নিজের <T> declare করতে পারে
  • Non-generic class generic method রাখতে পারে
  • Multiple type parameters possible
  • Primitive types generic arguments হতে পারে না
  • Wrapper types generic arguments হিসেবে use হয়
  • Autoboxing primitiveকে wrapper-এ convert করে
  • Unboxing null wrapper-এর ক্ষেত্রে fail করতে পারে
  • Raw types type safety bypass করে
  • Unchecked compiler warnings গুরুত্ব দিয়ে review করা উচিত
  • List<String> এবং List<Integer> different parameterized types
  • VideoLesson একটি ContentItem
  • কিন্তু List<VideoLesson> একটি List<ContentItem> নয়
  • Generic types invariant
  • A child object parent-typed collection-এ add করা যায়
  • Generics business validation replace করে না
  • Generics null safety guarantee করে না
  • Generics mutability define করে না
  • Generic abstraction real reusable type relationship solve করা উচিত
  • Java generics primarily compile-time contract preserve করে

Next Lesson

পরবর্তী lesson:

Working with List

আমরা শিখব:

  • Ordered collection
  • ArrayList
  • Creating mutable এবং immutable lists
  • Adding elements
  • Reading by index
  • Updating elements
  • Removing elements
  • List size
  • Duplicates
  • Iteration
  • Searching
  • List.of()
  • List.copyOf()
  • ArrayList vs immutable list
  • Index errors
  • Safe list design