Java-String 常见问题

264 阅读3分钟
  • String 属于基本的数据类型么?

    • String不属于基本类型, Java 的基础类型有 boolean, byte, short, char, int, long, float, double, 而String属于引用类型.
  • Java 中操作字符串有哪些类? 它们区别是什么?
    Java 中操作字符串的类有String, StringBuilder, StringBuffer三种.

    StringStringBuilder, StringBuffer的区别在于String是不可变的, 对String的操作都会导致一个新的String产生; StringBuilder, StringBuffer可以更改字符串的内容, 当内容不再更改之后, 可以调用 toString()方法来产生一个String.

    StringBuilder, StringBuffer的区别在于StringBuilder是线程不安全的, StringBuffer是线程安全的, StringBuffer中的方法都采用synchronized关键字修饰. 因此在单线程环境中使用StringBuilder可以获得更好的性能.

  • 如何将字符串内容反转?

    • 可以调用StringBuilderStringBufferreverse()方法, String并没有提供reverse()方法.
  • String#split()方法注意事项?

    • split()方法会去掉尾部长度为 0 的字符串.

      String str = "my,name,is,,,";
      String[] strArr = str.split(",");
      System.out.println(Arrays.toString(strArr));
      

      输出结果如下图所示, String#split()方法实际上是产生了六个字符串, 只不过最后三个字符串的长度都为 0, 所以被去掉了.

      spplit

      // Construct result
      int resultSize = list.size();
      if (limit == 0) {
          // 这里从尾部开始判断字符串长度, 若长度为 0, 则去掉.
          while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
              resultSize--;
          }
      }
      String[] result = new String[resultSize];
      return list.subList(0, resultSize).toArray(result);
      
  • 下面代码创建几个字符串对象?

    String str = new String("Hello");
    

    若常量池已经存在Helllo, 则创建一个; 若不存在则创建两个, 一个是由类加载的时候在运行时常量池创建的, 一个是在执行new的时候在堆上创建的.

  • 下面代码输出是什么?

    String str1 = "Hello";
    String str2 = new String("Hello");
    String str3 = str2.intern();
    // 输出 false
    System.out.println(str1 == str2);
    // 输出 true
    System.out.println(str1 == str3);
    

    当调用intern()方法时会去常量池中查找是否有相等的字符串(这里的相等的标准和String#equals()方法标准相同), 如果相同则返回其的引用; 如果没有, 则将该字符串的引用加入到常量池中, 并返回在常量池中的引用. 在上面代码中由于Hello在常量池中存在, 所以直接返回该常量的引用了.

    下面代码执行结果为true. 因为执行str1.intern()方法时, 字符串 计算机软件 在常量池中并不存在, 所以这时将该字符串的引用放置到常量池中, 然后再将其返回, 所以这时返回的值就是变量str1的值.

    String str1 = new StringBuilder("计算机").append("软件").toString();
    // 输出true
    System.out.println(str1.intern() == str1);
    
  • 为什么String适合做HashMap的 key?

    • 因为字符串是不可变的, 当调用StringhashCode()方法时会把String的 hashCode 存储起来, 这样就可以避免重复计算, 从而带来效率上的提升.
      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;
      }
      
  • String为什么是不变的?

    • 由于String的不可变, 可以让多个String变量指向常量池中的同一个常量, 从而节省内存.
    • 由于String的不可变, 可以让多个线程访问同一个String而不用担心同步的问题.
  • 参考:
    [1] : 我终于搞清楚了和String有关的那点事儿
    [2] : Java String Interview Questions And Answers
    [3] : 请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧
    [4] : Java 中new String("字面量") 中 "字面量" 是何时进入字符串常量池的?
    [5] : 深入理解Java虚拟机(第2版)