จำนวนพารามิเตอร์สูงสุดในการประกาศเมธอด Java


134

จำนวนพารามิเตอร์สูงสุดที่เมธอดใน Java สามารถมีได้คือเท่าใดและเพราะเหตุใด

ฉันใช้ Java 1.8 บนระบบ Windows 64 บิต

คำตอบทั้งหมดบน StackOverflow เกี่ยวกับเรื่องนี้บอกว่าขีด จำกัด ทางเทคนิคคือ 255 พารามิเตอร์โดยไม่ระบุสาเหตุ

เพื่อความแม่นยำ 255 สำหรับวิธีคงที่และ 254 สำหรับไม่คงที่ ( thisในกรณีนี้จะเป็น 255)

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

แต่สิ่งนี้ใช้ได้สำหรับintและประเภท 4 ไบต์ทั้งหมดเท่านั้น ฉันทำการทดสอบกับlongพารามิเตอร์บางอย่างและฉันสามารถประกาศพารามิเตอร์ 127 รายการในกรณีนั้นเท่านั้น

ด้วยStringพารามิเตอร์จำนวนที่อนุญาตที่ฉันอนุมานได้จากการทดสอบคือ 255 (อาจเป็นเพราะขนาดอ้างอิงคือ 4 ไบต์ใน Java?)

แต่เนื่องจากฉันใช้ระบบ 64 บิตขนาดอ้างอิงจึงควรกว้าง 8 ไบต์และด้วยStringพารามิเตอร์จำนวนสูงสุดที่อนุญาตควรเป็น 127 ซึ่งคล้ายกับlongประเภท

ขีด จำกัด นี้ถูกนำไปใช้อย่างไร?

ขีด จำกัด มีส่วนเกี่ยวข้องกับขนาดสแต็กของวิธีการหรือไม่?

หมายเหตุ: ฉันจะไม่ใช้พารามิเตอร์เหล่านี้ในวิธีการใด ๆ จริงๆ แต่คำถามนี้เป็นเพียงการชี้แจงพฤติกรรมที่แน่นอนเท่านั้น


40
7 ถ้าคุณไม่อยากบ้าไปกับความสามารถในการอ่าน (ฉันรู้ว่าคุณกำลังถามอะไร)
อดัม

14
<= 4ฉันจะยืนยัน สิ่งอื่น ๆ ที่ควรจะรวมอยู่ในวัตถุ
Vivin Paliath

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

20
@Jesper เพราะคำถามนี้ถามความรู้เกี่ยวกับข้อกำหนด JVM คำถามนี้ไม่ได้ถามว่า "How to do this or that?" แทนที่จะถามว่า "ทำไมฉันถึงต้องทำเช่นนั้น" ... +1 คำถามที่น่าสนใจ Userv
Amit

2
@amit สิ่งที่ฉันคิด OP แค่อยากรู้เกี่ยวกับเรื่องนี้
Evan Carslake

คำตอบ:


110

ขีด จำกัด นั้นถูกกำหนดไว้ในข้อกำหนด JVM :

จำนวนพารามิเตอร์เมธอดถูก จำกัด ไว้ที่ 255โดยนิยามของตัวบอกเมธอด (§4.3.3) ซึ่งขีด จำกัด จะมีหนึ่งหน่วยสำหรับสิ่งนี้ในกรณีของการเรียกใช้อินสแตนซ์หรือวิธีการอินเทอร์เฟซ

ส่วน§4.3.3ให้ข้อมูลเพิ่มเติม:

วิธีการให้คำอธิบายที่ถูกต้องเท่านั้นถ้ามันแสดงให้เห็นถึงวิธีการพารามิเตอร์ที่มีความยาวรวมของ 255 หรือน้อยกว่าที่มีความยาวที่มีผลงานในการนี้ในกรณีของอินสแตนซ์หรืออินเตอร์เฟซที่ใช้วิธีสวด

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

สังเกตของคุณเป็นจุดบนพื้นฐานคำคู่ ( long/ doubleต้อง) สองเท่าของขนาดปกติ 4 ตัวแปรไบต์และ 4 ไบต์อ้างอิงตัวอย่างวัตถุ

ในส่วนสุดท้ายของคำถามของคุณที่เกี่ยวข้องกับระบบ 64 บิตข้อกำหนดจะกำหนดจำนวนหน่วยที่พารามิเตอร์มีส่วนส่วนของข้อกำหนดนั้นยังคงต้องปฏิบัติตามแม้บนแพลตฟอร์ม 64 บิต JVM 64 บิตจะรองรับพารามิเตอร์อินสแตนซ์ 255 รายการ (เช่น 255 ของคุณStrings) โดยไม่คำนึงถึงขนาดตัวชี้ของวัตถุภายใน


