Se ha discutido antes en CodeRanch. Vea la discusión aquí.
missingfaktor
Respuestas:
97
Permítanme primero resaltar tres formas diferentes para un propósito similar.
length- matrices ( int[], double[], String[]) - Conocer la longitud de las matrices
length()- objeto relacionado Cadena ( String, StringBuilder, etc) - para conocer la longitud de la cadena
size()- Colección de objetos ( ArrayList, Set, etc) - para saber el tamaño de la colección
Ahora olvídate de length()considerar justo lengthy size().
lengthno es un método, por lo que tiene mucho sentido que no funcione en objetos. Solo funciona en matrices. size()su nombre lo describe mejor y como es un método, se usará en el caso de aquellos objetos que trabajen con colección (frameworks de colección) como dije allá arriba.
Ahora veamos length():
String no es una matriz primitiva (por lo que no podemos usar .length) y tampoco una Colección (por lo que no podemos usar .size()), por eso también necesitamos una diferente que es length()(mantener las diferencias y cumplir el propósito).
Como respuesta a ¿Por qué?
Lo encuentro útil, fácil de recordar y usar y amigable.
Un poco simplificado, puede pensar que las matrices son un caso especial y no clases ordinarias (un poco como primitivas, pero no). String y todas las colecciones son clases, de ahí los métodos para obtener tamaño, longitud o cosas similares.
Supongo que la razón en el momento del diseño fue el rendimiento. Si lo crearon hoy, probablemente se les ocurrió algo como clases de colección respaldadas por matrices.
Si alguien está interesado, aquí hay un pequeño fragmento de código para ilustrar la diferencia entre los dos en el código generado, primero la fuente:
Cortar de alguna manera la parte no tan importante del código de bytes, que se ejecuta javap -cen la clase, da como resultado lo siguiente para las dos últimas líneas:
En el primer caso (20-25), el código solo le pide a la JVM el tamaño de la matriz (en JNI esto habría sido una llamada a GetArrayLength ()) mientras que en el caso de String (28-35) necesita hacer una llamada al método para obtener la longitud.
A mediados de la década de 1990, sin buenos JIT y esas cosas, habría acabado con el rendimiento por completo si solo tuviera java.util.Vector (o algo similar) y no una construcción de lenguaje que en realidad no se comportara como una clase pero que fuera rápida. Por supuesto, podrían haber enmascarado la propiedad como una llamada a un método y manejarla en el compilador, pero creo que hubiera sido aún más confuso tener un método en algo que no es una clase real.
¡Java trata la matriz como objetos y las cadenas como objetos inmutables! : |
Nitish Upreti
@Myth: No veo su punto ... La propiedad de longitud de las matrices no es un campo público ni nada, es una construcción de jvm (arraylength es incluso una operación en el código de bytes). Es muy obvio cuando haces JNI o si simplemente desarmas el código de donde viene.
Fredrik
No creo que el razonamiento del diseño original fuera solo el rendimiento. ¿Cómo lo implementaría Vectorcuando el lenguaje Java no tuviera soporte para arreglos?
Holger
8
.lengthes una propiedad única de Java. Se usa para encontrar el tamaño de una matriz unidimensional .
.length()es un método. Se usa para encontrar la longitud de un String. Evita duplicar el valor.
int[] myArray = newint[10];
String myString = "hello world!";
List<int> myList = new ArrayList<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
Es muy probable que las cadenas y las matrices se hayan diseñado en diferentes momentos y, por lo tanto, terminen usando diferentes convenciones. Una justificación es que, dado que las cadenas utilizan matrices internamente length(), se utilizó un método para evitar la duplicación de la misma información. Otro es que el uso de un método length()ayuda a enfatizar la inmutabilidad de las cadenas, aunque el tamaño de una matriz tampoco se puede cambiar.
En última instancia, esto es solo una inconsistencia que evolucionó y que definitivamente se solucionaría si el lenguaje fuera rediseñado desde cero. Hasta donde yo sé, ningún otro lenguaje (C #, Python, Scala, etc.) hace lo mismo, por lo que es probable que sea solo una pequeña falla que terminó como parte del lenguaje.
Obtendrá un error si usa el incorrecto de todos modos.
Esta es una respuesta más justificable e imparcial.
Zubair Alam
3
En Java, un Array almacena su longitud por separado de la estructura que realmente contiene los datos. Cuando crea una matriz, especifica su longitud, y eso se convierte en un atributo definitorio de la matriz. No importa lo que haga con una matriz de longitud N (cambiar valores, anular cosas, etc.), siempre será una matriz de longitud N.
La longitud de una cadena es incidental; no es un atributo de la Cadena, sino un subproducto. Aunque las cadenas de Java son de hecho inmutables, si fuera posible cambiar su contenido, podría cambiar su longitud. Eliminar el último carácter (si fuera posible) reduciría la longitud.
Entiendo que esta es una distinción fina, y puede que me rechacen, pero es verdad. Si hago una matriz de longitud 4, esa longitud de cuatro es una característica definitoria de la matriz, y es cierta independientemente de lo que contenga. Si hago una cadena que contiene "perros", esa cadena tiene una longitud de 4 porque contiene cuatro caracteres.
Veo esto como una justificación para hacer uno con un atributo y el otro con un método. En verdad, puede que sea una inconsistencia involuntaria, pero siempre ha tenido sentido para mí, y así es como siempre lo he pensado.
Me enseñaron que para las matrices, la longitud no se recupera a través de un método debido al siguiente temor: los programadores simplemente asignarían la longitud a una variable local antes de ingresar a un bucle (piense en un bucle for donde el condicional usa la longitud de la matriz). supuestamente lo haría para recortar las llamadas a funciones (y así mejorar el rendimiento). El problema es que la longitud podría cambiar durante el ciclo y la variable no.
La longitud de una matriz no puede cambiar durante el ciclo.
Fredrik
2
no puede cambiar la longitud de esta matriz en particular, pero puede asignar una nueva a la misma variable
Bozho
2
@Bozho: Cierto, pero entonces es otra matriz y si lo haces intencionalmente y no actualizas lo que sea, verificas tu bucle, tienes un error. Java nunca ha tenido la intención de evitar que escribas errores. Puede hacer bucles infinitos, recursividad hasta que muera y todo tipo de errores lógicos sin que Java intente detenerlo. Es una buena razón para no almacenar la longitud en una variable, pero seguro que no es la razón por la que está diseñada de esa manera.
Fredrik
1
Siempre que se crea una matriz, se especifica su tamaño. Por tanto, la longitud puede considerarse un atributo de construcción. Para String, es esencialmente una matriz de caracteres. La longitud es una propiedad de la matriz char. No es necesario poner la longitud como campo, porque no todo necesita este campo.
http://www.programcreek.com/2013/11/start-from-length-length-in-java/
Un objeto es una instancia de clase o una matriz .
Así que la matriz tiene un papel muy especial en Java. Me pregunto por qué.
Se podría argumentar que la matriz de implementación actual es / era importante para un mejor rendimiento. Pero que es una estructura interna, que no debe exponerse.
Por supuesto, podrían haber enmascarado la propiedad como una llamada a un método y manejarla en el compilador, pero creo que hubiera sido aún más confuso tener un método en algo que no es una clase real.
Estoy de acuerdo con Fredrik, que una optimización inteligente del compilador hubiera sido la mejor opción. Esto también resolvería el problema de que incluso si usa una propiedad para matrices, no ha resuelto el problema para cadenas y otros tipos de colección (inmutables), porque, por ejemplo, stringse basa en una charmatriz como puede ver en la definición de clase. de String:
Como ingeniero realmente no me gusta la respuesta "porque siempre ha sido así". y deseaba que hubiera una mejor respuesta. Pero en este caso parece serlo.
tl; dr
En mi opinión, es un defecto de diseño de Java y no debería haberse implementado de esta manera.
Respuestas:
Permítanme primero resaltar tres formas diferentes para un propósito similar.
length
- matrices (int[]
,double[]
,String[]
) - Conocer la longitud de las matriceslength()
- objeto relacionado Cadena (String
,StringBuilder
, etc) - para conocer la longitud de la cadenasize()
- Colección de objetos (ArrayList
,Set
, etc) - para saber el tamaño de la colecciónAhora olvídate de
length()
considerar justolength
ysize()
.length
no es un método, por lo que tiene mucho sentido que no funcione en objetos. Solo funciona en matrices.size()
su nombre lo describe mejor y como es un método, se usará en el caso de aquellos objetos que trabajen con colección (frameworks de colección) como dije allá arriba.Ahora veamos
length()
:String no es una matriz primitiva (por lo que no podemos usar
.length
) y tampoco una Colección (por lo que no podemos usar.size()
), por eso también necesitamos una diferente que eslength()
(mantener las diferencias y cumplir el propósito).Como respuesta a ¿Por qué?
Lo encuentro útil, fácil de recordar y usar y amigable.
fuente
Un poco simplificado, puede pensar que las matrices son un caso especial y no clases ordinarias (un poco como primitivas, pero no). String y todas las colecciones son clases, de ahí los métodos para obtener tamaño, longitud o cosas similares.
Supongo que la razón en el momento del diseño fue el rendimiento. Si lo crearon hoy, probablemente se les ocurrió algo como clases de colección respaldadas por matrices.
Si alguien está interesado, aquí hay un pequeño fragmento de código para ilustrar la diferencia entre los dos en el código generado, primero la fuente:
public class LengthTest { public static void main(String[] args) { int[] array = {12,1,4}; String string = "Hoo"; System.out.println(array.length); System.out.println(string.length()); } }
Cortar de alguna manera la parte no tan importante del código de bytes, que se ejecuta
javap -c
en la clase, da como resultado lo siguiente para las dos últimas líneas:20: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 23: aload_1 24: arraylength 25: invokevirtual #4; //Method java/io/PrintStream.println:(I)V 28: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 31: aload_2 32: invokevirtual #5; //Method java/lang/String.length:()I 35: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
En el primer caso (20-25), el código solo le pide a la JVM el tamaño de la matriz (en JNI esto habría sido una llamada a GetArrayLength ()) mientras que en el caso de String (28-35) necesita hacer una llamada al método para obtener la longitud.
A mediados de la década de 1990, sin buenos JIT y esas cosas, habría acabado con el rendimiento por completo si solo tuviera java.util.Vector (o algo similar) y no una construcción de lenguaje que en realidad no se comportara como una clase pero que fuera rápida. Por supuesto, podrían haber enmascarado la propiedad como una llamada a un método y manejarla en el compilador, pero creo que hubiera sido aún más confuso tener un método en algo que no es una clase real.
fuente
Vector
cuando el lenguaje Java no tuviera soporte para arreglos?.length
es una propiedad única de Java. Se usa para encontrar el tamaño de una matriz unidimensional ..length()
es un método. Se usa para encontrar la longitud de unString
. Evita duplicar el valor.fuente
Considerar:
int[] myArray = new int[10]; String myString = "hello world!"; List<int> myList = new ArrayList<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
Es muy probable que las cadenas y las matrices se hayan diseñado en diferentes momentos y, por lo tanto, terminen usando diferentes convenciones. Una justificación es que, dado que las cadenas utilizan matrices internamente
length()
, se utilizó un método para evitar la duplicación de la misma información. Otro es que el uso de un métodolength()
ayuda a enfatizar la inmutabilidad de las cadenas, aunque el tamaño de una matriz tampoco se puede cambiar.En última instancia, esto es solo una inconsistencia que evolucionó y que definitivamente se solucionaría si el lenguaje fuera rediseñado desde cero. Hasta donde yo sé, ningún otro lenguaje (C #, Python, Scala, etc.) hace lo mismo, por lo que es probable que sea solo una pequeña falla que terminó como parte del lenguaje.
Obtendrá un error si usa el incorrecto de todos modos.
fuente
En Java, un Array almacena su longitud por separado de la estructura que realmente contiene los datos. Cuando crea una matriz, especifica su longitud, y eso se convierte en un atributo definitorio de la matriz. No importa lo que haga con una matriz de longitud N (cambiar valores, anular cosas, etc.), siempre será una matriz de longitud N.
La longitud de una cadena es incidental; no es un atributo de la Cadena, sino un subproducto. Aunque las cadenas de Java son de hecho inmutables, si fuera posible cambiar su contenido, podría cambiar su longitud. Eliminar el último carácter (si fuera posible) reduciría la longitud.
Entiendo que esta es una distinción fina, y puede que me rechacen, pero es verdad. Si hago una matriz de longitud 4, esa longitud de cuatro es una característica definitoria de la matriz, y es cierta independientemente de lo que contenga. Si hago una cadena que contiene "perros", esa cadena tiene una longitud de 4 porque contiene cuatro caracteres.
Veo esto como una justificación para hacer uno con un atributo y el otro con un método. En verdad, puede que sea una inconsistencia involuntaria, pero siempre ha tenido sentido para mí, y así es como siempre lo he pensado.
fuente
Me enseñaron que para las matrices, la longitud no se recupera a través de un método debido al siguiente temor: los programadores simplemente asignarían la longitud a una variable local antes de ingresar a un bucle (piense en un bucle for donde el condicional usa la longitud de la matriz). supuestamente lo haría para recortar las llamadas a funciones (y así mejorar el rendimiento). El problema es que la longitud podría cambiar durante el ciclo y la variable no.
fuente
Siempre que se crea una matriz, se especifica su tamaño. Por tanto, la longitud puede considerarse un atributo de construcción. Para String, es esencialmente una matriz de caracteres. La longitud es una propiedad de la matriz char. No es necesario poner la longitud como campo, porque no todo necesita este campo. http://www.programcreek.com/2013/11/start-from-length-length-in-java/
fuente
Solo quiero agregar algunos comentarios a la gran respuesta de Fredrik .
La Especificación del lenguaje Java en la Sección 4.3.1 establece
Así que la matriz tiene un papel muy especial en Java. Me pregunto por qué.
Se podría argumentar que la matriz de implementación actual es / era importante para un mejor rendimiento. Pero que es una estructura interna, que no debe exponerse.
Estoy de acuerdo con Fredrik, que una optimización inteligente del compilador hubiera sido la mejor opción. Esto también resolvería el problema de que incluso si usa una propiedad para matrices, no ha resuelto el problema para cadenas y otros tipos de colección (inmutables), porque, por ejemplo,
string
se basa en unachar
matriz como puede ver en la definición de clase. deString
:public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; // ...
Y no estoy de acuerdo con eso sería aún más confuso, porque array hereda todos los métodos de
java.lang.Object
.Como ingeniero realmente no me gusta la respuesta "porque siempre ha sido así". y deseaba que hubiera una mejor respuesta. Pero en este caso parece serlo.
tl; dr
En mi opinión, es un defecto de diseño de Java y no debería haberse implementado de esta manera.
fuente