Methods, Arrays, and Program Structure

Scope, Static Methods, and Method Overloading

ReadingPreview

You are viewing a free preview lesson.

Lesson Overview

আগের lessons-এ আমরা methods, parameters, arguments, এবং return values শিখেছি।

এখন তিনটি important concept বুঝতে হবে:

Scope
static methods
Method overloading

এই তিনটি concept Java code organize করা, method calls বুঝা, এবং variable-related bugs avoid করার জন্য গুরুত্বপূর্ণ।

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

  • What scope means
  • Local variables
  • Block scope
  • Method scope
  • Variable shadowing
  • Variable lifetime
  • What static means
  • Static method calls
  • Static fields
  • Instance methods-এর preview
  • Method overloading
  • Overload resolution
  • Valid and invalid overloads
  • Common design mistakes

What Is Scope?

Scope means:

Program-এর কোন অংশ থেকে একটি variable, method, বা member accessible?

Example:

static void greet() {
    String message =
            "Hello";

    System.out.println(
            message
    );
}

message variableটি greet() method-এর ভিতরে declared হয়েছে।

তাই এটি ওই method-এর local scope-এর অংশ।


Local Variable

A variable declared inside a method is called a:

Local variable

Example:

static void calculate() {
    int result =
            10 + 20;

    System.out.println(
            result
    );
}

Here:

result

is a local variable।


Local Variable Is Not Available Everywhere

This does not compile:

public class Main {

    public static void main(String[] args) {
        calculate();

        System.out.println(
                result
        );
    }

    static void calculate() {
        int result =
                30;
    }
}

Why?

Because:

result

exists only inside:

calculate()

Method Scope

Each method has its own local scope।

Example:

static void first() {
    String message =
            "First";

    System.out.println(
            message
    );
}

static void second() {
    String message =
            "Second";

    System.out.println(
            message
    );
}

Both methods may have a variable named:

message

because they belong to different scopes।


Same Name, Different Variables

static void first() {
    int number =
            10;
}

static void second() {
    int number =
            20;
}

These are two separate variables।

Conceptually:

first()  → its own number
second() → its own number

They do not conflict।


Parameters Are Also Local to the Method

Consider:

static void greet(
        String name
) {
    System.out.println(
            name
    );
}

The parameter:

name

belongs to the scope of greet()

You cannot use it from another unrelated method unless that method receives or declares its own name


Block Scope

Scope can be smaller than an entire method।

Curly braces create blocks।

Example:

static void checkAge(
        int age
) {
    if (age >= 18) {
        String message =
                "Adult";

        System.out.println(
                message
        );
    }
}

message exists only inside the if block।


Outside the Block

This does not compile:

static void checkAge(
        int age
) {
    if (age >= 18) {
        String message =
                "Adult";
    }

    System.out.println(
            message
    );
}

because message is outside its scope।


Loop Variables Have Scope Too

Example:

for (
        int i = 0;
        i < 5;
        i++
) {
    System.out.println(
            i
    );
}

The variable:

i

belongs to the for loop।

This is invalid after the loop:

System.out.println(
        i
);

Scope Helps Prevent Accidental Access

Imagine every variable in a program were accessible everywhere।

Any method could modify any variable at any time।

That would make programs extremely difficult to reason about।

Scope limits:

Who can see what?
Who can change what?
How long does the variable matter?

This becomes even more important when we study encapsulation।


Prefer the Smallest Useful Scope

Suppose:

static void process() {
    int total;

    // 50 lines of unrelated logic

    total =
            100;

    System.out.println(
            total
    );
}

If total is only needed near the end, declare it near where it is used:

static void process() {
    // other logic

    int total =
            100;

    System.out.println(
            total
    );
}

Smaller scope makes code easier to understand।


Variable Lifetime

Scope describes:

Where a variable can be accessed

Lifetime describes roughly:

How long that variable exists during execution

A local variable is associated with a specific method invocation।

Example:

static void showNumber() {
    int number =
            10;

    System.out.println(
            number
    );
}

Every call gets its own local execution state।


