อธิบายอาร์กิวเมนต์บรรทัดคำสั่งของ Java: ตั้งแต่พื้นฐานสู่รูปแบบการออกแบบเชิงปฏิบัติ

目次

1. บทนำ

จุดประสงค์ของบทนี้

อาร์กิวเมนต์ในบรรทัดคำสั่งของ Java เป็นฟีเจอร์พื้นฐานที่ทำให้โปรแกรมสามารถรับค่าจากภายนอกในขณะทำงานและปรับพฤติกรรมตามค่าเหล่านั้นได้ บทความนี้อธิบายทุกอย่างตั้งแต่ความหมายของ String[] args จนถึงรูปแบบการออกแบบที่ใช้ในแอปพลิเคชันจริง ในบทนี้เราจะชี้แจงว่าอาร์กิวเมนต์ในบรรทัดคำสั่งทำอะไรได้บ้างและในสถานการณ์ใดที่มันมีประโยชน์

อาร์กิวเมนต์ในบรรทัดคำสั่งคืออะไร?

แอปพลิเคชัน Java มักเริ่มทำงานจากเมธอด main ที่มีลายเซ็นดังต่อไปนี้:

public class App {
    public static void main(String[] args) {
        // args is an array of strings passed at runtime
    }
}

args คือ อาเรย์ของสตริง ที่เก็บค่าที่ผู้ใช้ระบุเมื่อโปรแกรมถูกเรียกใช้งาน ตัวอย่างเช่น:

javac App.java
java App Tokyo 2025 debug

ในกรณีนี้ args มีค่า ["Tokyo", "2025", "debug"].
หากไม่มีอาร์กิวเมนต์ใด ๆ args.length จะเป็น 0.

การใช้งานทั่วไป

  • สลับสภาพแวดล้อมหรือเป้าหมาย : โหมด production vs testing, รหัสภูมิภาค, ภาษา, ระดับล็อก.
  • ระบุเป้าหมายการประมวลผลจากภายนอก : ชื่อไฟล์อินพุต, ไดเรกทอรี, URL, รายการ ID.
  • การประมวลผลแบบแบตช์และอัตโนมัติ : ส่งวันที่หรือช่วงให้กับงานที่กำหนดเวลา, แทรกพารามิเตอร์จาก pipeline CI/CD.

ในทุกกรณี พฤติกรรมของโปรแกรมสามารถเปลี่ยน โดยไม่ต้องคอมไพล์ใหม่ ทำให้อาร์กิวเมนต์ในบรรทัดคำสั่งเหมาะกับการใช้ร่วมกับสคริปต์เชลล์และตัวจัดตารางงานเช่น cron.

ปัจจัยสำคัญในการออกแบบ

  • แยกอาร์กิวเมนต์ที่จำเป็นและไม่จำเป็น : หากอาร์กิวเมนต์ที่บังคับต้องหายไป ให้หยุดทำงานอย่างชัดเจนพร้อมข้อความช่วยเหลือหรือรหัสออก.
  • ตรวจสอบตั้งแต่ต้น : แปลงค่าตัวเลขหรือวันที่ให้เร็วที่สุดและให้คำแนะนำที่ชัดเจนเมื่ออินพุตไม่ถูกต้อง.
  • กำหนดค่าเริ่มต้น : อาร์กิวเมนต์ที่ไม่บังคับควรมีค่าเริ่มต้นที่ปลอดภัยเพื่อให้โปรแกรมยังคงทำงานได้.
  • ความอ่านง่ายและการบำรุงรักษา : หลีกเลี่ยงการเข้าถึงอาเรย์โดยตรง; ให้ทำการพาร์สอาร์กิวเมนต์เป็นอ็อบเจ็กต์โครงสร้าง (DTO หรือคลาสคอนฟิก).

การเลือกใช้ระหว่างอาร์กิวเมนต์, ตัวแปรสภาพแวดล้อม, และไฟล์คอนฟิก

  • อาร์กิวเมนต์ในบรรทัดคำสั่ง : เหมาะสำหรับการแทนที่ชั่วคราวหรือการตั้งค่าที่เจาะจงงาน (ลำดับความสำคัญสูงสุด, การกำหนดค่าท้องถิ่น).
  • ตัวแปรสภาพแวดล้อม : เหมาะสำหรับข้อมูลลับหรือ endpoint ที่แตกต่างตามสภาพแวดล้อมการปรับใช้.
  • ไฟล์คอนฟิก (properties/JSON/YAML) : เหมาะสำหรับการจัดการหลายการตั้งค่าอย่างเป็นระบบพร้อมการนำกลับมาใช้ใหม่และการควบคุมเวอร์ชัน.

โดยปฏิบัติ การออกแบบแบบสามชั้น — ไฟล์คอนฟิก + ตัวแปรสภาพแวดล้อม + อาร์กิวเมนต์ในบรรทัดคำสั่ง — ทำงานได้ดี โดยอาร์กิวเมนต์ในบรรทัดคำสั่งจะมีลำดับความสำคัญสูงสุด.

