ใช่เป็นเพียงน้ำตาลประโยคสำหรับT...
T[]
พารามิเตอร์ทางการสุดท้ายในรายการเป็นพิเศษ มันอาจเป็นพารามิเตอร์arityตัวแปรที่ระบุโดย elipsis ตามประเภท
ถ้าพารามิเตอร์อย่างเป็นทางการที่ผ่านมาเป็นตัวแปร arity ตัวแปรประเภทก็ถือว่าการกำหนดพารามิเตอร์อย่างเป็นทางการของประเภทT
T[]
วิธีการนั้นเป็นวิธีarity ตัวแปร มิฉะนั้นจะเป็นวิธีarity คงที่ การเรียกใช้เมธอด arity แบบตัวแปรอาจมีการแสดงออกของอาร์กิวเมนต์ที่เกิดขึ้นจริงมากกว่าพารามิเตอร์ทางการ นิพจน์อาร์กิวเมนต์จริงทั้งหมดที่ไม่สอดคล้องกับพารามิเตอร์ที่เป็นทางการก่อนพารามิเตอร์ arity ตัวแปรจะถูกประเมินและผลลัพธ์ที่เก็บไว้ในอาร์เรย์ที่จะถูกส่งผ่านไปยังการเรียกใช้เมธอด
นี่คือตัวอย่างที่แสดงให้เห็น:
public static String ezFormat(Object... args) {
String format = new String(new char[args.length])
.replace("\0", "[ %s ]");
return String.format(format, args);
}
public static void main(String... args) {
System.out.println(ezFormat("A", "B", "C"));
// prints "[ A ][ B ][ C ]"
}
และใช่ดังกล่าวข้างต้นmain
เป็นวิธีการที่ถูกต้องเพราะอีกครั้งเป็นเพียงString...
String[]
นอกจากนี้เนื่องจากมีอาร์เรย์ covariant ที่String[]
เป็นObject[]
เพื่อให้คุณยังสามารถโทรezFormat(args)
ทางใดทางหนึ่ง
ดูสิ่งนี้ด้วย
Varargs gotchas # 1: การผ่าน null
วิธีการแก้ไข varargs นั้นค่อนข้างซับซ้อนและบางครั้งก็ทำสิ่งที่อาจทำให้คุณประหลาดใจ
ลองพิจารณาตัวอย่างนี้:
static void count(Object... objs) {
System.out.println(objs.length);
}
count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!
เนื่องจากวิธีการ varargs ได้รับการแก้ไขจะเรียกคำสั่งสุดท้ายด้วยobjs = null
ซึ่งแน่นอนว่าจะทำให้มีNullPointerException
objs.length
หากคุณต้องการให้null
อาร์กิวเมนต์หนึ่งตัวกับพารามิเตอร์ varargs คุณสามารถทำอย่างใดอย่างหนึ่งต่อไปนี้:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
คำถามที่เกี่ยวข้อง
ต่อไปนี้เป็นตัวอย่างของคำถามที่ผู้คนถามเมื่อจัดการกับ varargs:
Vararg gotchas # 2: การเพิ่มอาร์กิวเมนต์พิเศษ
ดังที่คุณทราบแล้วสิ่งต่อไปนี้จะไม่ทำงาน
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
เนื่องจากวิธีการ varargs ทำงานezFormat
จริงได้รับ 2 ข้อโต้แย้งเป็นครั้งแรกที่เป็นที่เป็นที่สองString[]
String
หากคุณกำลังส่งอาเรย์ไปยัง varargs และคุณต้องการให้อิลิเมนต์นั้นได้รับการยอมรับว่าเป็นอาร์กิวเมนต์แต่ละตัวและคุณต้องเพิ่มอาร์กิวเมนต์พิเศษจากนั้นคุณไม่มีทางเลือกนอกจากสร้างอาร์เรย์อื่นที่รองรับองค์ประกอบเพิ่มเติม
ต่อไปนี้เป็นวิธีการช่วยเหลือที่มีประโยชน์:
static <T> T[] append(T[] arr, T lastElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
arr[N] = lastElement;
return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
System.arraycopy(arr, 0, arr, 1, N);
arr[0] = firstElement;
return arr;
}
ตอนนี้คุณสามารถทำสิ่งต่อไปนี้:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(append(myArgs, "Z")));
// prints "[ A ][ B ][ C ][ Z ]"
System.out.println(ezFormat(prepend(myArgs, "Z")));
// prints "[ Z ][ A ][ B ][ C ]"
Varargs gotchas # 3: ผ่านอาร์เรย์แบบดั้งเดิม
มันไม่ "ทำงาน":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs ใช้ได้กับประเภทอ้างอิงเท่านั้น การล็อคอัตโนมัติไม่สามารถใช้กับอาเรย์ดั้งเดิมได้ ผลงานดังต่อไปนี้:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"