Multiple Calls

showNumber();
showNumber();

Each invocation independently creates its own local number

The method does not automatically remember the previous local variable value between calls।


Example

static void count() {
    int value =
            0;

    value++;

    System.out.println(
            value
    );
}

Call:

count();
count();
count();

Output:

1
1
1

Why?

Each method invocation creates a new local:

value = 0

If We Need Shared State

If we wrote:

static int value =
        0;

outside the method but inside the class:

public class Main {

    static int value =
            0;

    static void count() {
        value++;

        System.out.println(
                value
        );
    }
}

then calls:

count();
count();
count();

produce:

1
2
3

Now value is not a local variable।

It is a:

static field

We'll explore fields properly in the OOP module।


Be Careful with Shared Mutable State

Just because a static field is possible does not mean it is always a good design।

Example:

static int total =
        0;

can be modified from many static methods in the class।

As programs grow, shared mutable state can become difficult to track।

Prefer local variables when the data belongs only to one operation।


Variable Shadowing

Shadowing happens when a variable with the same name hides another variable from an outer scope।

Consider:

public class Main {

    static String name =
            "LiveKlass";

    public static void main(String[] args) {
        String name =
                "Java";

        System.out.println(
                name
        );
    }
}

Output:

Java

The local name shadows the static field name inside main()


Shadowing Can Cause Confusion

Example:

static int total =
        100;

static void printTotal() {
    int total =
            200;

    System.out.println(
            total
    );
}

Output:

200

The local variable hides the field।

This is legal but can be confusing।

Avoid unnecessary shadowing unless the context is clear।


You Cannot Redeclare a Local Variable in the Same Scope

Invalid:

static void example() {
    int number =
            10;

    int number =
            20;
}

The name already exists in the same scope।


Nested Scope and Redeclaration

This is also invalid in Java:

static void example() {
    int number =
            10;

    if (true) {
        int number =
                20;
    }
}

A local variable in an inner block cannot redeclare an active local variable from the enclosing method scope।


Different Sequential Blocks

This can work:

static void example() {
    {
        int number =
                10;

        System.out.println(
                number
        );
    }

    {
        int number =
                20;

        System.out.println(
                number
        );
    }
}

The two variables do not exist at the same time in overlapping scopes।


Why Scope Matters for Methods

Good methods usually keep:

Temporary calculation details
Local variables
Intermediate values

inside the method that owns the operation।

Example:

static long calculateTotal(
        long price,
        int quantity
) {
    long total =
            price * quantity;

    return total;
}

Caller only cares about:

returned total

It does not need access to the internal local variable।


Introduction to static

So far we have written methods like:

static void greet() {
}

What does:

static

mean?

At a high level:

The method belongs to the class itself,
rather than to a specific object instance.

We haven't learned objects deeply yet, so let's understand this gradually।


Static Method

Example:

public class Calculator {

    static int add(
            int first,
            int second
    ) {
        return first + second;
    }
}

The method belongs to:

Calculator class

not to a specific Calculator object।


Calling a Static Method from the Same Class

public class Main {

    public static void main(String[] args) {
        greet();
    }

    static void greet() {
        System.out.println(
                "Hello"
        );
    }
}

Because both methods are static and belong to the same class, main() can call:

greet();

directly।


Calling a Static Method from Another Class

Suppose:

public class MathHelper {

    static int square(
            int number
    ) {
        return number * number;
    }
}

If the method is accessible, it can conceptually be called using the class name:

MathHelper.square(
        5
);

Later we'll study access modifiers such as:

public
private
protected

which determine whether another class can access the method।


Familiar Static Methods

You've already used static APIs।

Example:

Math.max(
        10,
        20
);

max() is a static method on:

Math

Another example:

Integer.parseInt(
        "42"
);

parseInt() is static।

Another:

String.valueOf(
        100
);

These calls do not require creating a separate utility object first।


Static Method Example

public class PriceCalculator {

    public static long calculateTotal(
            long price,
            int quantity
    ) {
        return price * quantity;
    }
}

Usage:

