Java Varargs: Variable-length Arguments (varargs) භාවිතය SC Guide

Java Varargs: Variable-length Arguments (varargs) භාවිතය SC Guide

Mastering Java Varargs: Flexible Arguments

කෝ වරෙල්ලා! අද අපි කතා කරන්න යන්නේ Java වල තියෙන මාරම කූල් feature එකක් ගැන. ඒ තමයි Varargs. අහලා තියෙනවද? නැතිනම් අවුලක් නෑ, අද අපි ඒක හොඳටම පාඩම් කරගමු. Software Engineer කෙනෙක් විදියට ඔයාට මේක ගොඩක් වැදගත් වෙයි. විශේෂයෙන්ම method parameters manage කරද්දි මේකෙන් ගොඩක් වෙලාවට අපේ වැඩ ලේසි වෙනවා.

නිකන් හිතන්නකෝ, ඔයාට method එකක් තියෙනවා numbers ටිකක් print කරන්න. සමහර වෙලාවට එක number එකක්, තව වෙලාවට තුනක්, තව වෙලාවට දහයක් වගේ විවිධ ප්‍රමාණවලින් numbers එන්න පුලුවන්. සාමාන්‍ය විදියට නම් ඔයාට මේ හැම number ප්‍රමාණයකටම වෙන වෙනම method overload කරන්න වෙනවා නේද? අප්පේ, ඒක ලොකු අවුලක් නේ. එතනට තමයි අපේ Varargs එන්නේ hero වගේ!

Varargs කියන්නේ Variable-length Arguments. ඒ කියන්නේ, ඔයාගේ method එකට ඕනෑම parameter ප්‍රමාණයක් (zero or more) accept කරන්න පුලුවන් විදියට හදන්න පුළුවන්. මේකෙන් අපේ code එක ගොඩක් clean වෙනවා වගේම කියවන්නත්, maintain කරන්නත් ලේසි වෙනවා. එහෙනම් හරි කටවහගෙන වැඩේට බහිමු!

Varargs කියන්නේ මොකද්ද?

හරි, දැන් බලමු Varargs කියන්නේ හරියටම මොකද්ද කියලා. Java වල method එකකට parameter එකක් විදියට data_type... variableName විදියට define කරොත් ඒක තමයි Varargs. මෙතන තියෙන ... තමයි magic එක. මේකෙන් කියවෙන්නේ මේ parameter එකට එක object එකක් හරි, කීපයක් හරි, නැත්නම් කිසිම object එකක් නැතුව හරි pass කරන්න පුළුවන් කියන එකයි. compiler එකට නම් මේක array එකක් විදියට තමයි treat කරන්නේ.

සරල උදාහරණයක් බලමු:

public class VarargsExample {

    public static void printNumbers(int... numbers) {
        System.out.println("Printing numbers:");
        for (int num : numbers) {
            System.out.println(num);
        }
    }

    public static void main(String[] args) {
        // Zero arguments
        printNumbers(); 
        System.out.println("---");

        // One argument
        printNumbers(10);
        System.out.println("---");

        // Multiple arguments
        printNumbers(10, 20, 30, 40);
        System.out.println("---");

        // An array as an argument
        int[] myNums = {50, 60, 70};
        printNumbers(myNums);
    }
}

මේ code එක බැලුවම තේරෙනවා නේද, printNumbers කියන method එකට අපි විවිධ ප්‍රමාණවලින් int values pass කරලා තියෙනවා. int... numbers කියන්නේ numbers කියන parameter එක int type එකේ variable-length arguments ටිකක් accept කරනවා කියන එකයි. Method එක ඇතුලේ numbers කියන එක int[] array එකක් විදියට තමයි behave කරන්නේ. ඒ නිසා අපිට for-each loop එකක් use කරලා ඒක iterate කරන්න පුළුවන්.

Varargs භාවිතය සහ රීති

