面试题:关于String问题解析 痛定思痛。 2022-05-19 05:41 209阅读 0赞 转自:[https://news.html5.qq.com/share/8231365430231037443?url=http%3A%2F%2Fkuaibao.qq.com%2Fs%2F20180720G1Z6ZM00&sh\_sid=2\_\_o9GiTuKTxqLODvwWCSc44du58fvo\_\_34cdb13bb403bc9dea12119410b088cb&ch=060000&qbredirect=&share=true&sc\_id=JIAkiFC][https_news.html5.qq.com_share_8231365430231037443_url_http_3A_2F_2Fkuaibao.qq.com_2Fs_2F20180720G1Z6ZM00_sh_sid_2_o9GiTuKTxqLODvwWCSc44du58fvo_34cdb13bb403bc9dea12119410b088cb_ch_060000_qbredirect_share_true_sc_id_JIAkiFC] ### 总结: ### 例:String str = new String("a")到底生成了几个对象 String 内存分析 创建对象分析: 2个,先去 "字符串池" 中找 "a", 没有找到,在 "字符串池" 中创建 "a" 这个String 对象,然后new String("a") 在堆中创建一个 String 对象(因为 new 关键字一出现,肯定会创建一个对象); 1个,先去先去 "字符串池" 中找 "a",找到 "a",存在,就不再生成"a" 这个String 对象,然后new String("a") 在堆中创建一个 String 对象(因为 new 关键字一出现,肯定会创建一个对象)。 循环i = 0; gh = "a0"; 先去 "字符串池" 中找 "a0", 没有找到,在 "字符串池" 中创建 "a0" 这个String 对象i = 1; gh = "a01"; 先去 "字符串池" 中找 "a01", 没有找到,在 "字符串池" 中创建 "a01" 这个String 对象 ### 原文: ### 字符串(java.lang.String 类)的使用 Java 字符串就是 Unicode 字符序列,例如串 “Java” 就是 4 个 Unicode 字符 J,a,v,a 组成的。Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个预定义的类String,每个用双引号括起来的字符串都是 String 类的一个实例。String e = “” ; // an empty stringString greeting = “Hello World”;Java 允许使用符号 "+" 把两个字符串连接起来String s1 = “Hello”;String s2 = “World!”;符号 “+” 把两个字符串按给定的顺序连接在一起,并且是完全按照给定的形式。当 “+” 运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串然后再进行连接int age = 18;String s = "age is" + age; //s赋值为age is 18这种特性通常被用在输出语句中: 字符串类常用的方法 char charAt(int index)返回字符串中第 index 个字符。boolean equals(String other)如果字符串与 other 相等,返回 true。因为 String 类重写了 equals 方法。boolean equalsIgnoreCase(String other)如果字符串与 other 相等(忽略大小写),则返回 trueint indexOf(String str) lastIndexOf()返回与 str 匹配的第一个字符串的开始位置,该位置从 0 开始计算,如果原始串中不存在 str,返回 -1。int indexOf(String str,int fromIndex)返回与 str 匹配的第一个字符串的开始位置,该位置从 fromIndex 开始计算,如果原始串中不存在 str,返回 -1。int length()返回字符串的长度。String replace(char oldChar,char newChar)返回一个新串,它是通过用 newChar 替换此字符串中出现的所有oldChar而生成的boolean startsWith(String prefix)如果字符串以prefix开始,则返回 trueboolean endsWith(String prefix)如果字符串以 prefix 结尾,则返回 trueString substring(int beginIndex)返回一个新字符串,该串包含从原始字符串 beginIndex 到串尾的所有字符String substring(int beginIndex,int endIndex)返回一个新字符串,该串包含从原始字符串 beginIndex 到串尾或 endIndex-1 的所有字符String toLowerCase()返回一个新字符串,该串将原始字符串中的所有大写字母改成小写字母String toUpperCase()返回一个新字符串,该串将原始字符串中的所有小写字母改成大写字母String trim()返回一个新字符串,该串删除了原始字符串头部和尾部的空格 **注:在 Java 中某个索引区间进行一些操作的方法,索引取值范围一般都是包头不包尾,就拿上面的String substring(int beginIndex,int endIndex) 来说,它是截取子串 从beginIndex 开始 到endIndex - 1 结束。** 字符串相等的判断 equals 方法用来检测两个字符串内容是否相等。如果字符串 s 和 t 内容相等,则s.equals(t) 返回 true,否则返回 false.s 和 t 既可以是字符串变量,也可以是字符串常量,例如: “Hello”.equals(t);要测试两个字符串除了大小写区别外是否是相等的,需要使用 equalsIgnoreCase 方法,例如:“Hello”.equalsIgnoreCase(“hellO”); //true判断字符串是否相等不要使用 "==","=="比较是引用是否相等(是否为同一个对象) String 内存分析 创建了 4 个对象分析:先去 "字符串池" 中找 "a", 没有找到,在 "字符串池" 中创建 "a" 这个String 对象,先去先去 "字符串池" 中找 "a",找到 "a", new String("a") 在堆中创建一个 String 对象(因为 new 关键字一出现,肯定会创建一个对象)。循环i = 0; gh = "a0"; 先去 "字符串池" 中找 "a0", 没有找到,在 "字符串池" 中创建 "a0" 这个String 对象i = 1; gh = "a01"; 先去 "字符串池" 中找 "a01", 没有找到,在 "字符串池" 中创建 "a01" 这个String 对象 思考 String 不是不可变对象吗?那为什么可以字符串拼接啊?你是在逗我吗?String JDK 源码 ![225254_2251658357_1_549_174.jpg][] final 修饰了 String 类,使得 String 类不可被继承。final 修饰了 char value\[\],使得字符串的值不可以改变。但是 final 并没有修饰 String 的引用,即 final String str;这样的话,字符串的引用可以改变指向,比如上面的字符串拼接,gh 刚开始指向 "a",随着拼接又指向了 "a0"、"a01"。实际上这个过程中只是 gh 这个引用的指向在改变,"a"、"a0"、"a01" 并没有被改变。注:这是我画的几个草图为了帮助大家理解,实际上字符串的内存分析要比这个复杂点。 ![225254_2251658357_2_579_303.jpg][] ![225254_2251658357_3_581_320.jpg][] ![225255_2251658357_4_575_313.jpg][] 明显可以看出来(在字符串拼接的过程中,创建出来的这些中间 String 对象并不会被回收),"+" 字符串拼接对于内存的浪费比较大,如果是服务器端编程,多线程将会很浪费空间。 字符串拼接存在的问题 要得到上面的 s4,就会 s1 和 s2 拼接生成临时一个 String 对象 t1,内容为 "hello word",然后有 t1 和 s3 拼接生成最终我们需要的 s4 对象,这其中,产生了一个中间的 t1,而且 t1 创建之后,没有主动回收,势必会占一定的空间。如果是一个很多(尤其是一个部署到服务器上的项目,每个用户开一个线程,那用户越来越多的时候这个性能的损耗就很明显了)字符串的拼接,那么代价就更大了,性能一下会降低很多。一个 Java 程序如果想运行起来,需要经过两个时期,编译时和运行时。在编译时,Java 编译器(Compiler)将 java 文件转换成字节码。在运行时,Java 虚拟机(JVM)运行编译时生成的字节码。通过这样两个时期,Java 做到了所谓的一处编译,处处运行。早期的版本中,字符串拼接是会在常量池创建对象的,所以不少编程规范都会说不要直接用加号去拼接字符串,因为老是去常量池创建对象的话,开销也不小。在 jdk5.0 之后 java 对字符串拼接做了编译器的优化处理。当 Java 编译器遇到字符串拼接的时候,会创建一个 StringBuilder 对象,后面的拼接,实际上是调用 StringBuilder 对象的 append 方法。这样就不会有我们上面担心的问题了。 分析上边这个代码,看起来没毛病。但是这里面有一个很重要的就是 StringBuilder 对象创建发生在循环之间,也就是意味着有多少次循环会创建多少个 StringBuilder 对象,这样明显不好。稍微优化一下。 ![225255_2251658357_5_551_174.jpg][] StringBuilder 对象的创建在循坏外面,这样就只创建了一个对象,比较好。 **总结** 我们在循环体中需要尽量避免隐式或者显式创建 StringBuilder。 也就是说平时简单的拼接,直接 "+" 号拼接就行;如果要用循环,就在外面 new 个StringBuilder 对象,然后循环里 append 拼接就行了好。 其实对于循坏来说,尽量避免在循坏里创建对象,可以将创建对象这个操作放在循坏外面,这样我们就让这个对象达到复用了。 [https_news.html5.qq.com_share_8231365430231037443_url_http_3A_2F_2Fkuaibao.qq.com_2Fs_2F20180720G1Z6ZM00_sh_sid_2_o9GiTuKTxqLODvwWCSc44du58fvo_34cdb13bb403bc9dea12119410b088cb_ch_060000_qbredirect_share_true_sc_id_JIAkiFC]: https://news.html5.qq.com/share/8231365430231037443?url=http%3A%2F%2Fkuaibao.qq.com%2Fs%2F20180720G1Z6ZM00&sh_sid=2__o9GiTuKTxqLODvwWCSc44du58fvo__34cdb13bb403bc9dea12119410b088cb&ch=060000&qbredirect=&share=true&sc_id=JIAkiFC [225254_2251658357_1_549_174.jpg]: http://zxpic.imtt.qq.com/zxpic_imtt/2018/07/20/2250/sizedimage/225254_2251658357_1_549_174.jpg [225254_2251658357_2_579_303.jpg]: http://zxpic.imtt.qq.com/zxpic_imtt/2018/07/20/2250/sizedimage/225254_2251658357_2_579_303.jpg [225254_2251658357_3_581_320.jpg]: http://zxpic.imtt.qq.com/zxpic_imtt/2018/07/20/2250/sizedimage/225254_2251658357_3_581_320.jpg [225255_2251658357_4_575_313.jpg]: http://zxpic.imtt.qq.com/zxpic_imtt/2018/07/20/2250/sizedimage/225255_2251658357_4_575_313.jpg [225255_2251658357_5_551_174.jpg]: http://zxpic.imtt.qq.com/zxpic_imtt/2018/07/20/2250/sizedimage/225255_2251658357_5_551_174.jpg
相关 Java面试必问:关于集合操作的问题解析 在Java面试中,对于集合操作的题目通常会涉及以下几个方面: 1. **基础操作**: - 如何创建一个空的集合? - 集合中元素如何添加(如List、Set)? 谁践踏了优雅/ 2024年09月11日 19:15/ 0 赞/ 4 阅读
相关 Java 核心面试题全解析 每个技术人都有个大厂梦,我觉得这很正常,并不是饭后的谈资而是每个技术人的追求。像阿里、腾讯、美团、字节跳动、京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司/小... 冷不防/ 2024年05月23日 22:12/ 0 赞/ 32 阅读
相关 Java高薪面试题+答案+解析 01 anonymousinnerclass(匿名内部类)是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)? 不行,对于 ゝ一世哀愁。/ 2024年03月16日 15:14/ 0 赞/ 22 阅读
相关 HTML面试题及解析 HTML部分常见问题 1、怎么让一个不定宽高的DIV,垂直水平居中? 使用CSS方法: 父盒子设置:display:table-cell;text-align:cente 淩亂°似流年/ 2023年10月09日 16:33/ 0 赞/ 16 阅读
相关 C#面试题及详细解析 请简述async函数的编译方式 async/await是C\5.0推出的异步代码编程模型,其本质是编译为状态机。只要函数前带上async,就会将函数转换为状态机。 请简述T ╰半橙微兮°/ 2023年10月09日 16:27/ 0 赞/ 10 阅读
相关 String str=new String("123"); 经典面试题再解析 String str=new String("123"); 创建了几个对象啊 在我出道的时候载过,现在我知道是两个:和等号= 左边的没有关系; 一个是:"123" 朱雀/ 2022年08月22日 04:56/ 0 赞/ 151 阅读
相关 Java String 解析 在开发过程中,使用\`List 解决方案:改用List<List<String>>,替换掉List<String[]> import java.io.; 灰太狼/ 2022年06月02日 00:44/ 0 赞/ 175 阅读
相关 面试题:关于String问题解析 转自:[https://news.html5.qq.com/share/8231365430231037443?url=http%3A%2F%2Fkuaibao.qq.com% 痛定思痛。/ 2022年05月19日 05:41/ 0 赞/ 210 阅读
相关 java String 解析 [https://www.cnblogs.com/zhangyinhua/p/7689974.html][https_www.cnblogs.com_zhangyinhua_p ╰+哭是因爲堅強的太久メ/ 2021年09月22日 00:14/ 0 赞/ 288 阅读
还没有评论,来说两句吧...