Saltar al contenido

Diferencia exacta entre CharSequence y String en Java

Este equipo especializado pasados muchos días de investigación y recopilar de datos, hallamos la solución, nuestro deseo es que resulte útil para ti en tu plan.

Solución:

Diferencias generales

Hay varias clases que implementan la CharSequence interfaz además String. Entre estos se encuentran

  • StringBuilder para secuencias de caracteres de longitud variable que se pueden modificar
  • CharBuffer para secuencias de caracteres de bajo nivel de longitud fija que se pueden modificar

Cualquier método que acepte un CharSequence puede operar en todos estos igualmente bien. Cualquier método que solo acepte un String requerirá conversión. Entonces usando CharSequence como tipo de argumento en todos los lugares donde no le importan los aspectos internos es prudente. Sin embargo debes usar String como un tipo de retorno si realmente devuelve un String, porque eso evita posibles conversiones de valores devueltos si el método de llamada realmente requiere un String.

También tenga en cuenta que los mapas deben usar String como tipo de clave, no CharSequence, ya que las claves del mapa no deben cambiar. En otras palabras, a veces la naturaleza inmutable de String es esencial.

Fragmento de código específico

En cuanto al código que pegó: simplemente compílelo y eche un vistazo al código de bytes de JVM usando javap -v. Allí notarás que ambos obj y str son referencias al mismo objeto constante. Como un String es inmutable, este tipo de compartir está bien.

los + operador de String se compila como invocaciones de varios StringBuilder.append llamadas. Entonces es equivalente a

System.out.println(
  (new StringBuilder())
  .append("output is : ")
  .append((Object)obj)
  .append(" ")
  .append(str)
  .toString()
)

Debo confesar que estoy un poco sorprendido de que mi compilador javac 1.6.0_33 compila el + obj utilizando StringBuilder.append(Object) en lugar de StringBuilder.append(CharSequence). El primero probablemente implica una llamada al toString() método del objeto, mientras que este último debería ser posible de una manera más eficiente. Por otra parte, String.toString() simplemente devuelve el String en sí mismo, por lo que hay poca penalización allí. Entonces StringBuilder.append(String) podría ser más eficiente mediante la invocación de un método.

tl; dr

Uno es una interfaz (CharSequence) mientras que otro es una implementación concreta de esa interfaz (String).

CharSequence animal = "cat"  // `String` object presented as the interface `CharSequence`.

Al igual que ArrayList es un List, y HashMap es un Map, así también String es un CharSequence.

Como interfaz, normalmente el CharSequence sería más común que String, pero una historia retorcida dio como resultado que la interfaz se definiera años después la implementación. Por eso, en las API más antiguas, a menudo vemos String mientras que en las API más nuevas tendemos a ver CharSequence utilizado para definir argumentos y tipos de retorno.

Detalles

Hoy en día sabemos que, en general, una API / framework debe enfocarse en exportar interfaces principalmente y clases concretas en segundo lugar. Pero no siempre conocimos tan bien esta lección.

los String la clase fue la primera en Java. Solo más tarde colocaron una interfaz frontal, CharSequence.

Historia retorcida

Un poco de historia podría ayudar a comprenderlo.

En sus inicios, Java se apresuró a comercializar un poco antes de su tiempo, debido a la manía de Internet / Web que animaba a la industria. Algunas bibliotecas no estaban tan bien pensadas como deberían. El manejo de cuerdas fue una de esas áreas.

Además, Java fue uno de los primeros entornos de programación orientada a objetos (OOP) no académicos y orientados a la producción. Las únicas implementaciones exitosas de OOP en el mundo real antes de eso fueron algunas versiones limitadas de SmallTalk, luego Objective-C con NeXTSTEP / OpenStep. Por lo tanto, aún quedaban por aprender muchas lecciones prácticas.

Java comenzó con el String clase y StringBuffer clase. Pero esas dos clases no estaban relacionadas, no estaban vinculadas entre sí por herencia ni interfaz. Más tarde, el equipo de Java reconoció que debería haber habido un vínculo unificador entre stringimplementaciones relacionadas para hacerlas intercambiables. En Java 4, el equipo agregó el CharSequence e implementó retroactivamente esa interfaz en String y String Buffer, además de agregar otra implementación CharBuffer. Más tarde en Java 5 agregaron StringBuilder, básicamente una versión no sincronizada y, por lo tanto, algo más rápida de StringBuffer.

