String 面试中需要了解的知识

239 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

String的特性

String可能是Java中最特殊的一个数据类型

  • 和基本数据类型的封装类型一样,具备不可变性
//不能被继承,不能从外部修改value
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    
        @FastNative
        public native char[] toCharArray();
        
        //外部调用都是通过native来返回的
        public String substring(int beginIndex) {
            if (beginIndex < 0) {
                throw new StringIndexOutOfBoundsException(this, beginIndex);
            }
            int subLen = length() - beginIndex;
            if (subLen < 0) {
                throw new StringIndexOutOfBoundsException(this, beginIndex);
            }
            return (beginIndex == 0) ? this : fastSubstring(beginIndex, subLen);
        }
        
       @FastNative
       private native String fastSubstring(int start, int length);
       
        public int hashCode() {
            int h = hash;
            final int len = length();
            if (h == 0 && len > 0) {
                for (int i = 0; i < len; i++) {
                h = 31 * h + charAt(i);
                }
            hash = h;
            }
            return h;
        }

}  
    

String实例的使用主要是对字面量的使用,更接近基本数据类型。

  • 声明方式像基本数据类型,但其实是引用类型
  • 作为引用类型,又不一定直接放在堆里,有可能放在字符串池(String Pool)中

线程安全度递减模型

image.png

字符串池和常量池

  • 每个类在运行时,都有自己的,与class文件对应的运行时常量池
  • 字符串池用来存全局驻留字符串的,Hotspot虚拟机中,通过一个hash表来实现
  • 常量池中的CONSTANT_String类型,会通过查询字符串池去进行解析,以保证二者对应的字符串实例是一致的。

intern方法的作用

JDK 1.7一下,字符串池在永久代,intern方法的含义是:

  • 如果字符串池中存在与当前字符串内容相同的缓存,则返回缓存实例否则在字符串池中创建相应实例,并返回 JDK1.7及以上,字符串池在堆中,字符串池中,存储的是字符串堆引用,ittern方法的含义是
  • 如果字符串池中存在与当前字符串内容相同的缓存,则返回缓存的引用,否则则在字符串池中存储当前字符串的引用

Hash(散列算法)

就是把任意长度 的输入,或者叫做预映射(pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射,也就是散列值的空间通常远小于输入空间,不同的输入可能会散列程相同的输出,而不可能从散列值来唯一的确定输入值.

image.png

java中的hashcode方法

  • 返回实例的散列值,这个方法主要是为了哈希表提供的
  • 只要不改变equals方法中使用的比较信息,每次在同一个实例上调用hashcode方法,必须始终返回相同的整数。但是在下一次程序执行时,改整数不必保持一致
  • 通过equals方法比较相等的两个实例,他们调用hashcode得到的整数必须相同
  • 通过equals方法比较不相等的两个实例,他们调用hashcode得到的整数可以相同,但是最好不相同,因为有助于提高哈希表的性能

String的hashCode选择乘数31的原因

  • 可以把四则运算转换为位运算,提高性能
  • 素数参与乘除运算,降低碰撞概率
  • 大小适中,保证结果位数是中,减少碰撞