ตัวอย่างขั้นต่ำ: แสดงรายการอาร์กิวเมนต์ทั้งหมด

public class ArgsEcho {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("No arguments were provided.");
            System.out.println("Example: java ArgsEcho input.txt debug");
            return;
        }
        System.out.println("Received arguments:");
        for (int i = 0; i < args.length; i++) {
            System.out.printf("args[%d] = %s%n", i, args[i]);
        }
    }
}

สิ่งที่บทความนี้จะครอบคลุมต่อไป (Roadmap)

  • การดำเนินการพื้นฐาน กับ String[] args (การตรวจสอบความยาว, การเข้าถึงสมาชิก)
  • การแปลงประเภท (int/double/boolean และการจัดการข้อยกเว้น)
  • รูปแบบตัวเลือก เช่น -v , --help , และ --mode=prod
  • การตั้งค่า IDE และวิธีส่งอาร์กิวเมนต์ระหว่างการทดสอบ
  • การจัดการข้อผิดพลาดและข้อพิจารณาด้านความปลอดภัย (อินพุตไม่ถูกต้อง, การจัดการข้อยกเว้น)
  • ตัวอย่างเชิงปฏิบัติ (การประมวลผลไฟล์, การสลับโหมด, การควบคุมระดับล็อก)

ก่อนอื่น จำหลักการสำคัญนี้ไว้: ทุกอาร์กิวเมนต์จะถูกส่งเป็นสตริงและต้องถูกแปลงและตรวจสอบอย่างปลอดภัยก่อนนำไปใช้ ในบทต่อไป เราจะสำรวจไวยากรณ์พื้นฐานและรูปแบบทั่วไปพร้อมตัวอย่างโค้ดที่เป็นรูปธรรม.

2. อาร์กิวเมนต์ในบรรทัดคำสั่งคืออะไร?

ความสัมพันธ์ระหว่างเมธอด main และ String[] args

จุดเริ่มต้นของแอปพลิเคชัน Java คือเมธอด main ซึ่งกำหนดดังต่อไปนี้:

public static void main(String[] args)

ที่นี่, args หมายถึง “arguments” และเป็น อาร์เรย์ของสตริงที่เก็บค่าที่ถูกส่งมาจากภายนอกเมื่อโปรแกรมเริ่มทำงาน.
เมื่อคุณรันโปรแกรม, ค่าที่ระบุหลัง java ClassName แยกด้วยช่องว่างจะถูกเก็บเป็นลำดับใน args.

ตัวอย่าง: การรันพร้อมอาร์กิวเมนต์

javac Sample.java
java Sample apple orange banana

ในกรณีนี้, เนื้อหาของ args มีดังต่อไปนี้:

IndexValue
args[0]“apple”
args[1]“orange”
args[2]“banana”

กล่าวคือ, args ทำงานเหมือน รายการสตริงที่มีความยาวเปลี่ยนแปลงได้, ซึ่งทำให้คุณสามารถส่งค่าจำนวนใดก็ได้.
หากไม่มีอาร์กิวเมนต์ใดระบุ, args.length จะเป็น 0 (มันจะไม่มีค่า null).

ตัวอย่างการทำงานและผลลัพธ์

public class Sample {
    public static void main(String[] args) {
        System.out.println("Number of arguments: " + args.length);
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "] = " + args[i]);
        }
    }
}
java Sample dog cat

ผลลัพธ์:

Number of arguments: 2
args[0] = dog
args[1] = cat

จุดสำคัญที่นี่คือ อาร์กิวเมนต์ทั้งหมดจะได้รับเป็นสตริง.
หากคุณต้องการใช้เป็นตัวเลขหรือค่า boolean, คุณต้องแปลงอย่างชัดเจนในภายหลัง.

ควรใช้ Command-Line Arguments เมื่อใด?

อาร์กิวเมนต์บรรทัดคำสั่งมักใช้ในสถานการณ์ต่อไปนี้:

  • สลับโหมดการทำงาน ตัวอย่าง: java Server start กับ java Server stop เพื่อทำการต่างกัน.
  • ระบุเส้นทางไฟล์หรือค่าการกำหนดค่า ตัวอย่าง: java ReportGenerator /data/input.csv
  • ส่งพารามิเตอร์ชั่วคราวระหว่างการทำสคริปต์ ตัวอย่าง: วันที่, ชื่อผู้ใช้, หรือเป็นตัวแทนที่เบา ๆ ของตัวแปรสภาพแวดล้อม.

กรณีการใช้งานเหล่านี้ช่วยเพิ่มความยืดหยุ่นและทำให้โปรแกรมสามารถ ควบคุมโดยอินพุตภายนอกโดยไม่ต้องคอมไพล์ใหม่.

พฤติกรรมเมื่อไม่มีอาร์กิวเมนต์ใดถูกให้

เมธอด main ใน Java จะมี String[] args เสมอ, แม้ไม่มีอาร์กิวเมนต์ใดถูกส่ง.
หากโปรแกรมทำงานโดยไม่มีอาร์กิวเมนต์, args.length == 0, ดังนั้นการเพิ่มการตรวจสอบเงื่อนไขเช่นต่อไปนี้จึงแนะนำ:

if (args.length == 0) {
    System.out.println("No arguments were specified. Exiting.");
    return;
}

นี่แสดงคุณลักษณะสำคัญของ command-line arguments: พวกมันทำให้โปรแกรมรับอินพุตภายนอกที่ยืดหยุ่นได้ตั้งแต่เริ่มต้น.

สรุป

  • String[] args เก็บรายการของอาร์กิวเมนต์ที่ส่งในขณะรันโปรแกรม.
  • อาร์กิวเมนต์ทั้งหมดจะถูกจัดการเป็น สตริง .
  • แม้ไม่มีอาร์กิวเมนต์ใดให้, args จะไม่เป็น null แต่เป็นอาร์เรย์ว่าง.
  • การใช้อาร์กิวเมนต์ทำให้โปรแกรม ยืดหยุ่น, ใช้ซ้ำได้, และง่ายต่อการอัตโนมัติ .

ในบทต่อไป, เราจะต่อยอดจากพื้นฐานนี้และแสดง รูปแบบการใช้งานพื้นฐานและตัวอย่างโค้ดที่เป็นรูปธรรม สำหรับการดึงและใช้ค่าจาก args.

3. การใช้งานพื้นฐานและตัวอย่างโค้ด

ไวยากรณ์พื้นฐานของ Command-Line Arguments

เพื่อใช้ command-line arguments, คุณต้องดึงค่าจาก String[] args ก่อน, ซึ่งถูกส่งไปยังเมธอด main.
เนื่องจาก args เป็นอาร์เรย์, คุณสามารถเข้าถึงแต่ละองค์ประกอบโดยใช้ดัชนีของมัน.

public class CommandExample {
    public static void main(String[] args) {
        System.out.println("Number of arguments: " + args.length);
        if (args.length > 0) {
            System.out.println("First argument: " + args[0]);
        } else {
            System.out.println("No arguments were specified.");
        }
    }
}

รันโปรแกรมดังนี้:

javac CommandExample.java
java CommandExample hello

ผลลัพธ์:

Number of arguments: 1
First argument: hello

ตามที่แสดงด้านบน, args[0] เก็บค่าที่ส่งเป็นค่าแรก.
หากมีอาร์กิวเมนต์หลายค่า, สามารถเข้าถึงได้เป็น args[1], args[2], เป็นต้น.

การประมวลผลอาร์กิวเมนต์ทั้งหมดพร้อมกัน

เมื่อจำนวนอาร์กิวเมนต์เปลี่ยนแปลงได้, การประมวลผลโดยใช้ลูปเป็นวิธีที่ทั่วไป
ตัวอย่างต่อไปนี้จะแสดงอาร์กิวเมนต์ที่ได้รับทั้งหมดตามลำดับ

public class PrintArgs {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("No arguments were provided.");
            System.out.println("Example: java PrintArgs apple orange banana");
            return;
        }

        System.out.println("Argument list:");
        for (int i = 0; i < args.length; i++) {
            System.out.printf("args[%d] = %s%n", i, args[i]);
        }
    }
}

การดำเนินการ:

java PrintArgs apple orange banana

ผลลัพธ์:

Argument list:
args[0] = apple
args[1] = orange
args[2] = banana

การใช้ลูปทำให้โปรแกรมของคุณสามารถจัดการกับจำนวนอาร์กิวเมนต์ใด ๆ ได้
เป็นแนวปฏิบัติที่ดีเสมอให้ตรวจสอบความยาวของอาร์เรย์ก่อนเข้าถึงสมาชิก

การกำหนดความหมายตามลำดับอาร์กิวเมนต์

คุณสามารถกำหนดความหมายเฉพาะให้กับอาร์กิวเมนต์ตามลำดับของมันได้
เช่น ตัวอย่างโปรแกรมที่รับชื่อไฟล์, โหมด, และแฟล็กการเขียนทับ

public class FileProcessor {
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: java FileProcessor <file> <mode> <overwrite>");
            System.out.println("Example: java FileProcessor data.txt verbose true");
            return;
        }

        String fileName = args[0];
        String mode = args[1];
        boolean overwrite = Boolean.parseBoolean(args[2]);

        System.out.println("File name: " + fileName);
        System.out.println("Mode: " + mode);
        System.out.println("Overwrite enabled: " + overwrite);
    }
}

ตัวอย่างการดำเนินการ:

java FileProcessor data.txt simple false

ผลลัพธ์:

File name: data.txt
Mode: simple
Overwrite enabled: false

โดยการกำหนดบทบาทให้กับตำแหน่งของอาร์กิวเมนต์, คุณสามารถควบคุมโปรแกรมได้อย่างยืดหยุ่น

ตัวอย่าง: การจัดการอาร์กิวเมนต์เป็นตัวเลข

เนื่องจากอาร์กิวเมนต์ทั้งหมดถูกส่งเป็นสตริง, จำเป็นต้องแปลงประเภทเมื่อจัดการเป็นตัวเลข
โปรแกรมต่อไปนี้รับจำนวนเต็มสองค่าและแสดงผลรวมของพวกมัน

