วันนี้เราจะมาพูดถึงเรื่อง varargs ในภาษา Java กัน Varargs - หรืออาร์กิวเมนต์แบบแปรผัน - เป็นเทคโนโลยีที่ช่วยให้คุณสามารถสร้างวิธีการที่มีจำนวนอาร์กิวเมนต์ได้ตามต้องการ ในบทความนี้ เราจะได้เรียนรู้วิธีสร้างวิธีการดังกล่าว อภิปรายว่าเหตุใดจึงจำเป็นต้องใช้ varargs และเมื่อใดจึงควรใช้วิธีดังกล่าวดีที่สุด
เรามีสองทางเลือก ตัวเลือก 1 - โอเวอร์โหลด:
วาราร์กคืออะไร?
Varargs เป็นอาร์กิวเมนต์ที่มีความยาวผันแปรได้: คุณลักษณะที่ปรากฏใน JDK5 Varargs อนุญาตให้เราสร้างวิธีการที่มีจำนวนอาร์กิวเมนต์ตามต้องการ โดยทั่วไปแล้ว มันเป็นไปได้ที่จะสร้างวิธีการดังกล่าวมาก่อน จริงอยู่ที่การทำเช่นนี้ไม่สะดวกนัก ลองยกตัวอย่าง สมมติว่าเราจำเป็นต้องเขียนวิธีการที่จะรับอาร์กิวเมนต์จำนวนเต็มตามจำนวนที่ต้องการแล้วบวกเข้าด้วยกันclass Calculator {
int sum(int a, int b){...};
int sum(int a, int b, int c){...};
int sum(int a, int b, int c, int d){...};
int sum(int a, int b, int c, int d, int e){...};
}
แต่มีปัญหาสองประการเกี่ยวกับการโอเวอร์โหลด ประการแรก มันไม่ชัดเจนเสมอไปว่าถึงเวลาที่ต้องหยุด และประการที่สอง มันยุ่งยาก อาร์เรย์จะดีกว่า ตัวเลือก 2 - อาร์เรย์:
class Calculator {
int sum(int[] numbers){...};
}
ด้วย array มันไม่ยุ่งยากอีกต่อไป และ array ดูเหมือนจะไม่มีอะไรเลย... จนกว่าจะถึงเวลาเรียกใช้เมธอด:
public static void main(String... sss) {
Calculator calculator = new Calculator();
int[] arguments = new int[7];
arguments[0] = 1;
arguments[1] = 10;
arguments[2] = 123;
arguments[3] = 234;
arguments[4] = 6234;
arguments[5] = 12;
arguments[6] = 8;
int sum = calculator.sum(arguments);
}
เราเห็นด้วย คุณสามารถเขียนทุกอย่างให้สั้นลงได้แน่นอน แต่ก่อนอื่น ฉันยังคงต้องการแสดงให้เห็นถึงความไม่สะดวกในการใช้อาร์เรย์เป็นอาร์กิวเมนต์ที่มีความยาวผันแปรได้ และประการที่สอง แม้ว่าเราจะเขียนดังนี้:
int[] arguments = {1,10,123,234,6234,12,8};
int sum = calculator.sum(arguments);
ถ้าอย่างนั้นเราก็ยังไม่กำจัดโค้ดที่มากเกินไปออกไป อย่างไรก็ตาม ด้วยการเปิดตัว Java 5 ฟีเจอร์ Varargs ดูเหมือนจะช่วยแก้ปัญหาเหล่านี้ได้ ทำให้สามารถส่งอาร์กิวเมนต์ไปยังเมธอดได้ไม่จำกัดจำนวน มีลักษณะดังนี้:
public class Calculator {
public static void main(String... sss) {
Calculator calculator = new Calculator();
int sum = calculator.sum(1,10,123,234,6234,12,8);
}
int sum(int... numbers){
return Arrays.stream(numbers).sum();
}
}
เอาล่ะ เรามาสรุปกัน Varargs เป็นอาร์กิวเมนต์ที่มีความยาวผันแปรได้ ซึ่งเป็นคุณสมบัติที่ปรากฏพร้อมกับการเปิดตัว Java 5 ต่อไป เราจะมาดูกฎบางอย่างสำหรับการทำงานกับ Varargs อย่างละเอียดยิ่งขึ้น
กฎ 5 ข้อของวาราร์ก
กฎข้อที่ 1อาร์กิวเมนต์ Vararg (หรืออาร์กิวเมนต์ที่มีความยาวแปรผัน/ตามอำเภอใจ) จะถูกระบุด้วยจุดไข่ปลาดังนี้:String... words
Integer... numbers
Person... people
Cat... cats
กฎข้อที่ 2อาร์กิวเมนต์ที่มีความยาวตามใจชอบสามารถระบุเป็นอาร์กิวเมนต์ของบางวิธีได้เท่านั้น:
void print(String... words)
int sum(Integer... numbers)
void save(Person... people)
void feed(Cat... cats)
กฎข้อที่ 3แต่ละอาร์กิวเมนต์ที่มีความยาวผันแปรดังกล่าวในเนื้อความของวิธีการคืออาร์เรย์:
void print(String... words){
for (int i = 0; i < words.length; i++) {
System.out.println(words[i]);
}
}
กฎข้อที่ 4อาร์กิวเมนต์ Vararg จะต้องเป็นอาร์กิวเมนต์สุดท้ายในรายการอาร์กิวเมนต์ของเมธอด:
void print(String... words, String anotherWord) // - Так нельзя!
void print(String... words, int someNumber) // - Так нельзя!
void print(String anotherWord, String... words) // - Так можно
void print(int someNumber, String... words) // - Так можно
กฎข้อที่ 5:แม้ว่า varargs จะเป็นอาร์เรย์ แต่เมื่อเรียกใช้เมธอดที่รับอาร์กิวเมนต์ที่มีความยาวผันแปรได้ ก็ไม่จำเป็นต้องสร้างอาร์เรย์ มันก็เพียงพอแล้วและเป็นที่ต้องการเพียงแค่แสดงรายการอาร์กิวเมนต์ที่จำเป็นโดยคั่นด้วยเครื่องหมายจุลภาค:
public class Main {
public static void main(String... sss) {
print("How","же","прекрасно","изучать","Java");
}
static void print(String... words){
for (int i = 0; i < words.length; i++) {
System.out.println(words[i]);
}
}
}
ตัวอย่างของ varargs
ในตัวอย่างด้านล่าง เราจะเขียนวิธีการที่รับค่า varargs ที่ประกอบด้วยจำนวนเต็ม และแสดงจำนวนองค์ประกอบที่ส่งผ่านและผลรวมขององค์ประกอบเหล่านั้น ลองส่งทั้งอาร์เรย์และชุดจำนวนเต็มให้กับวิธีนี้ (ทั้งสองตัวเลือกถูกต้อง):public static void main(String... sss) {
int[] a = new int[100];
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
sum(a);
sum(1,2,3,4,5,6,7,8,9,10);
}
static void sum(int... numbers){
final int length = numbers.length;
final int sum = Arrays.stream(numbers).sum();
final String lineSeparator = System.lineSeparator();
System.out.printf("Кол-во элементов для сложения - %d, сумма - %d%s", length, sum, lineSeparator);
}
หลังจากรันโปรแกรมจะแสดงผล:
Кол-во элементов для сложения - 100, сумма - 4950
Кол-во элементов для сложения - 10, сумма - 55
เป็นที่น่าสังเกตว่าวิธีนี้System.out.printf
ยอมรับ varargs ด้วย ถ้าเราดูโค้ดของวิธีนี้เราจะเห็นสิ่งนี้:
public PrintStream printf(String format, Object ... args) {
return format(format, args);
}
อีกวิธีหนึ่งที่ใช้กันอย่างแพร่หลายซึ่งยอมรับ varags คือString.format
. รหัสของมันแสดงอยู่ด้านล่าง:
public static String format(String format, Object... args) {
return new Formatter().format(format, args).toString();
}
เมื่อใดจึงควรใช้ varargs?
คำตอบสำหรับคำถามนี้ขึ้นอยู่กับว่าใครถาม หากไคลเอนต์ของ API บางตัวถามคำถามที่คล้ายกันซึ่งมีวิธีการแบบ varargs คำตอบก็คือ “ใช้วิธีการดังกล่าวให้บ่อยที่สุดเท่าที่จะทำได้” สำหรับโค้ดไคลเอ็นต์ varargs ทำให้ชีวิตง่ายขึ้นมากโดยทำให้โค้ดเขียนง่ายขึ้นและอ่านง่ายขึ้น อย่างไรก็ตาม หากนักพัฒนา API ถามคำถามนี้และสงสัยว่าคุณควรสร้างวิธีการด้วย varargs บ่อยแค่ไหน คำตอบก็คือ “คุณไม่ควรใช้ varargs บ่อยๆ” ควรใช้ Varargs เมื่อประโยชน์ของการใช้งานชัดเจนเท่านั้น คุณควรหลีกเลี่ยงการโอเวอร์โหลดเมธอดด้วย varargs เนื่องจากจะทำให้ไคลเอนต์โค้ดของคุณเข้าใจได้ยากว่าจริงๆ แล้วเมธอดโอเวอร์โหลดใดที่ถูกเรียกบทสรุป
ดังนั้นเราจึงได้กล่าวถึงหัวข้ออื่นแล้ว varargs ใน Java เราคิดออกว่ามันคืออะไร เราได้อธิบายกฎสำหรับการใช้ varargs เราดูตัวอย่างวิธีการที่มีการโต้แย้งที่มีความยาวตามใจชอบ และยังได้พูดคุยกันว่าเมื่อใดควรใช้ varargs และเมื่อใดควรงดใช้ เป็นการบ้าน คุณสามารถใช้วิธีการต่อไปนี้:- เขียน
void
วิธีการที่รับชุดข้อมูลจำนวนเต็มและส่งกลับค่าเฉลี่ยเลขคณิต - เขียน
void
วิธีการที่รับชุดของสตริงและพิมพ์คำที่ยาวที่สุด - เขียนวิธีการที่ส่งคืน
boolean
และรับตัวแปรประเภทเป็นอาร์กิวเมนต์แรกString
และชุดboolean
ของความยาวตัวแปรเป็นอาร์กิวเมนต์ถัดไป
ค่าที่เป็นไปได้String
คือAND
,OR
,XOR
. หากอาร์กิวเมนต์แรกมีค่าอื่น วิธีการนั้นจะต้องส่งข้อIllegalArgumentException
ยกเว้น
วิธีการจะต้องดำเนินการเชิงตรรกะ (ระบุไว้ในอาร์กิวเมนต์แรก) ในแต่ละองค์ประกอบของอาร์กิวเมนต์ varargs และส่งคืนผลลัพธ์ของการคำนวณ
- "AND" จริง จริง เท็จ - จะส่งคืนค่าเท็จ
- "OR", false, true, false, false - จะส่งกลับค่าจริง
GO TO FULL VERSION