String面试知识点总结

String三大核心机制

  1. 不变性:是一个immutable模式的对象,不变模式的主要作用是当一个对象需要被多线程共享并频繁访问时,可以保证数据的一致性
  2. 常量池优化:String对象创建后,会在字符串常量池进行缓存,下次创建同样的对象时,会直接返回缓存的引用
  3. final:String类不可继承,提高了系统的安全性

常见的考点

String类型不是基本数据类型,String底层实现为char类型的数组

// 部分源码
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

String实例化有两种方式:

  • 直接赋值
  • 通过构造函数:可以以字符串的形式传入,也可以传入一个char类型的数组
public static void main(String[] args) {
    char[] arr = {'你', '好'};
    String str1 = new String(arr);
    String str2 = new String("Hello World");
    String str3 = "Hello World";
}

直接赋值和通过构造函数创建的主要区别在于储存的区域不同,直接赋值的储存在字符串常量池中

public static void main(String[] args) {
    String str1 = "Hello";
    String str2 = "Hello";
    System.out.println(str1 == str2); // true
}

通过构造函数创建的储存在堆内存中

public static void main(String[] args) {
    String str1 = new String("Hello");
    String str2 = new String("Hello");
    System.out.println(str1 == str2); // false
}

String的equals方法:String的equals方法重写了Object类equals的方法,将String类型转换为char类型的数组,然后依次比较数组的每一位。

// equals源码
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

String不可变性:String的值一旦修改就会是一个新的对象,不是再原来的对象了

public static void main(String[] args) {
    String str1 = "abc";
    String str2 = str1;
    str1 += "def";
    System.out.println(str1 == str2); // false
}

String的intern()方法

当调用某个字符串对象的intern()方法时,会先去字符串常量池中寻找,如果已经存在一个值相等的字符串对象的话,则直接返回该对象的引用;如果不存在,则在字符串常量池中创建该对象,并返回。

public static void main(String[] args) {
    String str1 = "Hello World";
    String str2 = new String("Hello World");
    System.out.println(str1 == str2); // false
    String str3 = str2.intern();
    System.out.println(str1 == str3); // true
}

String 常用方法

1、字符串截取

  • public String substring(int beginIndex):从beginIndex开始截取,直到字符串结尾
  • public String substring(int beginIndex,int endIndex):从beginIndex开始截取,直到endIndex结束,不包含endIndex

注意:截取之后原字符串不变

public static void main(String[] args) {
    String str1 = "HelloWorld";
    String substr1 = str1.substring(4);
    String substr2 = str1.substring(4, 7);
    System.out.println(str1);    // HelloWorld
    System.out.println(substr1); // oWorld
    System.out.println(substr2); // oWo
}

2、字符串分割

  • public String[] split(String regex):将字符串按照regex分割成数组,同时支持正则表达式
public static void main(String[] args) {
    String str = "python java;golang,javascript";
    String[] arr = str.split("[,|;| ]");
    System.out.println(Arrays.toString(arr)); // [python, java, golang, javascript]
}

面试真题

要弄懂String类型,要先明白常量和变量的区别。常量是在编译时期就知道值是多少的;而变量是在运行时期才能确定值的

public static void main(String[] args) {
    String str1 = "helloWorld";
    String str2 = "hello" + "World";
    System.out.println(str1 == str2); // true
}

字符串hello和字符串World都是常量,拼接之后的值还是保存在字符串常量池中的,所以地址相同

public static void main(String[] args) {
    String str1 = "helloWorld";
    String str2 = "hello";
    str2 += "World";
    System.out.println(str1 == str2); // false
}

看似和上一题差不多,但实际上上一题的str2是有两个常量相加得到的,所以str2储存的是常量池中地址;而这一道题的str2是一个变量,变量储存在堆之中,同样一个变量加一个常量还是储存在堆中的,所以地址是不同的

public static void main(String[] args) {
    String str1 = "helloWorld";
    String str2 = "hello";
    String str3 = str2 + "World";
    System.out.println(str1 == str3); // false
}

同理,str1在常量池中,str3在堆中,所以他们的引用一定不相等

public static void main(String[] args) {
    String str1 = "helloWorld";
    final String str2 = "hello";
    String str3 = str2 + "World";
    System.out.println(str1 == str3); // true
}

这里str2加上final关键字之后称为常量,保存在常量池中,在加上常量World之后返回的值还是常量,所以str1str3是相等的

public static void main(String[] args) {
    String str1 = "helloWorld";
    final String str2 = new String("hello");
    String str3 = str2 + "World";
    System.out.println(str1 == str3); // false
}

这里虽然加上了final但是通过构造函数创建的对象本身就是储存在堆中的

public static void main(String[] args) {
    String str1 = "helloWorld";
    String str2 = "hello";
    String str3 = "World";
    String str4 = str2 + str3;
    System.out.println(str1 == str4); // false
    System.out.println(str1 == str4.intern()); // true
}

参考资料:https://blog.csdn.net/qq_34490018/article/details/82110578

你可能感兴趣的:(基础知识)