public class SumArgs {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Please specify two integers.");
            return;
        }

        int a = Integer.parseInt(args[0]);
        int b = Integer.parseInt(args[1]);
        int sum = a + b;

        System.out.println("Sum: " + sum);
    }
}

การดำเนินการ:

java SumArgs 7 13

ผลลัพธ์:

Sum: 20

หากค่าที่ไม่ใช่ตัวเลขเช่น "abc" ถูกส่ง, จะเกิด NumberFormatException
เพื่อทำให้โปรแกรมของคุณแข็งแรงขึ้น, คุณควรเพิ่มการจัดการข้อยกเว้น

การนำไปใช้ที่ปลอดภัยพร้อมการจัดการข้อยกเว้น

public class SafeSum {
    public static void main(String[] args) {
        try {
            if (args.length < 2) {
                throw new IllegalArgumentException("Insufficient arguments. Please specify two integers.");
            }
            int a = Integer.parseInt(args[0]);
            int b = Integer.parseInt(args[1]);
            System.out.println("Sum: " + (a + b));
        } catch (NumberFormatException e) {
            System.out.println("One or more arguments cannot be interpreted as numbers.");
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
}

ด้วยการจัดการข้อยกเว้นที่เหมาะสม, โปรแกรมสามารถคืนข้อความที่ชัดเจนแทนการหยุดทำงานอย่างกะทันหันเมื่อได้รับอาร์กิวเมนต์ที่ไม่ถูกต้อง

สรุป

  • อาร์กิวเมนต์บรรทัดคำสั่งจะถูกส่งเป็นสตริงในอาเรย์ args.
  • ตรวจสอบ args.length เสมอก่อนเข้าถึงสมาชิก.
  • ใช้ลูปเพื่อจัดการจำนวนอาร์กิวเมนต์ที่เปลี่ยนแปลงได้.
  • แปลงค่าตัวเลขโดยใช้เมธอดเช่น Integer.parseInt() .
  • ใช้การจัดการข้อยกเว้นเพื่อให้พฤติกรรมเป็นมิตรกับผู้ใช้.

ในบทต่อไป เราจะทบทวน ข้อผิดพลาดทั่วไปและข้อควรระวังสำคัญ และอธิบายวิธีเขียนโค้ดที่ปลอดภัยและนำกลับมาใช้ใหม่ได้ง่ายขึ้น.

4. ข้อผิดพลาดทั่วไปและข้อควรระวัง

แม้อาร์กิวเมนต์บรรทัดคำสั่งจะเป็นกลไกที่เรียบง่าย แต่ก็มีข้อหลบหลีกหลายอย่างที่ผู้เริ่มต้นมักเจอบ่อย
บทนี้จะแนะนำข้อผิดพลาดที่พบบ่อยและวิธีแก้ปฏิบัติที่ช่วยป้องกันได้.

ข้อผิดพลาดดัชนีอาเรย์ (ArrayIndexOutOfBoundsException)

ความผิดพลาดที่พบบ่อยที่สุดคือการเข้าถึงดัชนีที่ไม่มีอยู่
เนื่องจาก args เป็นอาเรย์ การระบุดัชนีที่อยู่นอกช่วงจะทำให้เกิดข้อยกเว้นดังต่อไปนี้.

ตัวอย่าง: โค้ดที่ไม่ถูกต้อง

public class ErrorExample {
    public static void main(String[] args) {
        System.out.println(args[0]); // Error occurs if no arguments are provided
    }
}

การทำงาน:

java ErrorExample

ผลลัพธ์:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0

วิธีแก้

ตรวจสอบ args.length เสมอก่อนเข้าถึงสมาชิกของอาเรย์.

if (args.length == 0) {
    System.out.println("No arguments were specified.");
    return;
}
System.out.println("First argument: " + args[0]);

ประเด็นสำคัญ:
args จะไม่มีค่า null.
แม้ไม่มีอาร์กิวเมนต์ใด ๆ ถูกส่งเข้ามา มันยังคงเป็นอาเรย์ที่มีความยาว 0.

อาร์กิวเมนต์ทั้งหมดเป็นสตริง

อาร์กิวเมนต์บรรทัดคำสั่ง จะได้รับเป็นสตริงเสมอ
ดังนั้นจึงต้องทำการแปลงประเภทเพื่อทำการคำนวณเชิงตัวเลข.

int num = Integer.parseInt(args[0]);

หากส่งสตริงที่ไม่ใช่ตัวเลขเช่น "abc" จะทำให้เกิด NumberFormatException.

วิธีแก้: เพิ่มการจัดการข้อยกเว้น

try {
    int num = Integer.parseInt(args[0]);
    System.out.println("Input value: " + num);
} catch (NumberFormatException e) {
    System.out.println("The argument cannot be interpreted as a number. Please provide a valid value.");
}

ประเด็นสำคัญ:
การใช้ค่าอาร์กิวเมนต์โดยตรงเป็นตัวเลขนั้นเสี่ยง
ควรสมมติว่าข้อมูลที่ผู้ใช้ป้อนอาจไม่ถูกต้องเสมอ.

อาร์กิวเมนต์ที่มีช่องว่าง

ในบรรทัดคำสั่ง, ช่องว่างจะถูกพิจารณาเป็นตัวแยกอาร์กิวเมนต์
เพื่อส่งสตริงที่มีช่องว่าง คุณต้อง ใส่ไว้ในเครื่องหมายอัญประกาศคู่.

ตัวอย่าง:

java Message "Hello World"

ผลลัพธ์:

args[0] = Hello World

หากโปรแกรมถูกเรียกโดยไม่ใส่เครื่องหมายอัญประกาศ "Hello" และ "World" จะถูกพิจารณาเป็นอาร์กิวเมนต์แยกกัน.

การจัดการอักขระหลายไบต์

เมื่อส่งอักขระหลายไบต์เช่นข้อความที่ไม่ใช่ ASCII, ปัญหาเรื่องการเข้ารหัสอักขระ อาจเกิดขึ้น
โดยเฉพาะบนระบบ Windows การเข้ารหัสของคอนโซลมักเป็น MS932 (Shift_JIS) ซึ่งอาจขัดแย้งกับโปรแกรม Java ที่ใช้ UTF-8.

วิธีแก้ไข:

  • ตั้งค่าคอนโซลให้เป็น UTF-8 ก่อนรัน ( chcp 65001 )
  • ทำให้การเข้ารหัสเป็น UTF-8 ในการตั้งค่า Run ของ IDE (Eclipse / IntelliJ IDEA)
  • ระบุออปชันการเริ่มต้นของ Java -Dfile.encoding=UTF-8 .
    java -Dfile.encoding=UTF-8 Sample Hello
    

จำนวนอาร์กิวเมนต์มากเกินไปหรือยาวเกินไป

ขึ้นอยู่กับระบบปฏิบัติการ จะมี ขีดจำกัดความยาวรวมของอาร์กิวเมนต์บรรทัดคำสั่ง
บน Windows ขีดจำกัดประมาณ 8,000 ตัวอักษร, ส่วนบน Linux ประมาณ 128 KB
หากต้องจัดการข้อมูลจำนวนมาก ควรใช้ การอ่านจากไฟล์หรือ standard input แทนการใช้อาร์กิวเมนต์บรรทัดคำสั่ง.

อักขระพิเศษและการหลีกเลี่ยง (Escaping)

ในเชลล์และคอนโซล คำสั่งบางตัวอักษรเช่น <, >, และ & มีความหมายพิเศษ
เพื่อส่งเป็นอาร์กิวเมนต์ตามตัวอักษรจริง ให้ใส่ไว้ในเครื่องหมายอัญประกาศหรือทำการ escape.

ตัวอย่าง:

java SymbolTest "<tag>" "&value"

นี่ป้องกันไม่ให้เชลล์ตีความอักขระเหล่านี้เป็นตัวดำเนินการเปลี่ยนเส้นทางหรือท่อ.

ลำดับอาร์กิวเมนต์ที่ไม่ถูกต้อง

เมื่อการเรียงลำดับอาร์กิวเมนต์มีความสำคัญ ผู้ใช้อาจกำหนดค่าผิดลำดับโดยบังเอิญ
โดยเฉพาะอย่างยิ่งกับคู่เช่นชื่อไฟล์อินพุตและเอาต์พุต.

มาตรการป้องกัน:

  • ใช้ ตัวเลือกที่มีชื่อ เช่น --input=input.txt (อธิบายในบทต่อไป)
  • ให้ตัวเลือก help ที่อธิบายการใช้งานอย่างชัดเจน

สรุป

Error TypeCauseCountermeasure
Out-of-range accessAccessing arguments without checking countValidate with args.length
Number conversion errorDirect conversion of invalid stringsHandle with try-catch
Incorrect splittingNo quotation marks for spaced valuesUse double quotation marks
Encoding issuesCharacter set mismatchUnify to UTF-8
Special character errorsShell interpretationQuote or escape characters
Incorrect orderUser input mistakesNamed options or help output

ในบทต่อไป เราแนะนำ รูปแบบการออกแบบเชิงปฏิบัติ โดยใช้การแปลงประเภท, รูปแบบตัวเลือก, และค่าเริ่มต้น เพื่อสร้างเครื่องมือบรรทัดคำสั่งที่ทนทานยิ่งขึ้น.

5. การใช้งานเชิงปฏิบัติ: การแปลงประเภท, อาร์กิวเมนต์ตัวเลือก, และค่าเริ่มต้น

ในบทนี้ เราจะสำรวจเทคนิคการจัดการอาร์กิวเมนต์บรรทัดคำสั่งอย่างยืดหยุ่นและพร้อมใช้งานในสภาพการผลิต
โดยการใช้ การแปลงประเภท, อาร์กิวเมนต์แบบตัวเลือก, และ การออกแบบค่าเริ่มต้น, คุณสามารถสร้างโปรแกรมที่ปลอดภัยและใช้งานง่ายสำหรับผู้ใช้

การแปลงอาร์กิวเมนต์เป็นประเภทตัวเลขและบูลีน

อาร์กิวเมนต์บรรทัดคำสั่งทั้งหมดจะถูกส่งเป็นค่า String แต่การดำเนินการคณิตศาสตร์และตรรกะเงื่อนไขต้องการประเภทข้อมูลที่เหมาะสม

การแปลงเป็นตัวเลข

int count = Integer.parseInt(args[0]);
double rate = Double.parseDouble(args[1]);

การแปลงเป็นบูลีน

boolean debugMode = Boolean.parseBoolean(args[2]);

ตัวอย่าง: โปรแกรมคำนวณเชิงตัวเลข

public class Multiply {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java Multiply <number1> <number2>");
            return;
        }

        try {
            double a = Double.parseDouble(args[0]);
            double b = Double.parseDouble(args[1]);
            System.out.println("Result: " + (a * b));
        } catch (NumberFormatException e) {
            System.out.println("One or more arguments are not numeric.");
        }
    }
}

