tipos modificadores metodos ejemplos constructores constantes clases atributos acceso java string final

modificadores - tipos de atributos en java



¿Por qué la clase String es declarada final en Java? (15)

¿JVM sabe qué es inmutable? La respuesta es No, el grupo de constantes contiene todos los campos inmutables pero todos los campos / objetos inmutables no se almacenan en el grupo de constantes solamente. Solo lo implementamos de forma que logre la inmutabilidad y sus características. CustomString podría implementarse sin hacer que sea definitiva usando MarkerInterface, que proporcionaría un comportamiento especial de Java para su agrupación, ¡aún se espera la función!

Desde que supe que la clase java.lang.String se declara como definitiva en Java, me preguntaba ¿por qué? No encontré ninguna respuesta en ese momento, pero esta publicación: ¿Cómo crear una réplica de la clase String en Java? me recordó mi consulta.

Claro, String proporciona toda la funcionalidad que siempre necesité, y nunca pensé en ninguna operación que requiriera una extensión de la clase String, ¡pero igual nunca sabrá lo que alguien podría necesitar!

Entonces, ¿alguien sabe cuál fue la intención de los diseñadores cuando decidieron hacerlo definitivo?


Además de las razones obvias sugeridas en otras respuestas, una idea de hacer que la clase String sea definitiva también podría estar relacionada con la sobrecarga de rendimiento de los métodos virtuales. Recuerde que String es una clase pesada, por lo que esta finalización, significa que no hay ninguna sub implementación, seguramente significa que no habrá gastos indirectos de llamadas. Por supuesto ahora tenemos cosas como la invocación virtual y otras, que siempre hacen este tipo de optimización para usted.


Además de los motivos mencionados en otras respuestas (seguridad, inmutabilidad, rendimiento), se debe tener en cuenta que String tiene soporte de lenguaje especial. Puedes escribir String literales y hay soporte para el operador + . Permitir que los programadores subclases String , alentaría a los piratas tales como:

class MyComplex extends String { ... } MyComplex a = new MyComplex("5+3i"); MyComplex b = new MyComplex("7+4i"); MyComplex c = new MyComplex(a + b); // would work since a and b are strings, // and a string + a string is a string.


Bueno, tengo un pensamiento diferente, no estoy seguro de si estoy en lo cierto o no, pero en Java String es el único objeto que puede tratarse como un tipo de datos primitivo, quiero decir que podemos crear un objeto String como String name = "java " . Ahora, al igual que otros tipos de datos primitivos que son copiar por valor, no copiar por referencia. Se espera que String tenga el mismo comportamiento, por lo que String es definitivo. Eso es lo que mi pensó. Por favor, ignore si es completamente ilógico.


Como dijo Bruno, se trata de la inmutabilidad. No se trata solo de cadenas, sino también de cualquier envoltorio, por ejemplo, doble, entero, personaje, etc. Hay muchas razones para esto:

  • Hilo de seguridad
  • Seguridad
  • Heap que es administrado por Java mismo (de manera diferente al montón común que es Basher Collected de manera diferente)
  • Gestión de la memoria

Básicamente es para que usted, como programador, pueda estar seguro de que su cadena nunca se cambiará. También, si sabe cómo funciona, puede mejorar la administración de la memoria. Intenta crear dos cadenas idénticas una tras otra, por ejemplo, "hola". Notarás, si depuras, que tienen identificaciones idénticas, eso significa que son exactamente LOS MISMOS objetos. Esto se debe al hecho de que Java te permite hacerlo. Esto no sería posible si las cuerdas fueran muttables. Pueden tener lo mismo que yo, etc., porque nunca cambiarán. Entonces, si alguna vez decides crear 1,000,000 de cuerdas "hola", lo que realmente harías es crear 1,000,000 de punteros para "hola". Al igual que cualquier función en la cadena, o cualquier envoltura por esa razón, daría lugar a la creación de otro objeto (de nuevo mira la ID del objeto, cambiará).

Completamente final en Java no significa necesariamente que el objeto no puede cambiar (es diferente, por ejemplo, a C ++). Significa que la dirección a la que apunta no puede cambiar, pero aún puede cambiar sus propiedades y / o atributos. Entonces, comprender la diferencia entre inmutabilidad y final en algún caso puede ser realmente importante.

HTH

Referencias


Con muchos puntos buenos ya mencionados, me gustaría añadir otro: una de las razones por las cuales Why String es inmutable en Java es permitir que String guarde en caché su código hash , siendo inmutable String en Java almacena en caché su código hash, y no calcula cada tiempo que llamamos el método de cadena de código hash, que lo hace muy rápido como la clave hashmap para ser utilizado en hashmap en Java.

En resumen, porque String es inmutable, nadie puede cambiar su contenido una vez creado, lo que garantiza que hashCode of String sea el mismo en múltiples invocación.

Si ves que String clase String se declara como

/** Cache the hash code for the string */ private int hash; // Default to 0

y la función hashcode() es la siguiente:

public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }

Si ya es una computadora, simplemente devuelva el valor.


Es muy útil tener cadenas implementadas como objetos inmutables . Debes leer sobre inmutabilidad para entender más sobre esto.

Una ventaja de los objetos inmutables es que

Puede compartir duplicados al señalarlos a una sola instancia.

(de here )

Si String no fuera final, podría crear una subclase y tener dos cadenas que se parecen cuando se ven como cadenas, pero que en realidad son diferentes.


La finalidad de las cadenas también las defiende como estándar. En C ++ puedes crear subclases de cadenas, por lo que cada tienda de programación podría tener su propia versión de cadena. Esto llevaría a una falta de un estándar fuerte.


