Preguntas y respuestas de la entrevista de cadena de Java

1. Introducción

La clase String es una de las clases más utilizadas en Java, lo que llevó a los diseñadores de lenguajes a tratarla de forma especial. Este comportamiento especial lo convierte en uno de los temas más candentes en las entrevistas de Java.

En este tutorial, repasaremos algunas de las preguntas de entrevista más comunes sobre String .

2. Fundamentos de las cuerdas

Esta sección consta de preguntas relacionadas con la estructura interna y la memoria de String .

Q1. ¿Qué es una cadena en Java?

En Java, una cadena está representado internamente por una matriz de bytes valores (o carbón de leña valores antes de JDK 9).

En versiones hasta Java 8 inclusive, una cadena estaba compuesta por una matriz inmutable de caracteres Unicode. Sin embargo, la mayoría de los caracteres requieren solo 8 bits (1 byte) para representarlos en lugar de 16 bits ( tamaño de carácter ).

Para mejorar el consumo y el rendimiento de la memoria, Java 9 introdujo cadenas compactas. Esto significa que si una cadena contiene solo caracteres de 1 byte, se representará con codificación Latin-1 . Si una cadena contiene al menos 1 carácter multibyte, se representará como 2 bytes por carácter utilizando codificación UTF-16.

En C y C ++, String también es una matriz de caracteres, pero en Java, es un objeto separado con su propia API.

Q2. ¿Cómo podemos crear un objeto de cadena en Java ?

java.lang.String define 13 formas diferentes de crear una cadena . Sin embargo, generalmente hay dos:

  • A través de un literal de cadena :
    String s = "abc";
  • A través de la nueva palabra clave:
    String s = new String("abc");

Todos los literales String en Java son instancias de la clase String .

Q3. ¿Es String un tipo primitivo o derivado?

Una cadena es un tipo derivado ya que tiene estado y comportamiento. Por ejemplo, tiene métodos como substring () , indexOf () y equals (), que las primitivas no pueden tener.

Pero, dado que todos lo usamos con tanta frecuencia, tiene algunas características especiales que lo hacen sentir como un primitivo:

  • Si bien las cadenas no se almacenan en la pila de llamadas como lo son las primitivas, se almacenan en una región de memoria especial llamada grupo de cadenas
  • Como primitivas, podemos usar el operador + en cadenas
  • Y nuevamente, al igual que las primitivas, podemos crear una instancia de String sin la nueva palabra clave

Q4. ¿Cuáles son los beneficios de que las cadenas sean inmutables?

Según una entrevista de James Gosling, las cuerdas son inmutables para mejorar el rendimiento y la seguridad.

Y de hecho, vemos varios beneficios de tener cadenas inmutables:

  • El grupo de cadenas solo es posible si las cadenas, una vez creadas, nunca se cambian, ya que se supone que deben reutilizarse
  • El código puede pasar una cadena de forma segura a otro método , sabiendo que ese método no puede modificarla
  • Inmutablemente, automáticamente hace que esta clase sea segura para subprocesos
  • Dado que esta clase es segura para subprocesos, no es necesario sincronizar datos comunes , lo que a su vez mejora el rendimiento.
  • Dado que se garantiza que no cambiarán, su código hash se puede almacenar en caché fácilmente

Q5. ¿Cómo se almacena una cadena en la memoria?

Según la Especificación de JVM, los literales de cadena se almacenan en un grupo de constantes de tiempo de ejecución, que se asigna desde el área de métodos de la JVM.

Aunque el área de método es lógicamente parte de la memoria del montón, la especificación no dicta la ubicación, el tamaño de la memoria o las políticas de recolección de basura. Puede ser específico de la implementación.

Esta agrupación de constantes de tiempo de ejecución para una clase o interfaz se construye cuando la JVM crea la clase o interfaz.

Q6. ¿Son las cadenas internas elegibles para la recolección de basura en Java?

Sí, toda cadena es en el grupo de cadena son aptos para reciclaje si no hay referencias del programa.

Q7. ¿Qué es el pool constante de cadenas?

El grupo de cadenas, también conocido como grupo de constantes de cadenas o grupo interno de cadenas , es una región de memoria especial donde la JVM almacena instancias de cadenas .