การดำเนินการ:

java Multiply 4.5 3

ผลลัพธ์:

Result: 13.5

ประเด็นสำคัญ:

  • ควรห่อการแปลงด้วยบล็อก try-catch เสมอเพื่อจัดการอินพุตที่ไม่ถูกต้องอย่างปลอดภัย.
  • Boolean.parseBoolean() จะคืนค่า true เฉพาะเมื่อค่าตรงกับ "true" โดยไม่สนใจตัวพิมพ์ใหญ่/เล็ก.

การออกแบบอาร์กิวเมนต์ตัวเลือกที่มีชื่อ

การออกแบบที่พึ่งพาการเรียงลำดับอาร์กิวเมนต์มักทำให้เกิดข้อผิดพลาดของมนุษย์
การใช้ตัวเลือกที่มีชื่อเช่น --key=value หรือแฟล็กเช่น -v ทำให้โปรแกรมใช้งานได้อย่างเป็นธรรมชาติ

ตัวอย่าง: การแยกวิเคราะห์ตัวเลือกที่มีชื่อ

public class OptionParser {
    public static void main(String[] args) {
        boolean verbose = false;
        String mode = "normal";
        String file = "default.txt";

        for (String arg : args) {
            if (arg.equals("-v") || arg.equals("--verbose")) {
                verbose = true;
            } else if (arg.startsWith("--mode=")) {
                mode = arg.substring("--mode=".length());
            } else if (arg.startsWith("--file=")) {
                file = arg.substring("--file=".length());
            }
        }

        System.out.println("Mode: " + mode);
        System.out.println("File: " + file);
        System.out.println("Verbose output: " + verbose);
    }
}