10
ฉันขอเพิ่มคำตอบนี้ว่าในสถาปัตยกรรม 64 บิตสแต็กยังเป็น 64 บิต ดังนั้นเนื่องจากข้อ จำกัด ในการนับพารามิเตอร์คือขนาดสแต็กที่ถูกผูกไว้สแต็ก 64 บิตจึงอนุญาตให้จัดเก็บการอ้างอิงอ็อบเจ็กต์ 255 รายการเดียวกัน การรักษาเฉพาะlongและdoubleไม่คำนึงถึงสถาปัตยกรรมระบบเกิดขึ้นในหลาย ๆ จุดของข้อมูลจำเพาะและดูเหมือนจะเป็นยุค 32 บิตที่เหลืออยู่
Sergei

ฉันอยู่ในระหว่างการแก้ไขเฉพาะส่วนนั้น :) ตกลงกันว่าข้อกำหนดยังคงต้องได้รับการเคารพแม้ในแพลตฟอร์มที่แตกต่างกัน
Umberto Raimondi

1
ใช่ถ้าจำนวนพารามิเตอร์เป็นฟังก์ชันของ word-size นั่นจะทำให้การพกพาไม่สะดวก คุณไม่สามารถรวบรวมโปรแกรม Java เดียวกันได้สำเร็จบนสถาปัตยกรรมที่แตกต่างกัน
Vivin Paliath

3
Varargs จะกลายเป็นอาร์เรย์วัตถุสามารถใช้ได้เพียงครั้งเดียวในรายการพารามิเตอร์และครอบครองตำแหน่งสุดท้าย เมื่อพิจารณาทั้งหมดนี้ฉันจะบอกว่าการใช้ varargs จำนวนพารามิเตอร์สามารถ "ขยาย" เป็น 254 + Integer.MAX_VALUE (อย่างน้อยสำหรับโปรแกรมเมอร์ ... พารามิเตอร์ยังคงเป็น 255) ดังนั้นการใช้เคล็ดลับนี้คุณสามารถมี Integer ได้ MAX_VALUE พารามิเตอร์ออบเจ็กต์
Umberto Raimondi

1
@MrTsjolder ลองดูคำตอบนี้สำหรับ varargs
Vivin Paliath

11

ส่วน 4.3.3ของข้อกำหนด JVM มีข้อมูลที่คุณต้องการ:

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

ดังนั้นจึงดูเหมือนว่าโฮสต์เครื่องเป็น 32 บิตหรือ 64 บิตจะไม่มีผลกับจำนวนพารามิเตอร์ หากคุณสังเกตเห็นเอกสารจะพูดในรูปของ "หน่วย" โดยที่ความยาวของ "หน่วย" หนึ่งหน่วยเป็นฟังก์ชันของขนาดคำ หากจำนวนพารามิเตอร์แปรผันตรงกับขนาดคำจะมีปัญหาในการพกพา คุณจะไม่สามารถรวบรวมโปรแกรม Java เดียวกันบนสถาปัตยกรรมที่แตกต่างกันได้ (สมมติว่าอย่างน้อยหนึ่งวิธีใช้พารามิเตอร์จำนวนสูงสุดบนสถาปัตยกรรมที่มีขนาดคำใหญ่กว่า)


10

ฉันพบปัญหาที่น่าสนใจจากจดหมายข่าวเกี่ยวกับเรื่องนี้http://www.javaspecialists.eu/archive/Issue059.html

พูลค่าคงที่ต่อคลาสหรือต่ออินเทอร์เฟซถูก จำกัด ไว้ที่ 65535 รายการโดยฟิลด์ค่าคงที่ 16 บิตของโครงสร้าง ClassFile สิ่งนี้ทำหน้าที่เป็นขีด จำกัด ภายในสำหรับความซับซ้อนทั้งหมดของคลาสเดียวหรืออินเทอร์เฟซ จำนวนรหัสต่อวิธีที่ไม่ใช่เนทีฟและไม่ใช่นามธรรมถูก จำกัด ไว้ที่ 65536 ไบต์โดยขนาดของดัชนีใน exception_table ของแอตทริบิวต์ Code ในแอตทริบิวต์ LineNumberTable และในแอตทริบิวต์ LocalVariableTable

จำนวนตัวแปรโลคัลที่มากที่สุดในอาร์เรย์ตัวแปรโลคัลของเฟรมที่สร้างขึ้นจากการเรียกใช้เมธอดถูก จำกัด ไว้ที่ 65535 โดยขนาดของรายการ max_locals ของแอตทริบิวต์ Code ที่ให้รหัสของวิธีการ โปรดทราบว่าค่าของประเภท long และ double ถือเป็นการสงวนตัวแปรโลคัลสองตัวแปรและมีส่วนร่วมสองหน่วยต่อค่า max_locals ดังนั้นการใช้ตัวแปรโลคัลของประเภทเหล่านั้นจะลดขีด จำกัด นี้

จำนวนฟิลด์ที่อาจประกาศโดยคลาสหรืออินเทอร์เฟซถูก จำกัด ไว้ที่ 65535 ตามขนาดของรายการ fields_count ของโครงสร้าง ClassFile โปรดสังเกตว่าค่าของรายการ fields_count ของโครงสร้าง ClassFile ไม่รวมเขตข้อมูลที่สืบทอดมาจาก superclasses หรือ superinterfaces

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.