La mayoría de las respuestas están relacionadas con la inmutabilidad: por qué un objeto de tipo String no se puede actualizar en su lugar. Aquí hay una buena discusión y la comunidad Java haría bien en adoptar la inmutabilidad como principal. (No aguantando la respiración)

Sin embargo, la pregunta del OP es acerca de por qué es definitiva, por qué no puede extenderse. Algunos aquí tomaron esto, pero estoy de acuerdo con el OP que hay una brecha real aquí. Otros desarrolladores de idiomas permiten crear nuevos tipos nominales para un tipo. Por ejemplo, en Haskell puedo crear los siguientes tipos nuevos que son idénticos en tiempo de ejecución como texto, pero proporcionan seguridad de enlace en tiempo de compilación.

newtype AccountCode = AccountCode Text newtype FundCode = FundCode Text

Así que enviaría la siguiente sugerencia como una mejora al lenguaje Java:

newtype AccountCode of String; newtype FundCode of String; AccountCode acctCode = "099876"; FundCode fundCode = "099876"; acctCode.equals(fundCode); // evaluates to false; acctCode.toString().equals(fundCode.toString()); // evaluates to true; acctCode=fundCode; // compile error getAccount(fundCode); // compile error

(O tal vez podríamos comenzar a quitarnos de Java)


La razón más importante por la que String es inmutable o definitiva es que es utilizada por el mecanismo de carga de clases y, por lo tanto, tiene aspectos de seguridad fundamentales y profundos.

Si String hubiera sido mutable o no final, una solicitud para cargar "java.io.Writer" podría haberse cambiado para cargar "mil.vogoon.DiskErasingWriter"

referencia: Por qué String es inmutable en Java


Para asegurarnos de que no obtengamos una mejor implementación. Por supuesto, debería haber sido una interfaz.

[edit] Ah, obteniendo más votos sin sentido. La respuesta es perfectamente seria. He tenido que programar varias veces la estúpida implementación de String, lo que ha provocado un severo rendimiento y pérdida de productividad


Pudo haber sido para simplificar la implementación. Si diseñas una clase que los usuarios de la clase puedan heredar, entonces tienes un nuevo conjunto de casos de uso para considerar en tu diseño. ¿Qué sucede si hacen esto o aquello con el campo X proptected? Para que sea definitivo, pueden enfocarse en lograr que la interfaz pública funcione correctamente y asegurarse de que sea sólida.


Si crea una cadena una vez, considerará que es un objeto si desea modificar eso, no es posible, creará un nuevo objeto.


Este es un buen artículo que describe dos razones ya mencionadas en las respuestas anteriores:

  1. Seguridad : el sistema puede entregar fragmentos sensibles de información de solo lectura sin preocuparse de que se alteren
  2. Rendimiento : los datos inmutables son muy útiles para hacer que las cosas sean seguras para los hilos.

Y este es probablemente el comentario más detallado en ese artículo. Tiene que ver con el grupo de cadenas en Java y problemas de seguridad. Se trata de cómo decidir qué entra en el grupo de cadenas. Suponiendo que ambas cadenas son iguales si su secuencia de caracteres es la misma, entonces tenemos una condición de carrera sobre quién llega primero y, junto con ella, problemas de seguridad. De lo contrario, el grupo de cadenas contendrá cadenas redundantes, perdiendo así la ventaja de tenerlas en primer lugar. Solo léelo por ti mismo, ¿quieres?

La extensión de String causaría estragos entre iguales e internos. JavaDoc dice igual a:

Compara esta cadena con el objeto especificado. El resultado es verdadero si y solo si el argumento no es nulo y es un objeto String que representa la misma secuencia de caracteres que este objeto.

Suponiendo que java.lang.String no fuera final, un SafeString podría ser igual a String , y viceversa; porque representarían la misma secuencia de caracteres.

¿Qué pasaría si aplicara un intern a un SafeString ? ¿El SafeString iría al grupo de cadenas de la JVM? El ClassLoader y todos los objetos a los que SafeString tenía referencias se SafeString en su lugar durante el tiempo de vida de la JVM. Tendría una condición de carrera sobre quién podría ser el primero en internar una secuencia de personajes: tal vez su SafeString ganaría, tal vez un String , o tal vez un SafeString cargado por un cargador de clases diferente (por lo tanto, una clase diferente).

Si ganó la carrera en el grupo, este sería un singleton verdadero y la gente podría acceder a todo su entorno (sandbox) a través de reflection y secretKey.intern().getClass().getClassLoader() .

O bien, la JVM podría bloquear este agujero asegurándose de que solo se hayan agregado objetos de Cadena concretos (y no subclases) al conjunto.

Si equals se implementó de manera tal que SafeString ! = String entonces SafeString.intern ! = String.intern , y SafeString tendría que ser agregado al grupo. El grupo se convertiría en un grupo de <Class, String> lugar de <String> y todo lo que necesitaría para ingresar al grupo sería un nuevo cargador de clases.


String es una clase muy básica en Java, muchas cosas dependen de que funcione de cierta manera, por ejemplo, ser inmutable.

Hacer que la clase sea final evita las subclases que podrían romper estas suposiciones.

Tenga en cuenta que, incluso ahora, si usa la reflexión, puede romper cadenas (cambiar su valor o código hash). La reflexión se puede detener con un administrador de seguridad. Si String no era final , todos podían hacerlo.

Otras clases que no están declaradas como final permiten definir subclases algo rotas (por ejemplo, podría tener una List que se agrega a la posición incorrecta), pero al menos la JVM no depende de aquellas para sus operaciones centrales.