IntArray vs Array <Int> em Kotlin

91

Não tenho certeza de qual é a diferença entre um IntArraye um Array<Int>em Kotlin e por que não posso usá-los de forma intercambiável:

má combinação

Eu sei que se IntArraytraduz em int[]quando direcionar o JVM, mas o que significa Array<Int>?

Além disso, você também pode ter String[]ou YourObject[]. Por que Kotlin tem classes do tipo {primitive}Arrayquando praticamente qualquer coisa pode ser organizada em uma matriz, não apenas primitivas.

FRR
fonte
1
Meu palpite é que Array<Int>compila para Integer[](se o compilador não otimizar isso)
Mibac
1
Consulte stackoverflow.com/questions/35253368/…
Pixel Elephant
Sim, isso faz muito sentido, obrigado a ambos!
FRR

Respostas:

111

Array<Int>é um Integer[]sob o capô, enquanto IntArrayé um int[]. É isso aí.

Isso significa que quando você coloca um Intem um Array<Int>, ele sempre será encaixotado (especificamente, com uma Integer.valueOf()chamada). No caso de IntArray, nenhum boxing ocorrerá, porque se traduz em um array primitivo Java.


Além das possíveis implicações de desempenho acima, também há conveniência a ser considerada. Matrizes primitivas podem não ser inicializadas e terão 0valores padrão em todos os índices. É por isso que IntArraye o resto das matrizes primitivas têm construtores que aceitam apenas um parâmetro de tamanho:

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

Em contraste, Array<T>não tem um construtor que leva apenas um parâmetro de tamanho: ele precisa de Tinstâncias válidas e não nulas em todos os índices para estar em um estado válido após a criação. Para Numbertipos, pode ser um padrão 0, mas não há como criar instâncias padrão de um tipo arbitrário T.

Portanto, ao criar um Array<Int>, você pode usar o construtor que também recebe uma função de inicializador:

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

Ou crie um Array<Int?>para evitar ter que inicializar todos os valores, mas depois você será forçado a lidar com os nullvalores possíveis toda vez que ler o array.

val arr = arrayOfNulls<Int>(10)
zsmb13
fonte
4
Esta é uma decisão bastante estúpida. Por causa disso, eles tiveram que criar uma nova classe para cada tipo primitivo ... Eles poderiam apenas usar a mesma que em Java.
desenvolvedor de Android
1
@androiddeveloper Que nova classe? int[]é IntArray, Integer[]é Array<Int>e assim por diante, onde está essa nova classe misteriosa? É a mesma coisa, apenas a sintaxe é diferente. int[]também é classe, aliás.
Eugen Pechanec
1
@EugenPechanec Isso é interessante. Eles dizem que é uma classe e que tem uma instância, mas também "instâncias desta classe são representadas como int []": kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int-array/… . Então, essas funções são apenas funções de extensão ou são de uma classe real? E por que era necessário ter "IntArray" e outros? Ainda pode ser feito apenas usando a sintaxe Java.
desenvolvedor Android de
1
@EugenPechanec Mas em Java, int [] não é uma classe, não? É um objeto, um conjunto de primitivos. Você não pode alcançar seu código ou estender a partir dele. Não? Todas as classes em Java têm uma letra maiúscula em seus nomes. Aqui não.
desenvolvedor Android de
1
@EugenPechanec Então no Kotlin é uma classe, enquanto no Java não é. Ainda não entendo o porquê. Eles poderiam apenas adicionar funções de extensão, não? Você pode estender talvez do IntArray? Sobre o nome, eu sei. É apenas a convenção, e uma boa também.
desenvolvedor Android de
6

É importante notar que usar o *operador spread ( ) em a varargretornará um IntArray. Se precisar de um Array<Int>, você pode converter o seu IntArrayusando .toTypedArray().

Eran Boudjnah
fonte
1

Arrays no Kotlin são classes (não tipos "especiais" como Java).

O stdlib do Kotlin fornece classes de propósito especial para arrays primitivos JVM a fim de melhorar a integração e o desempenho da linguagem Java.

A regra prática seria usar, Array<T>exceto se causar um problema ao misturar com o código Java existente ou se deveria ser chamado a partir de classes Java. Só para constar, eu nunca precisei usar IntArray.

Você pode verificar a documentação do idioma sobre este assunto aqui: https://kotlinlang.org/docs/reference/basic-types.html#arrays

onça-pintada
fonte
Eu acredito que você está certo sobre sempre favorecer Array <T> em vez de IntArray, eu estava preocupado com a sobrecarga de boxing / unboxing de usar o tipo boxed vs primitivo, mas parece que Kotlin é inteligente o suficiente para decidir se pode usar um primitivo ou não . (Corrija-me se estiver errado) "Na plataforma Java, os números são armazenados fisicamente como tipos primitivos JVM, a menos que precisemos de uma referência de número anulável (por exemplo, Int?) Ou genéricos estejam envolvidos. Nos últimos casos, os números são colocados em caixas." De kotlinlang.org/docs/reference/basic-types.html
FRR
@feresr não é um especialista, por qualquer meio, mas eu acho que só está se referindo às implementações de Int, Float, etc, uma vez que Kotlin não tem um tipo diferente de Booleanou boolean. Em termos de matrizes, presumo que Array<Int>seja diferente de IntArray. Pessoalmente, sempre usei o último, pois nunca me incomodou, mas talvez Kotlin tenha uma otimização adicional da qual não estou ciente. Se você está programando apenas em kotlin, não vejo nenhum caso em que você precise de um em vez do outro, mas o array primitivo ainda pode ter seus benefícios.
Allan W
@AllanW também não é um especialista, só curioso, acredito que java tem primitivos e objetos em caixa porque é mais eficiente trabalhar com primitivos, certo? Claro que às vezes você realmente precisa trabalhar com objeto (nulidade / genéricos). Isso está fora do escopo da minha pergunta original, mas me pergunto como o Kotlin lida com isso ao direcionar a JVM. Eu tento usar IntArray sempre que possível (pensando que está usando primitivos sob o capô), mas após o comentário @ jamming, não tenho mais certeza.
FRR
1
@feresr para mim, a documentação de Kotlin afirma explicitamente que as instâncias especiais de array existem para evitar a sobrecarga de boxing. Minha conclusão é que os dois provavelmente são diferentes e, no final, para o desenvolvedor, é o mesmo que decidir se deseja usar Integer [] ou int [] em Java.
Allan W
Eu concordo, então a resposta aceita pode ser um pouco enganosa para os recém-chegados, estou desmarcando isso como a resposta aceita por esse motivo.
FRR