Java String Interview Questions and Answers – Java字符串面试问题和答案

最后修改: 2019年 1月 7日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

The String class is one of the most widely used classes in Java, which prompted language designers to treat it specially. This special behavior makes it one of the hottest topics in Java interviews.

String是Java中使用最广泛的类之一,这促使语言设计师对其进行特殊处理。这种特殊的行为使它成为Java访谈中最热门的话题之一。

In this tutorial, we’ll go through some of the most common interview questions about String.

在本教程中,我们将通过一些关于String的最常见的面试问题。

2. String Fundamentals

2.字符串基础

This section consists of questions that concern the String internal structure and memory.

本节由涉及String内部结构和内存的问题组成。

Q1. What Is a String in Java?

Q1.什么是Java中的字符串?

In Java, a String is represented internally by an array of byte values (or char values before JDK 9).

在Java中,String在内部由byte值(或JDK 9之前的char值)组成的数组表示。

In versions up to and including Java 8, a String was composed of an immutable array of Unicode characters. However, most characters require only 8 bits (1 byte) to represent them instead of 16 bits (char size).

在包括Java 8在内的版本中,String是由Unicode字符的不可变数组组成。然而,大多数字符只需要8位(1字节)来表示,而不是16位(char大小)。

To improve memory consumption and performance, Java 9 introduced compact Strings. This means that if a String contains only 1-byte characters, it will be represented using Latin-1 encoding. If a String contains at least 1 multi-byte character, it will be represented as 2 bytes per character using UTF-16 encoding.

为了改善内存消耗和性能,Java 9 引入了compact Strings。这意味着,如果一个String只包含1字节的字符,它将使用Latin-1编码来表示。如果一个String包含至少1个多字节的字符,它将被表示为使用UTF-16编码的每个字符2字节。

In C and C++, String is also an array of characters, but in Java, it’s a separate object with its own API.

在C和C++中,String也是一个字符数组,但在Java中,它是一个独立的对象,有自己的API。

Q2. How Can We Create a String Object in Java?

Q2.我们如何在Java中创建一个字符串对象

java.lang.String defines 13 different ways to create a String. Generally, though, there are two:

java.lang.String定义了13种不同的方法来创建String。不过,一般来说,有两种。

  • Through a String literal:
    String s = "abc";
  • Through the new keyword:
    String s = new String("abc");

All String literals in Java are instances of the String class.

Java中所有的字符串字面都是String类的实例。

Q3. Is String a Primitive or a Derived Type?

Q3.String是原始类型还是派生类型?

A String is a derived type since it has state and behavior. For example, it has methods like substring(), indexOf(), and equals(), which primitives cannot have.

A String是一个派生类型,因为它有状态和行为。例如,它有像substring()indexOf()equals()这样的方法,这些都是基元不能拥有的。

But, since we all use it so often, it has some special characteristics that make it feel like a primitive:

但是,由于我们都经常使用它,所以它有一些特殊的特点,使它感觉像一个原始人。

  • While strings are not stored on the call stack like primitives are, they are stored in a special memory region called the string pool
  • Like primitives, we can use the operator on strings
  • And again, like primitives, we can create an instance of a String without the new keyword

Q4. What Are the Benefits of Strings Being Immutable?

Q4.弦是不可变的,有什么好处?

According to an interview by James Gosling, strings are immutable to improve performance and security.

根据James Gosling的采访,字符串是不可变的,以提高性能和安全性。

And actually, we see several benefits to having immutable strings:

而实际上,我们看到了几个拥有不可变字符串的好处

  • The string pool is only possible if the strings, once created, are never changed, as they are supposed to be reused
  • The code can safely pass a string to another method, knowing that it can’t be altered by that method
  • Immutably automatically makes this class thread-safe
  • Since this class is thread-safe, there is no need to synchronize common data, which in turn improves performance
  • Since they are guaranteed to not change, their hashcode can be easily cached

Q5. How Is a String Stored in Memory?

Q5.字符串是如何存储在内存中的?

According to the JVM Specification, String literals are stored in a runtime constant pool, which is allocated from the JVM’s method area.

根据JVM规范,String字面意义被存储在运行时常量池中,该池由JVM的方法区分配。

Although the method area is logically part of the heap memory, the specification does not dictate the location, memory size, or garbage collection policies. It can be implementation-specific.

尽管方法区在逻辑上是堆内存的一部分,但规范并没有规定其位置、内存大小或垃圾收集策略。

