ejemplo - text box java
Diferencia exacta entre CharSequence y String en java (8)
aparte del hecho de que String implementa CharSequence y que String es una secuencia de caracteres.
Varias cosas suceden en tu código:
CharSequence obj = "hello";
Eso crea un literal de String
, "hello"
, que es un objeto String
. Al ser un String
, que implementa CharSequence
, también es una CharSequence
. (Puede leer esta publicación sobre codificación en la interfaz, por ejemplo).
La siguiente línea:
String str = "hello";
es un poco mas complejo String
literales de String
en Java se guardan en un grupo (interno) de modo que el "hello"
en esta línea es el mismo objeto (identidad) que el "hello"
en la primera línea. Por lo tanto, esta línea solo asigna el mismo literal de str
a str
.
En este punto, tanto obj
como str
son referencias al String
literal "hello"
y por lo tanto son equals
, ==
y son a la vez un String
y un CharSequence
.
Sugiero que pruebes este código, mostrando en acción lo que acabo de escribir:
public static void main(String[] args) {
CharSequence obj = "hello";
String str = "hello";
System.out.println("Type of obj: " + obj.getClass().getSimpleName());
System.out.println("Type of str: " + str.getClass().getSimpleName());
System.out.println("Value of obj: " + obj);
System.out.println("Value of str: " + str);
System.out.println("Is obj a String? " + (obj instanceof String));
System.out.println("Is obj a CharSequence? " + (obj instanceof CharSequence));
System.out.println("Is str a String? " + (str instanceof String));
System.out.println("Is str a CharSequence? " + (str instanceof CharSequence));
System.out.println("Is /"hello/" a String? " + ("hello" instanceof String));
System.out.println("Is /"hello/" a CharSequence? " + ("hello" instanceof CharSequence));
System.out.println("str.equals(obj)? " + str.equals(obj));
System.out.println("(str == obj)? " + (str == obj));
}
Esta pregunta ya tiene una respuesta aquí:
- CharSequence VS String en Java? 9 respuestas
- ¿Por qué StringBuilder cuando hay String? 10 respuestas
- Elegir entre CharSequence y String para una API [duplicar] 1 respuesta
Leí esta publicación anterior . ¿Puede alguien decir cuál es la diferencia exacta entre CharSequence
y String, aparte del hecho de que String
implementa CharSequence
y que String
es una secuencia de caracteres? Por ejemplo:
CharSequence obj = "hello";
String str = "hello";
System.out.println("output is : " + obj + " " + str);
¿Qué sucede cuando se asigna "hello" a obj
y de nuevo a str
?
tl; dr
Una es una interfaz ( CharSequence
) mientras que otra es una implementación concreta de esa interfaz ( String
).
CharSequence animal = "cat" // `String` object presented as the interface `CharSequence`.
Como interfaz, normalmente la CharSequence
se vería más comúnmente que String
, pero algunos antecedentes retorcidos dieron como resultado que la interfaz se definiera años después de la implementación. Por lo tanto, en las API más antiguas, a menudo vemos String
mientras que en API más nuevas, tendemos a ver a CharSequence
para definir argumentos y tipos de devolución.
Detalles
Hoy en día, sabemos que generalmente una API / framework debe enfocarse en exportar interfaces principalmente y en clases concretas de manera secundaria. Pero no siempre supimos esta lección tan bien.
La clase String
fue primero en Java. Solo más tarde CharSequence
interfaz CharSequence
, CharSequence
.
Historia retorcida
Un poco de historia puede ayudar con la comprensión.
En sus comienzos, Java se apresuró a comercializar un poco antes de tiempo, debido a la manía de Internet / Web que anima la industria. Algunas bibliotecas no fueron tan bien pensadas como deberían haber sido. El manejo de cadenas fue una de esas áreas.
Además, Java fue uno de los primeros entornos no académicos orientados a la producción orientados a objetos (OOP) . 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, muchas lecciones prácticas aún no se habían aprendido.
Java comenzó con la clase String
y la clase StringBuffer
. Pero esas dos clases no estaban relacionadas, no estaban unidas entre sí por herencia o interfaz. Más tarde, el equipo de Java reconoció que debería haber existido un vínculo unificador entre las implementaciones relacionadas con cadenas para hacerlas intercambiables. En Java 4, el equipo agregó la interfaz CharSequence
e implementó de forma retroactiva esa interfaz en el String and 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 estas clases orientadas a cuerdas son un poco desordenadas, y un poco confusas de aprender. Se crearon muchas bibliotecas e interfaces para tomar y devolver objetos String
. Hoy en día, tales bibliotecas generalmente deben construirse para esperar CharSequence
. Pero (a) String
parece seguir dominando el espacio mental, y (b) puede haber algunos problemas técnicos sutiles al mezclar las diversas implementaciones de CharSequence
. Con la visión 20/20 de retrospectiva, podemos ver que todo este material de cuerda podría 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
, del mismo modo que utilizamos las interfaces Collection
o List
en lugar de las implementaciones ArrayList
o LinkedList
.
Interfaz frente a clase
La diferencia clave sobre CharSequence
es que es una interface , no una implementation . Eso significa que no puedes instanciar directamente una CharSequence
. Más bien, crea una de las clases que implementa esa interfaz.
Por ejemplo, aquí tenemos x
que se parece a una CharSequence
pero debajo de esto, en realidad, se trata de un objeto StringBuilder
.
CharSequence x = new StringBuilder( "dog" );
Esto se vuelve menos obvio cuando se utiliza un literal String. Tenga en cuenta que cuando ve el código fuente con solo comillas alrededor de los caracteres, el compilador lo está traduciendo en un objeto String.
CharSequence y = "cat"; // Looks like a CharSequence but is actually a String instance.
Hay algunas diferencias sutiles entre "cat"
y la new String("cat")
como se discutió en esta otra Pregunta , pero son irrelevantes aquí.
Diagrama de clase
Este diagrama de clase puede ayudar a guiarlo. Anoté 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.
Diferencias generales
Hay varias clases que implementan la interfaz CharSequence
además de String
. Entre estos están
-
StringBuilder
para secuencias de caracteres de longitud variable que pueden modificarse -
CharBuffer
para secuencias de caracteres de bajo nivel de longitud fija que pueden modificarse
Cualquier método que acepte una CharSequence
puede operar en todos ellos igualmente bien. Cualquier método que solo acepte una String
requerirá la conversión. Así que usar CharSequence
como un tipo de argumento en todos los lugares donde no te importan las partes internas es prudente. Sin embargo, debe 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 utilizar 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 compile eso y eche un vistazo al bytecode de JVM usando javap -v
. Allí notarás que tanto obj
como str
son referencias al mismo objeto constante. Como una String
es inmutable, este tipo de intercambio está bien.
El operador +
de String
se compila como invocaciones de varias llamadas StringBuilder.append
. 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
el + obj
usando StringBuilder.append(Object)
lugar de StringBuilder.append(CharSequence)
. El primero probablemente implica una llamada al método toString()
del objeto, mientras que el último debería ser posible de una manera más eficiente. Por otro lado, String.toString()
simplemente devuelve el String
mismo, por lo que hay poca penalización allí. Así que StringBuilder.append(String)
podría ser más eficiente por aproximadamente una invocación de método.
Considera UTF-8. En UTF-8, los puntos de código Unicode se crean a partir de uno o más bytes. Una clase que encapsula una matriz de bytes UTF-8 puede implementar la interfaz CharSequence, pero definitivamente no es una cadena. Ciertamente, no puede pasar una matriz de bytes UTF-8 donde se espera una Cadena, pero ciertamente puede aprobar una clase de contenedor UTF-8 que implemente CharSequence cuando el contrato se relaje para permitir una CharSequence. En mi proyecto, estoy desarrollando una clase llamada CBTF8Field (formato de transferencia binaria comprimida - Ocho bits) para proporcionar compresión de datos para xml y estoy buscando usar la interfaz CharSequence para implementar conversiones desde matrices de bytes CBTF8 hacia / desde matrices de caracteres (UTF-16 ) y matrices de bytes (UTF-8).
La razón por la que vine aquí fue para obtener una comprensión completa del contrato posterior.
De la API de Java de CharSequence :
Una CharSequence es una secuencia legible de caracteres. Esta interfaz proporciona acceso uniforme y de solo lectura a muchos tipos diferentes de secuencias de caracteres.
Esta interfaz es luego utilizada por String , CharBuffer y StringBuffer para mantener la consistencia de todos los nombres de métodos.
En charSequence no tienes métodos muy útiles que estén disponibles para String. Si no desea buscar en la documentación, escriba: obj. y str.
y vea qué métodos le ofrece su compilador. Esa es la diferencia básica para mí.
Sé que es algo obvio, pero CharSequence es una interfaz, mientras que String es una clase concreta :)
java.lang.String es una implementación de esta interfaz ...
CharSequence
es un contrato ( interface ) y String
es una implementation de este contrato.
public final class String extends Object
implements Serializable, Comparable<String>, CharSequence
La CharSequence para CharSequence
es:
Una CharSequence es una secuencia legible de valores de char. Esta interfaz proporciona acceso uniforme y de solo lectura a muchos tipos diferentes de secuencias de char. Un valor de char representa un personaje en el plano multilingüe básico (BMP) o un suplente. Consulte Representación de caracteres de Unicode para más detalles.