long total =
        PriceCalculator.calculateTotal(
                500,
                4
        );

main() Is Static

The standard entry point:

public static void main(
        String[] args
)

is static because the JVM needs to call it without first requiring you to manually create a Main object।

This lets Java start the application directly from the class entry point।


Static Fields

A field can also be static।

Example:

static int count =
        0;

This value belongs to the class rather than an individual object।


Constants Are Common Static Fields

Example:

static final int MAX_ATTEMPTS =
        3;

or:

static final String PLATFORM_NAME =
        "LiveKlass";

The conventional name for constants is:

UPPER_SNAKE_CASE

static final

Example:

static final int MAX_LESSONS =
        50;

At a basic level:

static → belongs to the class
final  → cannot be reassigned after initialization

Later we will explore final more deeply।


Don't Make Everything Static

Beginners often discover that making everything static solves compilation errors।

That can lead to code such as:

static String courseName;
static String learnerName;
static int enrollmentCount;
static boolean published;

and dozens of static methods modifying this shared state।

This becomes difficult to maintain।

Once we learn objects, many pieces of state will belong to objects instead।


Static vs Instance Method — Preview

Static:

class Calculator {

    static int add(
            int a,
            int b
    ) {
        return a + b;
    }
}

Called through:

Calculator.add(
        10,
        20
);

Instance method conceptually looks like:

class Course {

    void publish() {
        // change this course
    }
}

and will later be called on a specific object:

course.publish();

Difference:

Static method
→ behavior associated with the class

Instance method
→ behavior associated with a specific object

We will study this properly in the OOP modules।


Static Methods Cannot Directly Use Instance State

We'll preview this now।

Suppose:

class Course {

    String title;

    static void printTitle() {
        System.out.println(
                title
        );
    }
}

This does not work because a static method does not automatically know:

Which Course object's title?

There might be:

Course A
Course B
Course C

A static method has no this object instance।

We'll revisit this when learning objects।


When Static Methods Make Sense

Static methods often fit operations that:

Do not depend on object-specific state
Represent utility-like calculations
Create or transform values
Serve as application entry points

Examples:

Math.max(...)
Integer.parseInt(...)

or our simple:

calculateTotal(...)

during fundamentals lessons।


Method Overloading

Java allows multiple methods to have the same name if their parameter lists are different।

This is called:

Method overloading

Example:

static void greet() {
    System.out.println(
            "Hello!"
    );
}

static void greet(
        String name
) {
    System.out.println(
            "Hello, "
            + name
            + "!"
    );
}

Both methods are named:

greet

but their parameters differ।


Calling Overloaded Methods

greet();

calls:

static void greet()

while:

greet(
        "Sakib"
);

calls:

static void greet(
        String name
)

Java chooses the matching method based on the argument list।


Overloading by Number of Parameters

Valid:

static int add(
        int first,
        int second
) {
    return first + second;
}

static int add(
        int first,
        int second,
        int third
) {
    return first
            + second
            + third;
}

Calls:

add(
        10,
        20
);

and:

add(
        10,
        20,
        30
);

Java can distinguish them by parameter count।


Overloading by Parameter Types

Valid:

static int doubleValue(
        int value
) {
    return value * 2;
}

static double doubleValue(
        double value
) {
    return value * 2;
}

Calls:

doubleValue(
        10
);

uses the int version।

doubleValue(
        10.5
);

uses the double version।


Overloading by Parameter Order

This can also technically create different signatures:

static void show(
        String name,
        int age
) {
}

static void show(
        int age,
        String name
) {
}

These methods have different parameter sequences।

But be careful: creating overloads that differ only by parameter order can make APIs confusing।


Return Type Alone Cannot Overload a Method

Invalid:

static int getValue() {
    return 10;
}

static String getValue() {
    return "10";
}

These are not valid overloads।

Why?

Both parameter lists are:

()

Java cannot select a method based only on the expected return type।


Method Signature

For overloading purposes, a method signature is primarily determined by:

Method name
+
Parameter types/order

Return type does not make the signature unique for overloading।


Parameter Names Do Not Matter for Overloading