This runtime constant pool for a class or interface is constructed when the class or interface is created by the JVM.

类或接口的这个运行时常量池是在JVM创建该类或接口时构建的。

Q6. Are Interned Strings Eligible for Garbage Collection in Java?

Q6.在Java中,内部字符串是否有资格进行垃圾收集?

Yes, all Strings in the string pool are eligible for garbage collection if there are no references from the program.

是的,如果没有来自程序的引用,字符串池中的所有Strings都有资格进行垃圾回收。

Q7. What Is the String Constant Pool?

Q7.什么是字符串常量库?

The string pool, also known as the String constant pool or the String intern pool, is a special memory region where the JVM stores String instances.

字符串池,也被称为字符串常量池或字符串实习池,是一个特殊的内存区域,JVM在其中存储字符串实例。

It optimizes application performance by reducing how often and how many strings are allocated:

它通过减少分配字符串的频率和数量来优化应用性能

  • The JVM stores only one copy of a particular String in the pool
  • When creating a new String, the JVM searches in the pool for a String having the same value
  • If found, the JVM returns the reference to that String without allocating any additional memory
  • If not found, then the JVM adds it to the pool (interns it) and returns its reference

Q8. Is String Thread-Safe? How?

Q8.字符串是线程安全的吗?如何做到?

Strings are indeed completely thread-safe because they are immutable. Any class which is immutable automatically qualifies for thread-safety because its immutability guarantees that its instances won’t be changed across multiple threads.

字符串确实是完全线程安全的,因为它们是不可变的。任何一个不可变的类都自动符合线程安全的要求,因为它的不可变性保证了其实例不会在多个线程中被改变。

For example, if a thread changes a string’s value, a new String gets created instead of modifying the existing one.

例如,如果一个线程改变了一个字符串的值,就会创建一个新的String而不是修改现有的字符串。

Q9. For Which String Operations Is It Important to Supply a Locale?

Q9.对于哪些字符串操作来说,提供一个地方语言是很重要的?

The Locale class allows us to differentiate between cultural locales as well as to format our content appropriately.

Locale类允许我们区分不同的文化区域,以及适当地格式化我们的内容。

When it comes to the String class, we need it when rendering strings in format or when lower- or upper-casing strings.

当涉及到String类时,我们在渲染format中的字符串或在小写或大写字符串时需要它。

In fact, if we forget to do this, we can run into problems with portability, security, and usability.

事实上,如果我们忘记这样做,就会遇到可移植性、安全性和可用性的问题。

Q10. What Is the Underlying Character Encoding for Strings?

Q10.什么是字符串的基本字符编码?

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

根据Strings Javadocs(包括Java 8之前的版本),字符串在内部以UTF-16格式存储。

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.

char数据类型和java.lang.Character对象也是基于最初的Unicode规范,它将字符定义为固定宽度的16位实体。

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.

从JDK 9开始,只包含1字节字符的字符串使用Latin-1编码,而包含至少1个多字节字符的字符串使用UTF-16编码。

3. The String API

3.String API

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

在本节中,我们将讨论与String API有关的一些问题。

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

Q11.我们如何在Java中比较两个字符串?str1 == str2str1.equals(str2)之间有什么区别?

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

我们可以用两种不同的方式来比较字符串:通过使用等价运算符( == )和使用equals()方法。

Both are quite different from each other:

两者之间有很大不同。

  • The operator (str1 == str2checks 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.

虽然,如果两个字符串在词法上相等,那么str1.intern() == str2.intern() 也确实是

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

通常情况下,为了比较两个字符串的内容,我们应该始终使用String.equals

Q12. How Can We Split a String in Java?

Q12.如何在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类本身为我们提供了String#split方法,它接受一个正则表达式分隔符。它返回给我们一个String[]数组。

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:

关于split的一个棘手的问题是,当分割一个空字符串时,我们可能得到一个非空数组。

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

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

当然,split只是拆分JavaString的众多方法之一。

Q13. What Is Stringjoiner?

Q13.什么是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是Java 8中引入的一个类,用于将独立的字符串连接成一个字符串,例如获取一个颜色列表并将其作为一个以逗号分隔的字符串返回。我们可以提供一个分隔符以及前缀和后缀。

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

assertEquals("[Red,Green,Blue]", joiner.toString());

Q14. Difference Between String, Stringbuffer and Stringbuilder?

Q14.字符串、Stringbuffer和Stringbuilder之间的区别?

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

字符串是不可变的。这意味着如果我们试图改变或更改其值,那么Java会创建一个绝对新的字符串

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

例如,如果我们在一个字符串str1被创建后向其添加。

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

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

然后JVM不是修改str1,而是创建一个全新的String

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

然而,对于大多数简单的情况,编译器内部使用StringBuilder并优化上述代码。

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

但是,对于更复杂的代码,如循环,它将创建一个全新的String,使性能恶化。这就是StringBuilderStringBuffer的作用。

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.

Java中的StringBuilderStringBuffer都是创建持有可变字符序列的对象。StringBuffer是同步的,因此是线程安全的,而StringBuilder不是。

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

由于StringBuffer中的额外同步通常是不必要的,我们通常可以通过选择StringBuilder.获得性能提升。

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

Q15.为什么将密码存储在Char[]阵列中比存储在字符串中更安全?

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.

我们必须依靠垃圾收集器来删除字符串的内容。此外,在Java 6及以下版本中,字符串被存储在PermGen中,这意味着一旦一个String被创建,它永远不会被垃圾收集。

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.

通过使用char[]数组,我们可以完全控制该信息。 我们可以修改它或完全抹去它,甚至不需要依赖垃圾收集器。

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.

使用char[]而不是String并不能完全保证信息的安全;它只是一个额外的措施,减少了恶意用户获取敏感信息的机会。

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

Q16.字符串的intern()方法有什么作用?

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.

方法intern()在堆中创建一个String对象的精确副本,并将其存储在String常量池中,JVM维护该池。

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.

Java会自动截取所有使用字符串字面意义创建的字符串,但是如果我们使用new操作符创建一个String,例如,String str = new String(“abc”),那么Java会将其添加到堆中,就像任何其他对象一样。

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:

我们可以调用intern()方法来告诉JVM将其添加到字符串池中,如果它还不存在的话,并返回该内部字符串的一个引用。

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?

Q17.我们如何在Java中把字符串转换成整数,把整数转换成字符串?

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

String转换为Integer最直接的方法是使用Integer#parseInt

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

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

要做相反的事情,我们可以使用Integer#toString

String s = Integer.toString(num);

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

Q18.什么是String.format(),我们如何使用它?

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

String#format使用指定的格式字符串和参数返回一个格式化的字符串。

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,除非我们可以简单地接受操作系统的默认。

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?

Q19.我们如何将一个字符串转换为大写和小写?

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

String隐含地提供了String#toUpperCase来改变大小写。

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

虽然,Javadocs提醒我们,我们需要指定用户的Locale以确保正确性。

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

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

同样,要转换为小写,我们有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?

Q20.我们如何从字符串中获得一个字符数组?

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+):

String提供了toCharArray,它在JDK9之前返回其内部char数组的副本(在JDK9+中,将String转换为一个新的char数组)。

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?

Q21.我们如何将一个Java字符串转换成一个字节数组?

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

默认情况下,方法String#getBytes()使用平台的默认字符集将一个String编码为一个字节数组。

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

虽然API并不要求我们指定字符集,但我们应该这样做,以确保安全性和可移植性

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

4. String-Based Algorithms

4.基于字符串的算法

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

在本节中,我们将讨论一些与Strings有关的编程问题。

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

Q22.我们怎样才能在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.

然后我们将它们转换为char[]数组,对它们进行排序,然后检查是否相等

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

Q23.我们如何计算一个字符串中某个字符的出现次数?

Java 8 really simplifies aggregation tasks like these:

Java 8真正简化了像这样的聚合任务。

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.

而且,还有其他几种很好的方法来计算l的数量,包括循环、递归、正则表达式和外部库。

Q24. How Can We Reverse a String in Java?

Q24.我们如何在Java中反转一个字符串?

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

有很多方法可以做到这一点,最直接的方法是使用StringBuilder(或StringBuffer)的reverse方法。

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

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

Q25.我们如何检查一个字符串是否是帕林陀罗?

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

palindrome是指任何前后读数相同的字符序列,例如 “madam”、”radar “或 “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

5.结论

In this article, we went through some of the most prevalent String interview questions.

在这篇文章中,我们经历了一些最普遍的String面试问题。

All the code samples used here are available on GitHub.

这里使用的所有代码样本都可以在GitHub上找到