IntArray กับ Array <Int> ใน Kotlin


91

ฉันไม่แน่ใจว่าความแตกต่างระหว่าง an IntArrayและ an Array<Int>ใน Kotlin คืออะไรและทำไมฉันถึงไม่สามารถใช้แทนกันได้:

พลาด

ฉันรู้ว่าIntArrayแปลว่าint[]เมื่อกำหนดเป้าหมายJVMแต่Array<Int>แปลว่าอะไร

นอกจากนี้คุณยังสามารถมีหรือString[] YourObject[]เหตุใด Kotlin จึงมีคลาสประเภทนี้{primitive}Arrayเมื่อสามารถจัดเรียงอะไรก็ได้ในอาร์เรย์ไม่เพียง


1
ฉันเดาว่าArray<Int>คอมInteger[]ไพเลอร์ (ถ้าคอมไพเลอร์ไม่ปรับให้เหมาะสม)
Mibac


ใช่มันสมเหตุสมผลมากขอบคุณทั้งสอง!
FRR

คำตอบ:


111

Array<Int>คือInteger[]ภายใต้ประทุนในขณะIntArrayที่int[]. แค่นั้นแหละ.

ซึ่งหมายความว่าเมื่อคุณใส่IntในArray<Int>ก็จะถูกบรรจุอยู่ในกล่อง (เฉพาะที่มีInteger.valueOf()การเรียกร้อง) ในกรณีนี้IntArrayจะไม่มีการชกมวยเกิดขึ้นเนื่องจากแปลเป็นอาร์เรย์ดั้งเดิมของ Java


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

val arr = IntArray(10)
println(arr.joinToString()) // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

ในทางตรงกันข้ามArray<T>ไม่มีตัวสร้างที่รับเฉพาะพารามิเตอร์ขนาด: ต้องใช้Tอินสแตนซ์ที่ไม่เป็นค่าว่างที่ถูกต้องที่ดัชนีทั้งหมดอยู่ในสถานะที่ถูกต้องหลังการสร้าง สำหรับNumberประเภทอาจเป็นค่าเริ่มต้น0แต่ไม่มีวิธีใดในการสร้างอินสแตนซ์เริ่มต้นของประเภทที่กำหนดเองTแต่มีวิธีที่จะสร้างอินสแตนซ์เริ่มต้นของประเภทโดยพลการไม่มี

ดังนั้นเมื่อสร้าง an Array<Int>คุณสามารถใช้ตัวสร้างที่ใช้ฟังก์ชัน initializer ได้เช่นกัน:

val arr = Array<Int>(10) { index -> 0 }  // full, verbose syntax
val arr = Array(10) { 0 }                // concise version

หรือสร้างArray<Int?>เพื่อหลีกเลี่ยงการเริ่มต้นทุกค่า แต่หลังจากนั้นคุณจะถูกบังคับให้จัดการกับnullค่าที่เป็นไปได้ทุกครั้งที่อ่านจากอาร์เรย์

val arr = arrayOfNulls<Int>(10)

4
นี่เป็นการตัดสินใจที่ค่อนข้างโง่ ด้วยเหตุนี้พวกเขาจึงต้องสร้างคลาสใหม่สำหรับ primitive แต่ละประเภท ... พวกเขาสามารถใช้แบบเดียวกับบน Java
นักพัฒนา Android

1
@androiddeveloper คลาสใหม่อะไร int[]คือIntArray, Integer[]คือArray<Int>, และอื่น ๆ ที่เป็นคลาสใหม่นี้ลึกลับ? มันเหมือนกันเพียง แต่ไวยากรณ์ที่แตกต่างกัน int[]ยังเป็นชั้นเรียนอีกด้วย
Eugen Pechanec

1
@EugenPechanec นี่น่าสนใจ พวกเขาบอกว่ามันเป็นชั้นเรียนและการที่จะมีอินสแตนซ์ แต่ยัง "อินสแตนซ์ของคลาสนี้จะแสดงเป็น int []": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/... ดังนั้นฟังก์ชันเหล่านี้เป็นเพียงฟังก์ชันส่วนขยายหรือเป็นคลาสจริง? เหตุใดจึงต้องมี "IntArray" และอื่น ๆ ยังสามารถทำได้โดยใช้ไวยากรณ์ Java
นักพัฒนา Android

1
@EugenPechanec แต่ใน Java int [] ไม่ใช่คลาสไม่ใช่เหรอ? มันคือออบเจ็กต์อาร์เรย์ของสิ่งดั้งเดิม คุณไม่สามารถเข้าถึงได้คือรหัสหรือขยายจากรหัสนั้น ไม่? คลาสทั้งหมดบน Java มีอักษรตัวพิมพ์ใหญ่ที่ชื่อ นี่มันไม่ใช่
นักพัฒนา Android

1
@EugenPechanec ดังนั้นบน Kotlin จึงเป็นคลาสในขณะที่บน Java ไม่ใช่ ยังไม่เข้าใจว่าทำไม พวกเขาสามารถเพิ่มฟังก์ชันส่วนขยายได้หรือไม่? คุณสามารถขยายจาก IntArray ได้หรือไม่? เกี่ยวกับการตั้งชื่อฉันรู้ มันเป็นเพียงการประชุมและเป็นสิ่งที่ดีด้วย
นักพัฒนา Android