Varargs භාවිතය හරි ලේසියි. ඒත් ටිකක් අවධානය යොමු කරන්න ඕන පොඩි නීති ටිකක් තියෙනවා. මේ නීති ටික මතක තියාගත්තොත් කිසිම අවුලක් නැතුව වැඩේ කරගන්න පුළුවන්.

1. Varargs Parameter එක Methods වල අන්තිම Parameter එක වෙන්න ඕනේ.

මේක තමයි Varargs වල ප්‍රධානම රීතිය. Varargs parameter එක හැමවිටම method එකේ parameter list එකේ අන්තිමටම තියෙන්න ඕනේ. නැත්නම් compiler එකට ඒක identify කරන්න අමාරු වෙනවා. Code example එකක් බලමු:

// Correct: Varargs is the last parameter
public void displayDetails(String name, int age, String... hobbies) {
    System.out.println("Name: " + name + ", Age: " + age);
    System.out.print("Hobbies: ");
    for (String hobby : hobbies) {
        System.out.print(hobby + " ");
    }
    System.out.println();
}

// Incorrect: Varargs is not the last parameter - will cause a compile-time error
// public void invalidMethod(int... numbers, String message) { }

displayDetails method එකේ hobbies කියන Varargs parameter එක අන්තිමටම තියෙන නිසා ප්‍රශ්නයක් නෑ. හැබැයි invalidMethod එකේ වගේ numbers කියන Varargs parameter එකට පස්සේ message කියන String parameter එකක් දැම්මොත් compiler error එකක් එනවා. මොකද compiler එකට තේරෙන්නේ නෑ numbers කියන Varargs එක ඉවර වෙන්නේ කොතනින්ද කියලා.

2. එක් Method එකකට එක Varargs Parameter එකක් පමණයි.

අපිට method එකක් ඇතුලේ Varargs parameters දෙකක් භාවිතා කරන්න බෑ. ඒකත් compiler ambiguity එකක් නිසා තමයි. මේකත් පළවෙනි රීතියටම සම්බන්ධයි.

// Incorrect: More than one varargs parameter - will cause a compile-time error
// public void printMultipleLists(int... list1, String... list2) { }

// Correct: Only one varargs parameter
public void processItems(String category, String... items) {
    System.out.println("Category: " + category);
    for (String item : items) {
        System.out.println(" - " + item);
    }
}

ඔයාලට Varargs parameters දෙකක් වගේ දෙයක් ඕන නම්, වෙන වෙනම array parameters දෙකක් විදියට declare කරලා pass කරන්න පුළුවන්. ඒක තමයි හොඳම විසඳුම.

3. Varargs Method Call කරද්දී විවිධ ආකාර

Varargs method එකක් call කරද්දී අපිට options කීපයක් තියෙනවා. මේක මාරම flexible.

  • කිසිම Argument එකක් නොදී Call කිරීම: Varargs parameter එකට zero arguments pass කරන්න පුළුවන්. මේ වෙලාවේ method එක ඇතුලේ Varargs array එක empty array එකක් විදියට තමයි behave කරන්නේ. null නෙවෙයි, empty array එකක්.
  • තනි Argument එකක් දී Call කිරීම: int... numbers වගේ තැනකට int value එකක් විතරක් pass කරන්න පුළුවන්.
  • බහු Arguments දී Call කිරීම: Comma වලින් වෙන් කරලා අවශ්‍ය තරම් arguments pass කරන්න පුළුවන්.
  • Array එකක් Argument එකක් විදියට දී Call කිරීම: ஏற்கனவே තියෙන array එකක් Varargs method එකට pass කරන්නත් පුළුවන්. මේක හරිම පහසුයි.

මේ හැම එකටම උදාහරණයක් බලමු:

public class VarargsInvocation {

    public static void displayMessage(String... messages) {
        if (messages.length == 0) {
            System.out.println("No messages to display.");
        } else {
            System.out.println("Displaying " + messages.length + " messages:");
            for (String msg : messages) {
                System.out.println("- " + msg);
            }
        }
    }