Invalid:

static void print(
        int number
) {
}

static void print(
        int value
) {
}

Both signatures are effectively:

print(int)

Changing the parameter variable name does not create a new overload।


Example: Course Price Formatting

static void printPrice(
        long price
) {
    System.out.println(
            price
    );
}

static void printPrice(
        String label,
        long price
) {
    System.out.println(
            label
            + ": "
            + price
    );
}

Usage:

printPrice(
        499_000L
);

or:

printPrice(
        "Course price",
        499_000L
);

Why Overloading Can Be Useful

Overloading allows one conceptual operation to support different forms of input।

Example:

print(...)

Java itself heavily uses overloaded methods।

For example:

System.out.println(
        10
);

and:

System.out.println(
        "Hello"
);

println() supports many parameter types।


println() Is Overloaded

Conceptually, PrintStream provides overloads such as:

println(int)
println(long)
println(double)
println(boolean)
println(char)
println(String)
println(Object)

That is why the same method name works with many kinds of data।


Overload Resolution

When you call an overloaded method, Java looks for the most appropriate compatible method।

Example:

static void show(
        int value
) {
    System.out.println(
            "int"
    );
}

static void show(
        double value
) {
    System.out.println(
            "double"
    );
}

Call:

show(
        10
);

Output:

int

because 10 is an int literal and there is an exact int overload।


Numeric Widening

Suppose only:

static void show(
        long value
) {
    System.out.println(
            "long"
    );
}

Then:

show(
        10
);

can compile because Java can widen:

int → long

Exact Match Is Generally Preferred

If both exist:

show(int)
show(long)

and argument is:

10

Java chooses:

show(int)

because it is the more specific exact match।


Ambiguous Overloads

Poorly designed overloads can create ambiguity।

Example:

static void process(
        String value
) {
}

static void process(
        Integer value
) {
}

Then:

process(
        null
);

is ambiguous because null is compatible with both reference types and neither is clearly more specific relative to the other in a way that resolves this case।

Compiler error protects you from an unclear call।


Don't Overload Unrelated Behavior

Bad:

static void process(
        String course
) {
    // publish course
}

static void process(
        int learnerId
) {
    // delete learner
}

They technically overload, but the operations are unrelated।

Better:

publishCourse(...)
deleteLearner(...)

Same method name should usually represent the same conceptual behavior।


Overloading vs Different Method Names

Suppose:

static void register(
        String email
)

and:

static void register(
        String email,
        String name
)

If both represent learner registration, overloads may be reasonable।

But if behaviors have importantly different semantics, explicit names may be clearer।

Overloading is a tool, not a goal।


Default Arguments Do Not Exist in Java

Some languages support:

parameter = defaultValue

directly in method declarations।

Java does not have general default arguments।

Overloading is sometimes used to provide default behavior।

Example:

static void greet() {
    greet(
            "Guest"
    );
}

static void greet(
        String name
) {
    System.out.println(
            "Hello, "
            + name
    );
}

Now:

greet();

uses the default:

Guest

Delegating Between Overloads

Notice:

static void greet() {
    greet(
            "Guest"
    );
}

Instead of duplicating logic:

static void greet() {
    System.out.println(
            "Hello, Guest"
    );
}

static void greet(
        String name
) {
    System.out.println(
            "Hello, "
            + name
    );
}

the simpler overload delegates to the more general one।

This keeps one source of behavior।


Practical Example

public class Main {

    public static void main(String[] args) {
        printCourse(
                "Java"
        );

        printCourse(
                "Backend Development",
                799_000L
        );
    }

    static void printCourse(
            String title
    ) {
        printCourse(
                title,
                0L
        );
    }

    static void printCourse(
            String title,
            long priceInPaisa
    ) {
        System.out.println(
                "Course: "
                + title
        );

        System.out.println(
                "Price: "
                + priceInPaisa
        );
    }
}

The one-parameter overload reuses the two-parameter implementation।


Static Methods and Overloading Together

Static methods can be overloaded just like instance methods।

Example:

static int max(
        int first,
        int second
) {
    return first > second
            ? first
            : second;
}

static long max(
        long first,
        long second
) {
    return first > second
            ? first
            : second;
}

Scope and Overloading Are Different Concepts

Scope answers:

Where can this name be accessed?

Overloading answers:

Which method with this name matches these arguments?

Do not confuse them।


Practical Example: Score Application

public class Main {

    static final int PASS_MARK =
            60;

    public static void main(String[] args) {
        printResult(
                "Subu",
                85
        );

        printResult(
                55
        );
    }

    static void printResult(
            String name,
            int score
    ) {
        String result =
                getResult(
                        score
                );

        System.out.println(
                name
                + ": "
                + result
        );
    }

    static void printResult(
            int score
    ) {
        printResult(
                "Learner",
                score
        );
    }

    static String getResult(
            int score
    ) {
        if (
                score >= PASS_MARK
        ) {
            return "Passed";
        }

        return "Failed";
    }
}

Concepts involved:

static constant
local variables
method parameters
return value
method overloading
delegation
scope

Common Beginner Mistake 1: Using a Variable Outside Its Scope

if (true) {
    int number =
            10;
}

System.out.println(
        number
);

Invalid।


Common Beginner Mistake 2: Thinking Locals Persist Between Calls

static void increment() {
    int number =
            0;

    number++;

    System.out.println(
            number
    );
}

Repeated calls print:

1
1
1

not:

1
2
3

Common Beginner Mistake 3: Making Everything Static

This may compile initially:

static String courseTitle;
static int lessonCount;
static boolean published;

but it creates shared state and does not model independent objects properly।

We'll solve that using classes and instances later।


Common Beginner Mistake 4: Overloading Only by Return Type

Invalid:

static int value() {
    return 1;
}

static String value() {
    return "1";
}

Common Beginner Mistake 5: Overloading Only by Parameter Name

Invalid:

static void show(
        int age
) {
}

static void show(
        int score
) {
}

Both are:

show(int)

Common Beginner Mistake 6: Creating Confusing Overloads

Avoid APIs where callers cannot easily predict what an overload means।

Clarity is more important than minimizing method names।


Practice 1: Scope

What is wrong?

static void example() {
    if (true) {
        String message =
                "Hello";
    }

    System.out.println(
            message
    );
}

Answer

message exists only inside the if block।


Practice 2: Local Variable Lifetime

Predict the output:

public class Main {

    public static void main(String[] args) {
        show();
        show();
    }

    static void show() {
        int number =
                5;

        number++;

        System.out.println(
                number
        );
    }
}

Answer

6
6

Each call receives a new local number


Practice 3: Static Field

Predict:

public class Main {

    static int number =
            5;

    public static void main(String[] args) {
        show();
        show();
    }

    static void show() {
        number++;

        System.out.println(
                number
        );
    }
}

Answer

6
7

The static field is shared across both method calls।


Practice 4: Create an Overload

Create two methods:

static void printMessage(
        String message
)

and:

static void printMessage(
        String message,
        int times
)

The second should print the message repeatedly।


Possible Solution

static void printMessage(
        String message
) {
    System.out.println(
            message
    );
}

static void printMessage(
        String message,
        int times
) {
    for (
            int i = 0;
            i < times;
            i++
    ) {
        System.out.println(
                message
        );
    }
}

Practice 5: Delegating Overload

Improve:

static void greet() {
    System.out.println(
            "Hello, Guest!"
    );
}

static void greet(
        String name
) {
    System.out.println(
            "Hello, "
            + name
            + "!"
    );
}

so the no-argument overload delegates।

Solution

static void greet() {
    greet(
            "Guest"
    );
}

static void greet(
        String name
) {
    System.out.println(
            "Hello, "
            + name
            + "!"
    );
}

Practice 6: Valid or Invalid?

Are these valid overloads?

static void calculate(
        int value
) {
}

static void calculate(
        long value
) {
}

Answer

Yes।

Parameter types differ:

calculate(int)
calculate(long)

Practice 7: Valid or Invalid?