การดำเนินการ:

java OptionParser --mode=debug --file=log.txt -v

ผลลัพธ์:

Mode: debug
File: log.txt
Verbose output: true

ประเด็นสำคัญ:

  • startsWith() ทำให้ตรวจจับรูปแบบ --key=value ได้ง่าย.
  • สามารถระบุอาร์กิวเมนต์ในลำดับใดก็ได้.
  • เหมาะอย่างยิ่งสำหรับสคริปต์เชลล์และงานอัตโนมัติ.

การให้ค่าเริ่มต้น

สำคัญที่ต้องกำหนด ค่าเริ่มต้นที่ปลอดภัย ในกรณีที่อาร์กิวเมนต์ถูกละเว้น
ซึ่งทำให้โปรแกรมทำงานด้วยอินพุตขั้นต่ำและป้องกันการหยุดทำงานโดยไม่คาดคิด

ตัวอย่าง: โปรแกรมที่มีค่าเริ่มต้น

public class Greeting {
    public static void main(String[] args) {
        String name = "Guest";
        String lang = "ja";

        if (args.length > 0) name = args[0];
        if (args.length > 1) lang = args[1];

        if (lang.equals("en")) {
            System.out.println("Hello, " + name + "!");
        } else if (lang.equals("fr")) {
            System.out.println("Bonjour, " + name + "!");
        } else {
            System.out.println("Hello (default), " + name + "!");
        }
    }
}

Execution:

java Greeting Taro en

Output:

Hello, Taro!

Execution without arguments:

java Greeting

Output:

Hello (default), Guest!

Key points:

  • Safely handles missing arguments.
  • Behavior adapts based on the number of provided arguments.

Generalizing Option Parsing

For more complex tools, creating a dedicated option parser improves maintainability compared to manually processing args.

Example: Simple Option Parser

import java.util.HashMap;

public class SimpleParser {
    public static void main(String[] args) {
        HashMap<String, String> options = new HashMap<>();

        for (String arg : args) {
            if (arg.startsWith("--") && arg.contains("=")) {
                String[] pair = arg.substring(2).split("=", 2);
                options.put(pair[0], pair[1]);
            }
        }

        System.out.println("Parsed options:");
        for (String key : options.keySet()) {
            System.out.println(key + " = " + options.get(key));
        }
    }
}

Execution:

java SimpleParser --user=admin --port=8080 --mode=test

Output:

Parsed options:
user = admin
port = 8080
mode = test

Key points:

  • HashMap allows flexible storage of key-value pairs.
  • The parser can serve as a reusable foundation for CLI tools.

Practical Design Patterns

  • Few arguments : positional arguments are sufficient.
  • Many configuration values : use named options ( --key=value ).
  • Many optional values : define default values.
  • System integration and scripting : adopt consistent option conventions (e.g., --help , --config ).

Summary

FeatureApproachBenefit
Numeric/boolean conversionparseInt, parseDouble, parseBooleanEnables calculations and conditions
Named arguments--key=value formatOrder-independent and flexible
Default valuesVariable initialization and branchingSafe and user-friendly
Generic parserStore in HashMapEasy to extend and maintain

In the next chapter, we introduce real-world usage patterns, including file operations, batch processing, and mode switching commonly used in production environments.

6. Applied Examples: Common Real-World Patterns

This chapter demonstrates how command-line arguments are used in real-world scenarios.
By flexibly specifying arguments, you can build highly reusable tools for file operations, mode switching, and logging control.

Processing Files Specified by Command-Line Arguments

The most common use case is receiving a target file as a command-line argument.
This pattern is especially useful for automating file read/write operations.

Example: Reading and Displaying File Contents

import java.nio.file.*;
import java.io.IOException;

public class FileReaderTool {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: java FileReaderTool <filePath>");
            return;
        }

        String filePath = args[0];
        try {
            String content = Files.readString(Paths.get(filePath));
            System.out.println("=== Contents of " + filePath + " ===");
            System.out.println(content);
        } catch (IOException e) {
            System.out.println("Failed to read file: " + e.getMessage());
        }
    }
}

Execution example:

java FileReaderTool data.txt

Sample output:

=== Contents of data.txt ===
Sample data line 1
Sample data line 2

Key points:

  • Always include file existence checks and exception handling.
  • Easy to extend for batch processing of multiple files.

Switching Program Behavior by Mode

Using arguments to switch behavior allows a single program to serve multiple roles.

Example: Mode-Based Execution

public class ModeSelector {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage: java ModeSelector <mode>");
            System.out.println("Available modes: test / prod / debug");
            return;
        }

        String mode = args[0].toLowerCase();

        switch (mode) {
            case "test":
                System.out.println("Running in test mode...");
                break;
            case "prod":
                System.out.println("Running in production mode...");
                break;
            case "debug":
                System.out.println("Running in debug mode with detailed logging...");
                break;
            default:
                System.out.println("Unknown mode: " + mode);
        }
    }
}

การดำเนินการ:

java ModeSelector debug

ผลลัพธ์:

Running in debug mode with detailed logging...

ประเด็นสำคัญ:

  • มีประโยชน์สำหรับการสลับระหว่างสภาพแวดล้อมการพัฒนา, การทดสอบ, และการผลิต
  • ใช้กันอย่างแพร่หลายในสคริปต์อัตโนมัติและงานแบตช์

การคำนวณอัตโนมัติด้วยอาร์กิวเมนต์หลายค่า

ในการประมวลผลแบบแบตช์และสคริปต์ที่กำหนดเวลา, อาร์กิวเมนต์มักใช้เพื่อส่งพารามิเตอร์แบบไดนามิก
ตัวอย่างต่อไปนี้แสดงเครื่องมือคาลคูเลเตอร์ง่ายที่ทำงานกับค่าตัวเลขสองค่า.

public class Calculator {
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: java Calculator <num1> <num2> <op>");
            System.out.println("Example: java Calculator 10 5 add");
            return;
        }

        double a = Double.parseDouble(args[0]);
        double b = Double.parseDouble(args[1]);
        String op = args[2];

        switch (op) {
            case "add": System.out.println(a + b); break;
            case "sub": System.out.println(a - b); break;
            case "mul": System.out.println(a * b); break;
            case "div":
                if (b == 0) {
                    System.out.println("Division by zero is not allowed.");
                } else {
                    System.out.println(a / b);
                }
                break;
            default:
                System.out.println("Unknown operation.");
        }
    }
}

การดำเนินการ:

java Calculator 8 2 mul

ผลลัพธ์:

16.0

วิธีนี้ทำให้คุณสามารถสร้าง เครื่องมือขนาดเล็กที่เป็นมิตรต่อสคริปต์ ที่ผสานรวมได้อย่างง่ายดายกับกระบวนการทำงานอัตโนมัติ.

การระบุการกำหนดค่าด้วยอาร์กิวเมนต์แบบตัวเลือก

สำหรับการทำงานที่ยืดหยุ่นมากขึ้น, อาร์กิวเมนต์แบบตัวเลือกเช่น --key=value มีประโยชน์อย่างมาก.

public class ConfigLoader {
    public static void main(String[] args) {
        String config = "default.conf";
        boolean verbose = false;

        for (String arg : args) {
            if (arg.startsWith("--config=")) {
                config = arg.substring("--config=".length());
            } else if (arg.equals("--verbose")) {
                verbose = true;
            }
        }

        System.out.println("Configuration file: " + config);
        System.out.println("Verbose logging: " + (verbose ? "ON" : "OFF"));
    }
}

