Con respecto a las preguntas de esta serie, todos los que estudien Java deberían comprenderlas. Por supuesto, no importa si aprendes Java sólo por diversión. Si cree que ha superado el nivel principiante pero no comprende bien estos problemas, agréguese al equipo de principiantes.
Pregunta 1: ¿Qué estoy afirmando?
Cadena s = "¡Hola mundo!";
Mucha gente ha hecho esto, pero ¿qué declaramos exactamente? La respuesta suele ser: una cadena con el contenido "¡Hola mundo!". Respuestas tan vagas son a menudo la fuente de conceptos poco claros. Si dieras una respuesta precisa, probablemente la mitad de las personas responderían mal.
Esta declaración declara una referencia a un objeto, llamado "s", que puede apuntar a cualquier objeto de tipo String. Actualmente, apunta al objeto de tipo String "¡Hola mundo!". Esto es lo que realmente pasó. No declaramos un objeto String, simplemente declaramos una variable de referencia que solo puede apuntar al objeto String. Entonces, si después de la declaración de ahora, si ejecuta otra oración:
Cadena cadena = s;
Hemos declarado otra referencia que solo puede apuntar al objeto String, llamado cadena. No se genera ningún segundo objeto String que aún apunte al objeto original, es decir, apunta al mismo objeto que s.
Pregunta 2: ¿Cuál es la diferencia entre el método "==" y el método igual?
El operador == se utiliza específicamente para comparar los valores de las variables en busca de igualdad. Lo más fácil de entender es:
Copie el código de código de la siguiente manera:
int a = 10;
intb=10;
Entonces a==b será cierto.
Pero lo que es difícil de entender es:
Copie el código de código de la siguiente manera:
Cadena a=nueva cadena("foo");
Cadena b=nueva Cadena("foo");
Entonces a==b devolverá falso.
Según la publicación anterior, las variables de objeto son en realidad referencias y sus valores apuntan a la dirección de memoria donde se encuentra el objeto, no al objeto en sí. Tanto a como b usan el nuevo operador, lo que significa que se generarán dos cadenas con el contenido "foo" en la memoria. Dado que hay "dos", naturalmente se ubican en diferentes direcciones de memoria. Los valores de a y b son en realidad los valores de dos direcciones de memoria diferentes, por lo que al usar el operador "==", el resultado será falso. Es cierto que los objetos señalados por a y b tienen el contenido "foo" y deberían ser "iguales", pero el operador == no implica la comparación del contenido del objeto.
La comparación del contenido de los objetos es exactamente lo que hace el método igual.
Eche un vistazo a cómo se implementa el método igual del objeto Object:
Copie el código de código de la siguiente manera:
booleano es igual (Objeto o){
devolver esto==o;
}
Los objetos objeto utilizan el operador == de forma predeterminada. Entonces, si su clase creada por usted mismo no anula el método igual, entonces su clase obtendrá el mismo resultado usando igual y ==. También se puede ver que el método igual de Object no logra el objetivo que debería lograr el método igual: comparar si el contenido de dos objetos es igual. Debido a que la respuesta debe ser determinada por el creador de la clase, Object deja esta tarea al creador de la clase.
Eche un vistazo a una clase extrema:
Copie el código de código de la siguiente manera:
Monstruo de clase {
contenido de cadena privada;
...
booleano es igual (Objeto otro) {retorna verdadero;}
}
Anulé el método igual. Esta implementación hace que las comparaciones entre instancias de Monster siempre sean verdaderas independientemente de su contenido.
Entonces, cuando utilice el método igual para determinar si el contenido de un objeto es igual, no lo dé por sentado. Porque tal vez pienses que son iguales, pero el autor de esta clase no lo cree así, y la implementación del método igual de la clase está controlada por él. Si necesita utilizar el método de igualdad o cualquier colección basada en código hash (HashSet, HashMap, HashTable), consulte el documento de Java para confirmar cómo se implementa la lógica de igualdad de esta clase.
Pregunta 3: ¿Ha cambiado String?
No. Debido a que String está diseñado para ser una clase inmutable, todos sus objetos son objetos inmutables. Por favor mire el siguiente código:
Copie el código de código de la siguiente manera:
Cadena s = "Hola";
s = s + "¡mundo!";
¿Ha cambiado el objetivo señalado por s? Esta conclusión se puede derivar fácilmente de la conclusión del primer artículo de esta serie. Veamos qué pasó. En este código, s originalmente apuntaba a un objeto String con el contenido "Hola", y luego realizamos una operación + en s. ¿Ha cambiado el objeto señalado por s? La respuesta es no. En este momento, s ya no apunta al objeto original, sino a otro objeto String con el contenido "¡Hola mundo!". El objeto original todavía existe en la memoria, pero la variable de referencia s ya no apunta a él.
A través de la explicación anterior, podemos llegar fácilmente a otra conclusión. Si las cadenas se modifican con frecuencia de varias maneras, o se modifican de manera imprevista, entonces usar String para representar una cadena causará una gran sobrecarga de memoria. Dado que el objeto String no se puede cambiar una vez creado, se requiere un objeto String para representar cada cadena diferente. En este momento, debería considerar usar la clase StringBuffer, que permite modificaciones, en lugar de generar un nuevo objeto para cada cadena diferente. Además, el cambio de política entre estos dos tipos es muy simple.
Al mismo tiempo, también podemos saber que si desea utilizar una cadena con el mismo contenido, no necesita crear una nueva cadena cada vez. Por ejemplo, si queremos inicializar una variable de referencia de cadena llamada s en el constructor y establecerla en el valor inicial, debemos hacer esto:
Copie el código de código de la siguiente manera:
Demostración de clase pública {
Cadenas privadas;
…
Demostración pública {
s = "Valor inicial";
}
…
}
En lugar de s = new String("Valor inicial");
Este último llamará al constructor cada vez para generar un nuevo objeto, lo que tiene un bajo rendimiento y un gran consumo de memoria, y no tiene sentido. Debido a que el objeto String no se puede cambiar, solo se puede usar un objeto String para representar una cadena con el mismo contenido. . En otras palabras, si llama al constructor anterior varias veces para crear múltiples objetivos, todos sus atributos de tipo Cadena apuntarán al mismo objetivo.
La conclusión anterior también se basa en el hecho de que para las constantes de cadena, si el contenido es el mismo, Guangzhou Java Training cree que representan el mismo objeto de cadena. Llamar al constructor con la palabra clave new siempre creará un nuevo objetivo, independientemente de si el contenido es el mismo.
En cuanto a por qué la clase String debería describirse como una clase inmutable, está determinada por su propósito. De hecho, no sólo String, sino también muchas clases de la biblioteca de clases estándar de Java son inmutables. Al desarrollar un sistema, a veces necesitamos describir clases inmutables para transmitir un conjunto de valores relacionados, lo que también es una manifestación del pensamiento orientado a objetivos. Las clases inmutables tienen algunas ventajas. Por ejemplo, debido a que su propósito es de solo lectura, no habrá problemas con el acceso simultáneo de varios subprocesos. Por supuesto, también existen algunas deficiencias, como que cada situación diferente necesita un objeto para representarla, lo que puede causar problemas funcionales. Por lo tanto, la biblioteca de clases estándar de Java también proporciona una versión variable, a saber, StringBuffer.