Optimiza el rendimiento de la aplicación al reducir la frecuencia y la cantidad de cadenas que se asignan:

  • La JVM almacena solo una copia de una cadena en particular en el grupo
  • Al crear una nueva cadena , la JVM busca en el grupo una cadena que tenga el mismo valor
  • Si se encuentra, la JVM devuelve la referencia a esa cadena sin asignar memoria adicional
  • Si no se encuentra, la JVM lo agrega al grupo (lo interna) y devuelve su referencia

Q8. ¿Son las cuerdas seguras para subprocesos? ¿Cómo?

De hecho, las cadenas son completamente seguras para subprocesos porque son inmutables. Cualquier clase que sea inmutable califica automáticamente para la seguridad de subprocesos porque su inmutabilidad garantiza que sus instancias no se cambiarán en varios subprocesos.

Por ejemplo, si un hilo cambia el valor de una cadena, se crea una nueva cadena en lugar de modificar la existente.

Q9. ¿Para qué operaciones de cadenas es importante proporcionar una configuración regional?

La clase Locale nos permite diferenciar entre lugares culturales, así como dar formato a nuestro contenido de manera adecuada.

Cuando se trata de la clase String , la necesitamos cuando renderizamos cadenas en formato o cuando se escriben cadenas en mayúsculas o minúsculas.

De hecho, si nos olvidamos de hacer esto, podemos tener problemas con la portabilidad, la seguridad y la usabilidad.

Q10. ¿Cuál es la codificación de caracteres subyacente para cadenas?

According to String's Javadocs for versions up to and including Java 8, Strings are stored in the UTF-16 format internally.

The char data type and java.lang.Character objects are also based on the original Unicode specification, which defined characters as fixed-width 16-bit entities.

Starting with JDK 9, Strings that contain only 1-byte characters use Latin-1 encoding, while Strings with at least 1 multi-byte character use UTF-16 encoding.

3. The String API

In this section, we'll discuss some questions related to the String API.

Q11. How Can We Compare Two Strings in Java? What’s the Difference Between str1 == str2 and str1.Equals(str2)?

We can compare strings in two different ways: by using equal to operator ( == ) and by using the equals() method.

Both are quite different from each other:

  • The operator (str1 == str2) checks for referential equality
  • The method (str1.equals(str2)) checks for lexical equality

Though, it's true that if two strings are lexically equal, then str1.intern() == str2.intern() is also true.

Typically, for comparing two Strings for their content, we should always use String.equals.

Q12. How Can We Split a String in Java?

The String class itself provides us with the String#split method, which accepts a regular expression delimiter. It returns us a String[] array:

String[] parts = "john,peter,mary".split(","); assertEquals(new String[] { "john", "peter", "mary" }, parts);

One tricky thing about split is that when splitting an empty string, we may get a non-empty array:

assertEquals(new String[] { "" }, "".split(","));

Of course, split is just one of many ways to split a Java String.

Q13. What Is Stringjoiner?

StringJoiner is a class introduced in Java 8 for joining separate strings into one, like taking a list of colors and returning them as a comma-delimited string. We can supply a delimiter as well as a prefix and suffix:

StringJoiner joiner = new StringJoiner(",", "[", "]"); joiner.add("Red") .add("Green") .add("Blue"); assertEquals("[Red,Green,Blue]", joiner.toString());

Q14. Difference Between String, Stringbuffer and Stringbuilder?

Strings are immutable. This means that if we try to change or alter its values, then Java creates an absolutely new String.

For example, if we add to a string str1 after it has been created:

String str1 = "abc"; str1 = str1 + "def";

Then the JVM, instead of modifying str1, creates an entirely new String.

However, for most of the simple cases, the compiler internally uses StringBuilder and optimizes the above code.

But, for more complex code like loops, it will create an entirely new String, deteriorating performance. This is where StringBuilder and StringBuffer are useful.

Both StringBuilder and StringBuffer in Java create objects that hold a mutable sequence of characters.StringBuffer is synchronized and therefore thread-safe whereas StringBuilder is not.

Since the extra synchronization in StringBuffer is typically unnecessary, we can often get a performance boost by selecting StringBuilder.

Q15. Why Is It Safer to Store Passwords in a Char[] Array Rather Than a String?

Since strings are immutable, they don't allow modification. This behavior keeps us from overwriting, modifying, or zeroing out its contents, making Strings unsuitable for storing sensitive information.

We have to rely on the garbage collector to remove a string's contents. Moreover, in Java versions 6 and below, strings were stored in PermGen, meaning that once a String was created, it was never garbage collected.