static int calculate(
        int value
) {
    return value;
}

static long calculate(
        int value
) {
    return value;
}

Answer

Invalid।

Return type alone cannot distinguish overloads।


Practice 8: Predict Overload Selection

static void show(
        int value
) {
    System.out.println(
            "int"
    );
}

static void show(
        double value
) {
    System.out.println(
            "double"
    );
}

Call:

show(
        5
);

Answer

int

The exact int match is selected।


True or False

  1. A local variable can always be accessed from every method.
  2. Method parameters are local to the method invocation.
  3. Variables declared inside an if block are normally limited to that block.
  4. Local variables automatically preserve values between method calls.
  5. static means the method belongs to the class.
  6. main() is static.
  7. Every field should be static.
  8. Methods can be overloaded by parameter count.
  9. Methods can be overloaded only by changing the return type.
  10. Parameter names determine whether two methods are valid overloads.
  11. Overloaded methods should usually represent related behavior.
  12. One overload may call another overload.

Answers

1. False
2. True
3. True
4. False
5. True
6. True
7. False
8. True
9. False
10. False
11. True
12. True

Knowledge Check

Question 1

What does scope describe?

Question 2

What is a local variable?

Question 3

Can two different methods each have a local variable with the same name?

Question 4

What is block scope?

Question 5

Do local variables automatically retain values across separate method calls?

Question 6

At a high level, what does static mean?

Question 7

Why should we avoid making all application state static?

Question 8

What is method overloading?

Question 9

Can methods be overloaded using only different return types?

Question 10

What parts of a method distinguish overloads?

Question 11

Why might one overload delegate to another?

Question 12

Why can poorly designed overloads be harmful?


Knowledge Check Answers

Answer 1

Scope describes the region of code where a variable, method, or member name can be accessed।

Answer 2

A variable declared inside a method or block for use within that local execution context।

Answer 3

Yes. Their scopes are separate।

Answer 4

Variables declared inside a block such as an if, loop, or explicit {} block are accessible only within the allowed scope of that block।

Answer 5

No. Each method invocation gets its own local execution state।

Answer 6

static means the member belongs to the class rather than requiring a specific object instance।

Answer 7

Shared mutable state becomes difficult to track and does not properly model independent objects or responsibilities।

Answer 8

Defining multiple methods with the same name but different parameter lists।

Answer 9

No।

Answer 10

The method name together with the parameter types, number, and order determines the overload signature।

Answer 11

To reuse the main implementation and avoid duplicated behavior।

Answer 12

They can create ambiguity and make it difficult for callers to understand which behavior a call represents।


Lesson Summary

এই lesson-এ আমরা তিনটি important Java concepts শিখেছি:

Scope
static
Method overloading

We learned:

  • Local variables belong to limited scopes
  • Different methods may use the same local variable names independently
  • Parameters belong to method scope
  • if, loops, and other blocks can create smaller scopes
  • Smaller useful scopes improve readability
  • Local variables do not automatically persist across calls
  • Static fields represent class-level shared state
  • Unnecessary shared mutable state should be avoided
  • static methods belong to a class rather than a specific object instance
  • main() is static
  • Many standard Java APIs expose static methods
  • Instance methods will later represent behavior on specific objects
  • Method overloading allows related methods to share a name
  • Overloads may differ by parameter count, types, or order
  • Return type alone cannot create a valid overload
  • Parameter names do not distinguish overloads
  • Java selects an appropriate overload based on the supplied arguments
  • One overload can delegate to another to reduce duplication
  • Overloading should improve API clarity, not make it more confusing

The main design ideas are:

Keep data visible only where it is needed.

Use static behavior deliberately.

Use overloading when multiple forms represent
the same conceptual operation.

Next Lesson

পরবর্তী lesson:

Introduction to Arrays

আমরা শিখব:

  • Why arrays exist
  • Declaring arrays
  • Creating arrays
  • Array indexes
  • Reading and updating elements
  • Default values
  • length
  • Array initialization syntax
  • Common indexing mistakes
  • Reference behavior
  • Basic array traversal