6

เป็นที่น่าสังเกตว่าการใช้ตัวดำเนินการสเปรด ( *) บน a varargจะส่งกลับIntArrayไฟล์. หากคุณต้องการArray<Int>คุณสามารถแปลงของคุณโดยใช้IntArray.toTypedArray()


1

อาร์เรย์ใน Kotlin เป็นคลาส (ไม่ใช่ประเภท "พิเศษ" เช่น Java)

stdlib ของ Kotlin มีคลาสวัตถุประสงค์พิเศษสำหรับอาร์เรย์ดั้งเดิมของ JVM เพื่อปรับปรุงการรวมและประสิทธิภาพของภาษา Java

กฎทั่วไปจะใช้Array<T>ยกเว้นว่ามันทำให้เกิดปัญหาเมื่อผสมกับโค้ด Java ที่มีอยู่หรือควรเรียกจากคลาส Java IntArrayสำหรับบันทึกที่ฉันไม่เคยมีการใช้งาน

คุณสามารถตรวจสอบเอกสารของภาษาเกี่ยวกับเรื่องนี้ได้ที่นี่: https://kotlinlang.org/docs/reference/basic-types.html#arrays


ฉันเชื่อว่าคุณพูดถูกเสมอเกี่ยวกับการชอบ Array <T> มากกว่า IntArray ฉันกังวลเกี่ยวกับค่าใช้จ่ายในการชกมวย / การแกะกล่องของการใช้ประเภทบรรจุกล่องเทียบกับแบบดั้งเดิม แต่ดูเหมือนว่า Kotlin จะฉลาดพอที่จะตัดสินใจว่าสภาพอากาศสามารถใช้แบบดั้งเดิมได้หรือไม่ . (แก้ไขฉันถ้าฉันผิด) "บนแพลตฟอร์ม Java ตัวเลขจะถูกจัดเก็บทางกายภาพเป็นประเภทดั้งเดิมของ JVM เว้นแต่เราต้องการการอ้างอิงตัวเลขที่เป็นโมฆะ (เช่น Int?) หรือ generics ที่เกี่ยวข้องในกรณีหลังนี้จะมีการใส่กล่องตัวเลข" จากkotlinlang.org/docs/reference/basic-types.html
FRR

@feresr ไม่ได้เป็นผู้เชี่ยวชาญโดยวิธีใด ๆ แต่ผมคิดว่าเป็นเพียงหมายถึงการใช้งานของInt, Floatฯลฯ ให้ที่ Kotlin ไม่ได้มีชนิดที่แตกต่างกันสำหรับหรือBoolean booleanในแง่ของอาร์เรย์ฉันคิดว่าArray<Int>มันจะแตกต่างจากIntArray. โดยส่วนตัวแล้วฉันใช้แบบหลังมาโดยตลอดเนื่องจากไม่เคยรบกวนฉันเลย แต่ Kotlin อาจมีการเพิ่มประสิทธิภาพเพิ่มเติมที่ฉันไม่ทราบ หากคุณกำลังเขียนโปรแกรมใน kotlin แต่เพียงผู้เดียวฉันไม่เห็นกรณีใด ๆ ที่คุณต้องการมากกว่าอีกอันหนึ่ง แต่อาร์เรย์ดั้งเดิมอาจยังคงมีประโยชน์
Allan W

@Allan ไม่ใช่ผู้เชี่ยวชาญเช่นกันเพียงแค่อยากรู้อยากเห็นฉันเชื่อว่า java มีทั้งวัตถุดั้งเดิมและวัตถุชนิดบรรจุกล่องเพราะการทำงานกับวัตถุดั้งเดิมมีประสิทธิภาพมากกว่าใช่ไหมแน่นอนว่าบางครั้งคุณต้องทำงานกับวัตถุ (nullability / generics) สิ่งนี้ไม่อยู่ในขอบเขตของคำถามเดิมของฉัน แต่ฉันสงสัยว่า Kotlin จัดการกับสิ่งนี้อย่างไรเมื่อกำหนดเป้าหมายไปที่ JVM ฉันพยายามใช้ IntArray ทุกครั้งที่ทำได้ (คิดว่ามันใช้แบบดั้งเดิมภายใต้ประทุน) แต่หลังจาก @ ติดขัดความคิดเห็นฉันไม่แน่ใจอีกต่อไป
FRR

1
@feresr สำหรับฉันเอกสารของ Kotlin ระบุอย่างชัดเจนว่ามีอินสแตนซ์อาร์เรย์พิเศษเพื่อหลีกเลี่ยงค่าใช้จ่ายในการชกมวย Takeaway ของฉันคือทั้งสองมีแนวโน้มที่จะแตกต่างกันและในท้ายที่สุดสำหรับผู้พัฒนามันก็กลายเป็นเหมือนกันกับการตัดสินใจว่าคุณต้องการใช้ Integer [] หรือ int [] ใน Java
Allan W

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