By using a char[] array, we have complete control over that information.We can modify it or wipe it completely without even relying on the garbage collector.

Using char[] over String doesn't completely secure the information; it's just an extra measure that reduces an opportunity for the malicious user to gain access to sensitive information.

Q16. What Does String’s intern() Method Do?

The method intern() creates an exact copy of a String object in the heap and stores it in the String constant pool, which the JVM maintains.

Java automatically interns all strings created using string literals, but if we create a String using the new operator, for example, String str = new String(“abc”), then Java adds it to the heap, just like any other object.

We can call the intern() method to tell the JVM to add it to the string pool if it doesn't already exist there, and return a reference of that interned string:

String s1 = "Baeldung"; String s2 = new String("Baeldung"); String s3 = new String("Baeldung").intern(); assertThat(s1 == s2).isFalse(); assertThat(s1 == s3).isTrue();

Q17. How Can We Convert String to Integer and Integer to String in Java?

The most straightforward approach to convert a String to an Integer is by using Integer#parseInt:

int num = Integer.parseInt("22");

To do the reverse, we can use Integer#toString:

String s = Integer.toString(num);

Q18. What Is String.format() and How Can We Use It?

String#format returns a formatted string using the specified format string and arguments.

String title = "Baeldung"; String formatted = String.format("Title is %s", title); assertEquals("Title is Baeldung", formatted);

We also need to remember to specify the user's Locale, unless we are okay with simply accepting the operating system default:

Locale usersLocale = Locale.ITALY; assertEquals("1.024", String.format(usersLocale, "There are %,d shirts to choose from. Good luck.", 1024))

Q19. How Can We Convert a String to Uppercase and Lowercase?

String implicitly provides String#toUpperCase to change the casing to uppercase.

Though, the Javadocs remind us that we need to specify the user's Locale to ensure correctness:

String s = "Welcome to Baeldung!"; assertEquals("WELCOME TO BAELDUNG!", s.toUpperCase(Locale.US));

Similarly, to convert to lowercase, we have String#toLowerCase:

String s = "Welcome to Baeldung!"; assertEquals("welcome to baeldung!", s.toLowerCase(Locale.UK));

Q20. How Can We Get a Character Array from String?

String provides toCharArray, which returns a copy of its internal char array pre-JDK9 (and converts the String to a new char array in JDK9+):

char[] hello = "hello".toCharArray(); assertArrayEquals(new String[] { 'h', 'e', 'l', 'l', 'o' }, hello);

Q21. How Would We Convert a Java String into a Byte Array?

By default, the method String#getBytes() encodes a String into a byte array using the platform’s default charset.

And while the API doesn't require that we specify a charset, we should in order to ensure security and portability:

byte[] byteArray2 = "efgh".getBytes(StandardCharsets.US_ASCII); byte[] byteArray3 = "ijkl".getBytes("UTF-8");

4. String-Based Algorithms

In this section, we'll discuss some programming questions related to Strings.

Q22. How Can We Check If Two Strings Are Anagrams in Java?

An anagram is a word formed by rearranging the letters of another given word, for example, “car” and “arc”.

To begin, we first check whether both the Strings are of equal length or not.

Then we convert them to char[] array, sort them, and then check for equality.

Q23. How Can We Count the Number of Occurrences of a Given Character in a String?

Java 8 really simplifies aggregation tasks like these:

long count = "hello".chars().filter(ch -> (char)ch == 'l').count(); assertEquals(2, count);

And, there are several other great ways to count the l's, too, including loops, recursion, regular expressions, and external libraries.

Q24. How Can We Reverse a String in Java?

There can be many ways to do this, the most straightforward approach being to use the reverse method from StringBuilder (or StringBuffer):

String reversed = new StringBuilder("baeldung").reverse().toString(); assertEquals("gnudleab", reversed);

Q25. How Can We Check If a String Is a Palindrome or Not?

A palindrome is any sequence of characters that reads the same backward as forward, such as “madam”, “radar” or “level”.

To check if a string is a palindrome, we can start iterating the given string forward and backward in a single loop, one character at a time. The loop exits at the first mismatch.

5. Conclusion

En este artículo, analizamos algunas de las preguntas de entrevistas de String más frecuentes .

Todos los ejemplos de código utilizados aquí están disponibles en GitHub.