    public static void main(String[] args) {
        // 1. Call with zero arguments
        System.out.println("--- Zero arguments ---");
        displayMessage(); 

        // 2. Call with one argument
        System.out.println("--- One argument ---");
        displayMessage("Hello Java!"); 

        // 3. Call with multiple arguments
        System.out.println("--- Multiple arguments ---");
        displayMessage("Good morning", "Have a great day", "Keep coding!"); 

        // 4. Call with an array
        System.out.println("--- Array as argument ---");
        String[] greetings = {"Hi", "How are you?", "Welcome!"};
        displayMessage(greetings); 
    }
}

මේ code එක run කරලා බලන්න. Varargs කොච්චර flexible ද කියලා ඔයාටම තේරෙයි.

සාමාන්‍ය භාවිත අවස්ථා

Varargs කොහෙද ගොඩක් වෙලාවට භාවිත වෙන්නේ කියලා දැනගන්න එකත් වැදගත්. Java වල core library වල පවා Varargs ගොඩක් තැන්වල පාවිච්චි වෙනවා. හොඳම උදාහරණය තමයි System.out.printf().

ඔයා printf() use කරලා ඇති නේද? ඒකට ඕන තරම් arguments pass කරන්න පුලුවන්. ඒකත් Varargs භාවිතයෙන් හදපු method එකක්. මේ වගේ scenarios වලදී Varargs මාරම ප්‍රයෝජනවත්.

  • System.out.printf() වගේ formatting methods: විවිධ data types වල values ගොඩක් format කරලා print කරන්න ඕන වෙලාවට.
  • Custom logging methods: log messages ගොඩක් එක්ක, විවිධ log levels වලට logging කරන්න ඕන වෙලාවට.
  • Utility methods: Numbers sum කරන, average හොයන, strings concatenate කරන වගේ පොදු utility methods හදද්දි.
  • SQL query building: Dynamic SQL queries වල parameters set කරද්දි.

සරල utility method එකකට උදාහරණයක් බලමු:

public class SimpleCalculator {

    public static int sum(int... numbers) {
        int total = 0;
        for (int num : numbers) {
            total += num;
        }
        return total;
    }

    public static String concatenate(String separator, String... words) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < words.length; i++) {
            result.append(words[i]);
            if (i < words.length - 1) {
                result.append(separator);
            }
        }
        return result.toString();
    }

    public static void main(String[] args) {
        System.out.println("Sum of 1, 2, 3: " + sum(1, 2, 3)); // 6
        System.out.println("Sum of 10, 20, 30, 40, 50: " + sum(10, 20, 30, 40, 50)); // 150
        System.out.println("Sum of nothing: " + sum()); // 0

        System.out.println("Concatenated words: " + concatenate("-", "apple", "banana", "cherry")); // apple-banana-cherry
        System.out.println("Concatenated single word: " + concatenate(" ", "hello")); // hello
        System.out.println("Concatenated nothing: " + concatenate(" ", "")); // (empty string)
    }
}

මෙන්න මේ වගේ methods හදද්දි Varargs හරිම පහසුයි නේද? overloading ගොඩක් අඩු වෙනවා.

Varargs වල වාසි සහ අවාසි

ඕනෑම feature එකක වගේ Varargs වලත් වාසි වගේම අවාසිත් තියෙනවා. ඒ දෙකම දැනගෙන සිටීම වැදගත්.

වාසි (Pros):

  • Flexible Argument Counting: method එකක් call කරද්දි අවශ්‍ය arguments ප්‍රමාණයට අනුව parameters සකස් කරන්න පුළුවන්.
  • Explicit Array Creation අවශ්‍ය නොවීම: method එකට array එකක් pass කරන්න ඕනෙ නම්, array එකක් create කරලා pass කරන්න ඕන නෑ. compiler එක ඒක අපිට කරලා දෙනවා.

Code Readability සහ Maintainability වැඩිවීම: Varargs නැතුව නම් අපිට එකම method එක විවිධ parameter ගණන් වලට overload කරන්න වෙනවා. උදාහරණයක් විදියට, sum method එකට int එකක්, දෙකක්, තුනක් වගේ overload දාන්න වෙනවා. ඒක code එක අවුල් කරනවා. Varargs use කරද්දි, එක method එකකින් ඔක්කොම parameter ගණන් handle කරන්න පුළුවන්.