Entonces estos string-Las clases orientadas son un poco desordenadas y un poco confuso aprender sobre ellas. Muchas bibliotecas e interfaces se crearon para aceptar y devolver String objetos. Hoy en día, estas bibliotecas deberían construirse para esperar CharSequence. Pero (a) String parece dominar todavía el espacio mental, y (b) puede haber algunos problemas técnicos sutiles al mezclar los diversos CharSequence implementaciones. Con la visión 20/20 en retrospectiva, podemos ver que todo esto string las cosas podrían haberse manejado mejor, pero aquí estamos.

Idealmente, Java habría comenzado con una interfaz y / o superclase que se usaría en muchos lugares donde ahora usamos String, al igual que usamos el Collection o List interfaces en lugar de ArrayList o LinkedList implementaciones.

Interfaz versus clase

La diferencia clave sobre CharSequence es que es una interfaz, no una implementación. Eso significa que no puede instanciar directamente un CharSequence. En su lugar, crea una instancia de una de las clases que implementa esa interfaz.

Por ejemplo, aquí tenemos x que parece un CharSequence pero debajo hay en realidad un StringBuilder objeto.

CharSequence x = new StringBuilder( "dog" );  // Looks like a `CharSequence` but is actually a `StringBuilder` instance.

Esto se vuelve menos obvio cuando se usa un literal de cadena. Tenga en cuenta que cuando ve el código fuente con solo comillas alrededor de los caracteres, el compilador lo está traduciendo a un objeto String.

CharSequence y = "cat";  // Looks like a `CharSequence` but is actually a `String` instance.

Literal versus constructor

Hay algunas diferencias sutiles entre "cat" y new String("cat") como se discutió en esta otra Pregunta, pero son irrelevantes aquí.

Diagrama de clase

Este diagrama de clases puede servir de guía. Observé la versión de Java en la que parecían demostrar cuánto cambio se ha producido a través de estas clases e interfaces.

diagrama que muestra los diversos string-clases e interfaces relacionadas a partir de Java 8

Bloques de texto

Aparte de agregar más caracteres Unicode, incluida una multitud de emoji, en los últimos años no ha cambiado mucho en Java para trabajar con texto. Hasta que bloques de texto.

Los bloques de texto son una nueva forma de manejar mejor el tedio de string literales con varias líneas o caracteres de escape. Esto haría que escribir cadenas de código incrustadas como HTML, XML, SQL o JSON sea mucho más conveniente.

Para citar JEP 378:

Un bloque de texto es un multilínea string literal que evita la necesidad de la mayoría de las secuencias de escape, formatea automáticamente el string de una manera predecible, y le da al desarrollador control sobre el formato cuando lo desee.

La función de bloques de texto no no introducir un nuevo tipo de datos. Los bloques de texto son simplemente una nueva sintaxis para escribir un String literal. Un bloque de texto produce un String objeto, al igual que la sintaxis literal convencional. Un bloque de texto produce un String objeto, que también es un CharSequence objeto, como se discutió anteriormente.

Ejemplo de SQL

Para citar JSR 378 nuevamente …

Usando “unidimensional” string literales.

String query = "SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"n" +
               "WHERE "CITY" = 'INDIANAPOLIS'n" +
               "ORDER BY "EMP_ID", "LAST_NAME";n";

Usar un bloque de texto “bidimensional”

String query = """
               SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
               WHERE "CITY" = 'INDIANAPOLIS'
               ORDER BY "EMP_ID", "LAST_NAME";
               """;

Los bloques de texto se encuentran en Java 15 y posteriores, por JEP 378: Bloques de texto.

Primera vista previa en Java 13, bajo JEP 355: Bloques de texto (vista previa). Luego, vista de nuevo en Java 14 en JEP 368: Bloques de texto (segunda vista previa).

Este esfuerzo fue precedido por JEP 326: Literales de cadena sin formato (versión preliminar). Los conceptos fueron reelaborados para producir el Bloques de texto característica en su lugar.

CharSequence es un contrato (interfaz), y String es una implementación de este contrato.

public final class String extends Object 
    implements Serializable, Comparable, CharSequence

La documentación para CharSequence es:

Un CharSequence es una secuencia legible de valores char. Esta interfaz proporciona acceso uniforme de solo lectura a muchos tipos diferentes de secuencias de caracteres. Un valor char representa un carácter en el plano multilingüe básico (BMP) o un sustituto. Consulte Representación de caracteres Unicode para obtener más detalles.

Aquí puedes ver las reseñas y valoraciones de los usuarios

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *