Já foi discutido antes no CodeRanch. Veja a discussão aqui.
missingfaktor
Respostas:
98
Deixe-me primeiro destacar três maneiras diferentes para fins semelhantes.
length- matrizes ( int[], double[], String[]) - para saber o comprimento das matrizes
length()- Cadeia objecto relacionado ( String, StringBuilder, etc.) - a saber o comprimento da corda
size()- Objeto Coleção ( ArrayList, Set, etc.) - para saber o tamanho da coleção
Agora esqueça de length()considerar apenas lengthe size().
lengthnão é um método, portanto, faz todo o sentido que não funcione em objetos. Ele só funciona em matrizes. size()seu nome o descreve melhor e por ser um método, ele será usado no caso daqueles objetos que trabalham com coleção (frameworks de coleção) como eu disse lá em cima.
Agora vamos para length():
String não é um array primitivo (então não podemos usar .length) e também não é uma Collection (então não podemos usar .size()), por isso também precisamos de um diferente que é length()(mantenha as diferenças e atenda ao propósito).
Como resposta a por quê?
Acho que é útil, fácil de lembrar e usar e amigável.
Um pouco simplificado, você pode pensar nisso como arrays sendo um caso especial e não classes comuns (um pouco como primitivas, mas não). String e todas as coleções são classes, daí os métodos para obter tamanho, comprimento ou coisas semelhantes.
Eu acho que a razão na época do design era o desempenho. Se eles o criaram hoje, provavelmente teriam criado algo como classes de coleção baseadas em array.
Se alguém estiver interessado, aqui está um pequeno trecho de código para ilustrar a diferença entre os dois no código gerado, primeiro a fonte:
No primeiro caso (20-25), o código apenas pergunta ao JVM o tamanho do array (em JNI, isso seria uma chamada para GetArrayLength ()), enquanto no caso de String (28-35) ele precisa fazer um chamada de método para obter o comprimento.
Em meados dos anos 1990, sem bons JITs e outras coisas, teria matado totalmente o desempenho ter apenas o java.util.Vector (ou algo semelhante) e não uma construção de linguagem que realmente não se comportasse como uma classe, mas fosse rápida. Eles poderiam, é claro, ter mascarado a propriedade como uma chamada de método e manipulado no compilador, mas acho que seria ainda mais confuso ter um método em algo que não é uma classe real.
Java trata array como objetos e strings como objetos imutáveis !! : |
Nitish Upreti
@Myth: Não vejo seu ponto ... A propriedade length dos arrays não é um campo público nem nada, é uma construção do jvm (arraylength é até uma operação no bytecode). É muito óbvio quando você faz JNI ou se você apenas desmonta o código de onde ele vem.
Fredrik
Não acho que o raciocínio do design original fosse apenas desempenho. Como você implementaria Vectorquando a linguagem Java não tivesse suporte a array?
Holger
8
.lengthé uma propriedade única de Java. É usado para encontrar o tamanho de uma única matriz dimensional .
.length()é um método. É usado para encontrar o comprimento de a String. Evita duplicar o valor.
int[] myArray =newint[10];String myString ="hello world!";List<int> myList =newArrayList<int>();
myArray.length // Gives the length of the array
myString.length()// Gives the length of the string
myList.size()// Gives the length of the list
É muito provável que strings e arrays tenham sido projetados em momentos diferentes e, portanto, acabaram usando convenções diferentes. Uma justificativa é que, como Strings usam arrays internamente, um método,, length()foi usado para evitar a duplicação das mesmas informações. Outra é que usar um método length()ajuda a enfatizar a imutabilidade das strings, embora o tamanho de uma matriz também seja imutável.
No final das contas, essa é apenas uma inconsistência que evoluiu e que definitivamente seria corrigida se a linguagem fosse redesenhada do zero. Até onde eu sei, nenhuma outra linguagem (C #, Python, Scala, etc.) faz a mesma coisa, então essa provavelmente é apenas uma pequena falha que acabou fazendo parte da linguagem.
Você obterá um erro se usar o errado de qualquer maneira.
Esta é uma resposta mais justificável e imparcial.
Zubair Alam
3
Em Java, um Array armazena seu comprimento separadamente da estrutura que realmente contém os dados. Ao criar um Array, você especifica seu comprimento, e isso se torna um atributo de definição do Array. Não importa o que você faça com um Array de comprimento N (alterar valores, anular coisas, etc.), sempre será um Array de comprimento N.
O comprimento de uma String é acidental; não é um atributo da String, mas um subproduto. Embora Java Strings sejam de fato imutáveis, se fosse possível alterar seu conteúdo, você poderia alterar seu comprimento. Eliminar o último caractere (se fosse possível) diminuiria o comprimento.
Eu entendo que esta é uma boa distinção e posso ser rejeitado a favor, mas é verdade. Se eu fizer um Array de comprimento 4, esse comprimento de quatro é uma característica definidora do Array, e é verdadeiro independentemente do que é mantido dentro. Se eu fizer uma String que contém "cachorros", essa String terá um comprimento 4 porque contém quatro caracteres.
Eu vejo isso como uma justificativa para fazer um com um atributo e outro com um método. Na verdade, pode ser apenas uma inconsistência não intencional, mas sempre fez sentido para mim e sempre foi assim que pensei sobre isso.
Aprendi que, para arrays, o comprimento não é recuperado por meio de um método devido ao seguinte medo: os programadores apenas atribuem o comprimento a uma variável local antes de entrar em um loop (pense em um loop for em que a condicional usa o comprimento do array.) O programador supostamente faria isso para diminuir as chamadas de função (e assim melhorar o desempenho). O problema é que o comprimento pode mudar durante o loop, mas a variável não.
O comprimento de uma matriz não pode mudar durante o loop.
Fredrik
2
você não pode alterar o comprimento dessa matriz específica, mas pode atribuir uma nova à mesma variável
Bozho
2
@Bozho: Verdadeiro, mas então é outro array e se você fizer isso intencionalmente e não atualizar o que quer que verifique seu loop, você tem um bug. Java nunca teve a intenção de impedir que você escrevesse bugs. Você pode fazer loops infinitos, recursão até morrer e todos os tipos de erros lógicos sem que o java tente impedi-lo. É uma boa razão para não armazenar o comprimento em uma variável, mas certamente não é a razão pela qual foi projetado dessa forma.
Fredrik
1
Sempre que uma matriz é criada, seu tamanho é especificado. Portanto, o comprimento pode ser considerado um atributo de construção. Para String, é essencialmente uma matriz char. O comprimento é uma propriedade da matriz char. Não há necessidade de colocar o comprimento como um campo, porque nem tudo precisa desse campo.
http://www.programcreek.com/2013/11/start-from-length-length-in-java/
Portanto, array tem, de fato, um papel muito especial em Java. Eu me pergunto por quê.
Pode-se argumentar que o array de implementação atual é / foi importante para um melhor desempenho. Mas então é uma estrutura interna, que não deve ser exposta.
Eles poderiam, é claro, ter mascarado a propriedade como uma chamada de método e manipulado no compilador, mas acho que teria sido ainda mais confuso ter um método em algo que não é uma classe real.
Eu concordo com Fredrik, que uma otimização do compilador inteligente teria sido a melhor escolha. Isso também resolveria o problema, que mesmo se você usar uma propriedade para arrays, você não resolveu o problema para strings e outros tipos de coleção (imutáveis), porque, por exemplo, stringé baseado em um chararray como você pode ver na definição de classe de String:
Como engenheiro, realmente não gosto da resposta "Porque sempre foi assim". e gostaria que houvesse uma resposta melhor. Mas, neste caso, parece que sim.
tl; dr
Na minha opinião, é uma falha de design do Java e não deveria ter sido implementado dessa forma.
Respostas:
Deixe-me primeiro destacar três maneiras diferentes para fins semelhantes.
length
- matrizes (int[]
,double[]
,String[]
) - para saber o comprimento das matrizeslength()
- Cadeia objecto relacionado (String
,StringBuilder
, etc.) - a saber o comprimento da cordasize()
- Objeto Coleção (ArrayList
,Set
, etc.) - para saber o tamanho da coleçãoAgora esqueça de
length()
considerar apenaslength
esize()
.length
não é um método, portanto, faz todo o sentido que não funcione em objetos. Ele só funciona em matrizes.size()
seu nome o descreve melhor e por ser um método, ele será usado no caso daqueles objetos que trabalham com coleção (frameworks de coleção) como eu disse lá em cima.Agora vamos para
length()
:String não é um array primitivo (então não podemos usar
.length
) e também não é uma Collection (então não podemos usar.size()
), por isso também precisamos de um diferente que élength()
(mantenha as diferenças e atenda ao propósito).Como resposta a por quê?
Acho que é útil, fácil de lembrar e usar e amigável.
fonte
Um pouco simplificado, você pode pensar nisso como arrays sendo um caso especial e não classes comuns (um pouco como primitivas, mas não). String e todas as coleções são classes, daí os métodos para obter tamanho, comprimento ou coisas semelhantes.
Eu acho que a razão na época do design era o desempenho. Se eles o criaram hoje, provavelmente teriam criado algo como classes de coleção baseadas em array.
Se alguém estiver interessado, aqui está um pequeno trecho de código para ilustrar a diferença entre os dois no código gerado, primeiro a fonte:
Cortar uma parte não tão importante do código de bytes, rodando
javap -c
na classe resulta no seguinte para as duas últimas linhas:No primeiro caso (20-25), o código apenas pergunta ao JVM o tamanho do array (em JNI, isso seria uma chamada para GetArrayLength ()), enquanto no caso de String (28-35) ele precisa fazer um chamada de método para obter o comprimento.
Em meados dos anos 1990, sem bons JITs e outras coisas, teria matado totalmente o desempenho ter apenas o java.util.Vector (ou algo semelhante) e não uma construção de linguagem que realmente não se comportasse como uma classe, mas fosse rápida. Eles poderiam, é claro, ter mascarado a propriedade como uma chamada de método e manipulado no compilador, mas acho que seria ainda mais confuso ter um método em algo que não é uma classe real.
fonte
Vector
quando a linguagem Java não tivesse suporte a array?.length
é uma propriedade única de Java. É usado para encontrar o tamanho de uma única matriz dimensional ..length()
é um método. É usado para encontrar o comprimento de aString
. Evita duplicar o valor.fonte
Considerar:
É muito provável que strings e arrays tenham sido projetados em momentos diferentes e, portanto, acabaram usando convenções diferentes. Uma justificativa é que, como Strings usam arrays internamente, um método,,
length()
foi usado para evitar a duplicação das mesmas informações. Outra é que usar um métodolength()
ajuda a enfatizar a imutabilidade das strings, embora o tamanho de uma matriz também seja imutável.No final das contas, essa é apenas uma inconsistência que evoluiu e que definitivamente seria corrigida se a linguagem fosse redesenhada do zero. Até onde eu sei, nenhuma outra linguagem (C #, Python, Scala, etc.) faz a mesma coisa, então essa provavelmente é apenas uma pequena falha que acabou fazendo parte da linguagem.
Você obterá um erro se usar o errado de qualquer maneira.
fonte
Em Java, um Array armazena seu comprimento separadamente da estrutura que realmente contém os dados. Ao criar um Array, você especifica seu comprimento, e isso se torna um atributo de definição do Array. Não importa o que você faça com um Array de comprimento N (alterar valores, anular coisas, etc.), sempre será um Array de comprimento N.
O comprimento de uma String é acidental; não é um atributo da String, mas um subproduto. Embora Java Strings sejam de fato imutáveis, se fosse possível alterar seu conteúdo, você poderia alterar seu comprimento. Eliminar o último caractere (se fosse possível) diminuiria o comprimento.
Eu entendo que esta é uma boa distinção e posso ser rejeitado a favor, mas é verdade. Se eu fizer um Array de comprimento 4, esse comprimento de quatro é uma característica definidora do Array, e é verdadeiro independentemente do que é mantido dentro. Se eu fizer uma String que contém "cachorros", essa String terá um comprimento 4 porque contém quatro caracteres.
Eu vejo isso como uma justificativa para fazer um com um atributo e outro com um método. Na verdade, pode ser apenas uma inconsistência não intencional, mas sempre fez sentido para mim e sempre foi assim que pensei sobre isso.
fonte
Aprendi que, para arrays, o comprimento não é recuperado por meio de um método devido ao seguinte medo: os programadores apenas atribuem o comprimento a uma variável local antes de entrar em um loop (pense em um loop for em que a condicional usa o comprimento do array.) O programador supostamente faria isso para diminuir as chamadas de função (e assim melhorar o desempenho). O problema é que o comprimento pode mudar durante o loop, mas a variável não.
fonte
Sempre que uma matriz é criada, seu tamanho é especificado. Portanto, o comprimento pode ser considerado um atributo de construção. Para String, é essencialmente uma matriz char. O comprimento é uma propriedade da matriz char. Não há necessidade de colocar o comprimento como um campo, porque nem tudo precisa desse campo. http://www.programcreek.com/2013/11/start-from-length-length-in-java/
fonte
Eu só quero acrescentar algumas observações à ótima resposta de Fredrik .
A especificação da linguagem Java na Seção 4.3.1 declara
Portanto, array tem, de fato, um papel muito especial em Java. Eu me pergunto por quê.
Pode-se argumentar que o array de implementação atual é / foi importante para um melhor desempenho. Mas então é uma estrutura interna, que não deve ser exposta.
Eu concordo com Fredrik, que uma otimização do compilador inteligente teria sido a melhor escolha. Isso também resolveria o problema, que mesmo se você usar uma propriedade para arrays, você não resolveu o problema para strings e outros tipos de coleção (imutáveis), porque, por exemplo,
string
é baseado em umchar
array como você pode ver na definição de classe deString
:E eu não concordo com isso seria ainda mais confuso, porque array herda todos os métodos de
java.lang.Object
.Como engenheiro, realmente não gosto da resposta "Porque sempre foi assim". e gostaria que houvesse uma resposta melhor. Mas, neste caso, parece que sim.
tl; dr
Na minha opinião, é uma falha de design do Java e não deveria ter sido implementado dessa forma.
fonte