การดำเนินการ:

java ConfigLoader --config=prod.conf --verbose

ผลลัพธ์:

Configuration file: prod.conf
Verbose logging: ON

ประเด็นสำคัญ:

  • ตัวเลือกที่มีชื่อช่วยลดข้อผิดพลาดของมนุษย์เนื่องจากลำดับไม่สำคัญ
  • ใช้กันทั่วไปสำหรับเส้นทางการกำหนดค่าและโหมดการดำเนินการ

ตัวอย่างการใช้งานจริง: เครื่องมือประมวลผลไฟล์พร้อมการบันทึก

import java.nio.file.*;
import java.io.*;

public class FileCopyTool {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java FileCopyTool <input> <output> [--verbose]");
            return;
        }

        String input = args[0];
        String output = args[1];
        boolean verbose = (args.length > 2 && args[2].equals("--verbose"));

        try {
            Files.copy(Paths.get(input), Paths.get(output), StandardCopyOption.REPLACE_EXISTING);
            if (verbose) {
                System.out.println("File copied successfully: " + input + " → " + output);
            }
        } catch (IOException e) {
            System.out.println("Copy failed: " + e.getMessage());
        }
    }
}

Execution:

java FileCopyTool report.txt backup.txt --verbose

Output:

File copied successfully: report.txt → backup.txt

Key points:

  • Logging can be toggled via options for development or production use.
  • This structure is reusable as a foundation for real-world scripts.

Summary

Use CaseTypical Argument PatternScenario
File specification<file>Input/output processing, automated backups
Mode switching<mode> or --mode=debugEnvironment-specific execution
Configuration selection--config=xxx.confSystem configuration and runtime parameters
Option control--verbose, --dry-runLogging and safe test runs
Batch processing<startDate> <endDate>Scheduled jobs and data aggregation

In the next chapter, we cover how to pass command-line arguments in IDEs and testing environments, including Eclipse and IntelliJ IDEA, along with debugging tips.

7. Testing and Debugging Tips / Configuring Arguments in IDEs

Programs that use command-line arguments can be executed and tested not only from the terminal, but also within development environments such as Eclipse and IntelliJ IDEA.
This chapter explains how to configure arguments during development and introduces tips for efficient debugging.

Setting Arguments in Eclipse

In Eclipse, you can configure command-line arguments using Run Configurations.
This allows you to run programs with predefined arguments without manually typing commands each time.

Steps:

  1. From the menu bar, select Run → Run Configurations… .
  2. From the list on the left, choose the target Java Application.
  3. Open the Arguments tab.
  4. Enter arguments in the Program arguments field, separated by spaces. Example: data.txt debug true
  5. Click Apply , then Run .

The same arguments will be reused the next time you run the program.
You can also save multiple configurations to switch between different test scenarios.

Tips:

  • Arguments may be written on separate lines; Eclipse treats them as space-separated values.
  • Strings containing spaces must be enclosed in double quotation marks (e.g., "Hello World" ).
  • To change character encoding, specify -Dfile.encoding=UTF-8 in the VM arguments field.

Setting Arguments in IntelliJ IDEA

IntelliJ IDEA provides an even more streamlined configuration process.

Steps:

  1. Open Run → Edit Configurations… .
  2. Select the configuration for the target class.
  3. Enter arguments in the Program arguments field. Example: --mode=debug --file=log.txt --verbose
  4. Click OK or Apply , then run the program.

Tips:

  • Run configurations are saved per project.
  • The same configuration is used for both Run and Debug executions.
  • You can define environment variables alongside arguments to closely simulate production environments.

Understanding Differences from Command-Line Execution

There may be differences between running a program in an IDE and running it directly from the terminal, particularly regarding environment variables and working directories.

AspectIDE ExecutionTerminal Execution
Working directoryProject root (configurable)Current shell directory
Environment variablesDefined per run configurationInherited from the shell
EncodingIDE default or configuredDepends on OS and console

Being aware of these differences helps prevent issues that only occur after deployment.

Debugging Tips for Argument-Based Programs

  • Print all received arguments at startup to verify correct input.
  • Log parsed values after validation and type conversion.
  • Use breakpoints at argument parsing logic to inspect runtime values.
  • Test edge cases such as missing arguments, invalid values, and empty strings.

Summary

  • Command-line arguments can be tested efficiently within IDEs.
  • Eclipse and IntelliJ IDEA provide built-in support for argument configuration.
  • Be mindful of differences between IDE and terminal environments.
  • Effective debugging starts with validating and logging argument values.

ด้วยเทคนิคเหล่านี้ คุณสามารถพัฒนา ทดสอบ และดีบักโปรแกรม Java ที่พึ่งพาอาร์กิวเมนต์บรรทัดคำสั่งได้อย่างมั่นใจ เพื่อให้พฤติกรรมสอดคล้องกันในสภาพแวดล้อมการพัฒนาและการผลิต.