别再乱用 String 了!底层原理、常量池、拼接陷阱全解析
做java开发String是每天都在用的类但是绝大部分人只停留在只会写、只会赋值底层还不是很了解很多人都有这样的疑惑明明都是abc为什么有时候相等、有时候不相等String 到底是不是可变的为什么都说它不可变循环里字符串拼接为什么不建议用String、StringBuilder、StringBuffer 到底该怎么选new String () 会创建几个对象常量池到底有什么用一、什么是StringString就是字符串属于引用数据类型但是用法很像基本数据类型都可以直接赋值。有三种创建String类型数据的方式1.直接用字符串赋值。2.使用new String()传字符串。3.使用new String()传字符数组。很多人只会这么写但不知道内存、常量池、底层结构差别巨大。二、核心重点为什么String是不可变的1.什么是不可变的字符串一旦建立在这个字符串的基础上拼接和修改都是创建一个新的对象进行修改的。这里指的都是字符串不可变但是String变量可以指向新的字符串原来的字符串只是没有变量引用而已依旧没有改变。2.底层原理JDK1.9 之前底层是private final char[ ]valueJDK1.9 之后优化为private final byte[ ] valuefinal数组引用不能改private外部拿不到数组改不了里面字符所以对象本体内容 彻底无法修改。能变的只有外面的引用变量。3. 设计成不可变的好处字符串常量池可以缓存复用节省大量内存线程安全不可变对象天然多线程安全哈希值固定适合做 HashMap 键作为参数传递时更安全不会被意外篡改。三、字符串常量池面试常问1.字面常量赋值String s1 java;String s2 java;System.out.println(s1 s2); //true通过比较两个引用比较的是在内存中的地址输出结果是true说明是s1和s2两个引用指向的是同一个字符串对象。这说明通过字符串给引用变量赋值是要在常量池中寻找是否有此字符串常量有直接引用无现在常量池中创建这个字符串常量再引用总之只要是通过字符串常量赋值指向的都是同一个字符串。这与Integer不一样Integer只有部分值0 - 127是直接指向已有对象超过区间是建立新的对象。2.new String( )创建先在常量池看有没有相同的字符串常量没有就创建再在堆内存创建一个新 String 对象引用指向堆里的对象。所以地址不一样是 false。3. 经典问题new String (abc) 创建几个对象常量池没有2 个常量池 1 个 堆 1 个常量池已有1 个只在堆创建四、字符拼接1.普通拼接String s a b c;编译期会直接优化成String s new String(abc)放入常量池效率很高。2.循环拼接String str ;for (int i 0; i 1000; i) {str i; }每一次都会生成新的 String 对象大量创建废弃对象浪费内存、效率极低。循环拼接字符串一律用 StringBuilder。常量、少量拼接 →String单线程循环拼接 →StringBuilder多线程共享拼接 →StringBuffer
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2592934.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!