IntArray vs Array <Int> trong Kotlin


88

Tôi không chắc sự khác biệt giữa dấu IntArrayvà dấu Array<Int>là gì trong Kotlin và tại sao tôi không thể sử dụng chúng thay thế cho nhau:

missmatch

Tôi biết điều đó có IntArraynghĩa là int[]khi nhắm mục tiêu JVM, nhưng Array<Int>dịch sang cái gì?

Ngoài ra, bạn cũng có thể có String[]hoặc YourObject[]. Tại sao Kotlin lại có các lớp thuộc loại này {primitive}Arraykhi mà hầu hết mọi thứ đều có thể được sắp xếp thành một mảng, không chỉ các nguyên mẫu.


1
Tôi đoánArray<Int>biên dịch để Integer[](nếu trình biên dịch không tối ưu hóa này)
MiBAC


Yup, điều đó rất có ý nghĩa, cảm ơn cả hai!
FRR

Câu trả lời:


107

Array<Int>là một Integer[]dưới mui xe, trong khi IntArraylà một int[]. Đó là nó.

Điều này có nghĩa là khi bạn đặt một Intvào Array<Int>, nó sẽ luôn được đóng hộp (cụ thể là với một Integer.valueOf()cuộc gọi). Trong trường hợp của IntArray, không có quyền nào xảy ra, bởi vì nó chuyển sang một mảng nguyên thủy Java.


Ngoài các tác động hiệu suất có thể có của những điều trên, cũng có sự tiện lợi để xem xét. Các mảng ban đầu có thể không được khởi tạo và chúng sẽ có 0giá trị mặc định ở tất cả các chỉ mục. Đây là lý do tại sao IntArrayvà phần còn lại của mảng nguyên thủy có các hàm tạo chỉ nhận tham số kích thước:

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

Ngược lại, Array<T>không có một phương thức khởi tạo chỉ nhận tham số kích thước: nó cần các cá thể hợp lệ, không rỗng Tở tất cả các chỉ mục để ở trạng thái hợp lệ sau khi tạo. Đối với Numbercác loại, đây có thể là một mặc định 0, nhưng không có cách nào để tạo các phiên bản mặc định của một loại tùy ý T.

Vì vậy, khi tạo một Array<Int>, bạn có thể sử dụng hàm tạo cũng có chức năng khởi tạo:

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

Hoặc tạo một Array<Int?>để tránh phải khởi tạo mọi giá trị, nhưng sau đó bạn sẽ buộc phải xử lý nullcác giá trị có thể có mỗi khi bạn đọc từ mảng.

val arr = arrayOfNulls<Int>(10)

4
Đây là một quyết định khá ngu ngốc. Do đó, họ phải tạo một lớp mới cho mỗi kiểu nguyên thủy ... Họ chỉ có thể sử dụng giống như trên Java.
nhà phát triển android

1
@androiddeveloper Lớp mới nào? int[]IntArray, Integer[]Array<Int>, v.v., lớp mới bí ẩn này ở đâu? Nó giống nhau chỉ có cú pháp là khác nhau. int[]nhân tiện cũng là đẳng cấp.
Eugen Pechanec

1
@EugenPechanec Điều này thật thú vị. Họ nói rằng đó là một lớp và nó có một cá thể, nhưng "các cá thể của lớp này cũng được biểu diễn dưới dạng int []": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/… . Vậy, những hàm đó chỉ là những hàm mở rộng hay chúng thuộc một lớp thực sự? Và tại sao cần phải có "IntArray", và những thứ khác? Vẫn có thể được thực hiện bằng cú pháp Java.
nhà phát triển android

1
@EugenPechanec Nhưng trong Java, int [] không phải là một lớp, phải không? Đó là một đối tượng, một mảng các nguyên thủy. Bạn không thể tiếp cận là mã, hoặc mở rộng từ nó. Không? Tất cả các lớp trên Java đều có một ký tự hoa ở tên của chúng. Đây không phải.
nhà phát triển android

1
@EugenPechanec Vì vậy, trên Kotlin nó là một lớp, trong khi trên Java thì không. Tuy nhiên, vẫn không hiểu tại sao. Họ chỉ có thể thêm các chức năng mở rộng, không? Bạn có thể mở rộng từ IntArray? Về cách đặt tên, tôi biết. Đó chỉ là quy ước, và cũng là một quy ước tốt.
nhà phát triển android