// Without Varargs
public int sum(int a) { return a; }
public int sum(int a, int b) { return a + b; }
public int sum(int a, int b, int c) { return a + b + c; }
// ... and so on

// With Varargs - much cleaner!
public int sum(int... numbers) { /* logic */ }

අවාසි (Cons):

  • Performance Overhead (අඩු වශයෙන්): Varargs method එකක් call කරද්දි, compiler එක arguments ටික array එකක් විදියට convert කරනවා. මේ array එක heap එකේ create වෙනවා. method එක ගොඩක් වෙලාවට call කරනවා නම්, මේ array creation එකෙන් performance එකට පොඩි බලපෑමක් වෙන්න පුළුවන්. හැබැයි සාමාන්‍ය භාවිතයේදී මේක එච්චර ලොකු ප්‍රශ්නයක් නෙවෙයි.

null Argument: Varargs parameter එකක් null විදියට pass කරන්නත් පුළුවන්. ඒත් method එක ඇතුලේ ඒක handle නොකරොත් NullPointerException එකක් එන්න පුළුවන්.

public static void process(String... items) {
    if (items == null) {
        System.out.println("Items array is null.");
        return;
    }
    System.out.println("Processing " + items.length + " items.");
    // ... further processing
}

public static void main(String[] args) {
    process(null); // This is allowed, but will cause NPE if not handled inside process method.
    process(); // This creates an empty array (items.length is 0)
}

null argument එකක් pass කරලා, method එක ඇතුලේ items.length වගේ access කරන්න ගියොත් NPE එකක් එනවා. ඒ නිසා null check එකක් දාන්න පුගලීව තියාගන්න.

Ambiguity with Overloading: Varargs එක්ක method overloading පාවිච්චි කරද්දි පොඩි ambiguity එකක් ඇතිවෙන්න පුළුවන්.

public class OverloadAmbiguity {
    public static void display(int... nums) {
        System.out.println("Varargs method: " + nums.length + " numbers.");
    }

    public static void display(int num1, int num2) {
        System.out.println("Two int method: " + num1 + ", " + num2);
    }

    public static void main(String[] args) {
        display(10, 20); // Which method will be called?
        // This will call display(int num1, int num2) because it's a more specific match.
        // If display(int num1, int num2) wasn't present, then display(int... nums) would be called.
        // The compiler prefers the most specific method match.
    }
}

මේ වගේ තැන් වලදී compiler එක ambiguity එකක් දෙනවා. එහෙම නැතිව වඩාත් specific method signature එකට preference එක දෙනවා. ඒ නිසා overloading එක්ක Varargs පාවිච්චි කරද්දි සැලකිලිමත් වෙන්න ඕනේ.

නිගමනය

හොඳයි යාලුවනේ! අද අපි Java වල තියෙන Varargs කියන නියම feature එක ගැන හොඳටම ඉගෙන ගත්තා. Method parameters handle කරද්දි අපිට තියෙන complexity එක අඩු කරගන්න මේක මාරම උදව්වක්. Code එක clean කරගන්න, maintain කරගන්න වගේම flexible methods හදන්නත් Varargs වලින් පුළුවන්.

මතක තියාගන්න Varargs parameter එක හැමවිටම අන්තිම parameter එක විදියට තියෙන්න ඕනේ වගේම, එක් method එකකට එක Varargs parameter එකක් විතරයි use කරන්න පුළුවන් කියන එක.

දැන් ඔයාලට පුළුවන් මේක ඔයාලගේ Java projects වලට implement කරලා බලන්න. මොනවා හරි ප්‍රශ්න තියෙනවා නම්, comments section එකේ දාන්න. අපි ඒ ගැන කතා කරමු. ආයෙත් ඉක්මනටම හම්බෙමු! Keep coding!