6

Cần lưu ý rằng việc sử dụng *toán tử spread ( ) trên a varargsẽ trả về một IntArray. Nếu bạn cần một Array<Int>, bạn có thể chuyển đổi IntArraycách sử dụng của mình .toTypedArray().


1

Mảng trong Kotlin là các lớp (không phải kiểu "đặc biệt" như Java).

Kotlin's stdlib cung cấp các lớp mục đích đặc biệt cho các mảng nguyên thủy JVM để cải thiện hiệu suất và tích hợp ngôn ngữ Java.

Quy tắc ngón tay cái sẽ là sử dụng Array<T>ngoại trừ nếu nó gây ra sự cố khi trộn với mã Java hiện có, hoặc phải được gọi từ các lớp Java. Đối với bản ghi, tôi không bao giờ phải sử dụng IntArray.

Bạn có thể kiểm tra tài liệu của Ngôn ngữ về vấn đề này tại đây: https://kotlinlang.org/docs/reference/basic-types.html#arrays


Tôi tin rằng bạn đúng khi luôn yêu thích Array <T> hơn IntArray, tôi đã lo lắng về chi phí quyền anh / unboxing khi sử dụng loại đóng hộp so với loại nguyên thủy, nhưng có vẻ như Kotlin đủ thông minh để quyết định thời tiết nó có thể sử dụng loại nguyên thủy hay không . (Hãy sửa cho tôi nếu tôi sai) "Trên nền tảng Java, các số được lưu trữ vật lý dưới dạng các kiểu nguyên thủy JVM, trừ khi chúng ta cần tham chiếu số có thể nullable (ví dụ: Int?) Hoặc liên quan đến generics. Trong các trường hợp sau, các số được đóng hộp." Từ kotlinlang.org/docs/reference/basic-types.html
FRR

@feresr không phải là một chuyên gia bằng bất kỳ phương tiện, nhưng tôi nghĩ rằng chỉ là đề cập đến việc triển khai của Int, Float, vv, cho rằng Kotlin không có một loại khác nhau cho Booleanhay boolean. Về mảng, tôi sẽ giả sử rằng Array<Int>sẽ khác với IntArray. Cá nhân tôi luôn sử dụng cái sau vì nó không bao giờ làm phiền tôi, nhưng có lẽ Kotlin có tối ưu hóa bổ sung mà tôi không biết. Nếu bạn chỉ lập trình bằng kotlin, tôi không thấy có trường hợp nào bạn cần cái này hơn cái kia, nhưng mảng nguyên thủy có thể vẫn có những lợi ích của nó.
Allan W

@AllanW cũng không phải là một chuyên gia, chỉ là tò mò thôi, tôi tin rằng java có cả các đối tượng nguyên thủy và các đối tượng đóng hộp vì nó hiệu quả hơn khi làm việc với các đối tượng nguyên thủy phải không ?, tất nhiên đôi khi bạn thực sự cần làm việc với đối tượng (nullability / generics). Điều này vượt ra khỏi phạm vi câu hỏi ban đầu của tôi nhưng tôi tự hỏi làm thế nào Kotlin xử lý điều này khi nhắm mục tiêu JVM. Tôi cố gắng sử dụng IntArray bất cứ khi nào có thể (nghĩ rằng nó đang sử dụng nguyên thủy) nhưng sau khi nhận xét gây nhiễu @, tôi không còn chắc chắn nữa.
FRR

1
@feresr với tôi, tài liệu của Kotlin tuyên bố rõ ràng rằng các trường hợp mảng đặc biệt ở đó để tránh phí quyền anh. Điểm rút ra của tôi là cả hai có thể khác nhau, và cuối cùng đối với nhà phát triển, nó sẽ giống như việc quyết định bạn muốn sử dụng Integer [] hay int [] trong Java.
Allan W

Tôi đồng ý, sau đó câu trả lời được chấp nhận có thể gây hiểu lầm cho người mới, tôi đã bỏ đánh dấu đây là câu trả lời được chấp nhận vì lý do này.
FRR
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.