漫画:老板扣了我1000,因为我没记住阿里巴巴开发手册的这条规则。
本文故事构思来源于脉脉上的一篇帖子“一行代码引发的血案”。
其实关于字符串的文章,我之前也写过一篇《诡异的字符串问题》,字符串对于我们开发者而言,可以用最近很流行的一句话“用起来好嗨哟,仿佛人生达到了巅峰”。
确实大家都用的很嗨,很便利,但 JDK 的工程师在背后付出了努力又有几个人真的在意呢?
咱们今天就通过一个例子来详细的说明。
public class StringTest {public static void main(String[] args) {// 无变量的字符串拼接String s = "aa"+"bb"+"dd";System.out.println(s);// 有变量的字符串拼接String g = "11"+s+5;System.out.println(g);// 循环中使用字符串拼接String a = "0";for (int i = 1; i < 10; i++) {a = a + i;}System.out.println(a);// 循环外定义StringBuilderStringBuilder b = new StringBuilder();for (int i = 1; i < 10; i++) {b.append(i);}System.out.println(b);}
}
复制代码
有同学可能会说,这么一段代码,怎么来区分呢?既然我在对话中说了 Java 从 JDK5 开始,便在编译期间进行了优化,那么编译期间 javac 命令主要干了什么事情呢?一句话归根结底,那么肯定就是把 .java 源码编译成 .class 文件,也就是我们常说的中间语言——字节码。然后 JVM 引擎再对 .class 文件进行验证,解析,翻译成本地可执行的机器指令,这只是一个最简单的模型,其实现在的 JVM 引擎后期还会做很多优化,比如代码热点分析,JIT编译,逃逸分析等。
说到这里,我记得之前群里有同学说,字节码长得太丑了,看了第一眼就不想看第二眼,哈哈,丑是丑点,但是很有内涵,能量强大,实现了跨平台性。
关于怎么查看字节码,我之前分享过两个工具,一个 JDK 自带的 javap,另一个IDEA的插件 jclasslib Bytecode viewer。今天给你再分享一个,我之前破解 apk 常用的工具 jad,它会让你看字节码文件轻松很多。
先说一下,我分别用 Jdk 1.6 - 1.8 自带的 javap 工具进行了反编译,发现生成的 JVM 指令是一样的,所以在此处不会列出每一个版本生成的指令文件。为了便于大家阅读指令文件,这里用jad工具生成,代码如下。
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) annotate
// Source File Name: StringTest.javaimport java.io.PrintStream;public class StringTest
{public StringTest(){// 0 0:aload_0 // 1 1:invokespecial #1 <Method void Object()>// 2 4:return }public static void main(String args[]){String s = "aabbdd";// 0 0:ldc1 #2 <String "aabbdd">// 1 2:astore_1 System.out.println(s);// 2 3:getstatic #3 <Field PrintStream System.out>// 3 6:aload_1 // 4 7:invokevirtual #4 <Method void PrintStream.println(String)>String g = (new StringBuilder()).append("11").append(s).append(5).toString();// 5 10:new #5 <Class StringBuilder>// 6 13:dup // 7 14:invokespecial #6 <Method void StringBuilder()>// 8 17:ldc1 #7 <String "11">// 9 19:invokevirtual #8 <Method StringBuilder StringBuilder.append(String)>// 10 22:aload_1 // 11 23:invokevirtual #8 <Method StringBuilder StringBuilder.append(String)>// 12 26:iconst_5 // 13 27:invokevirtual #9 <Method StringBuilder StringBuilder.append(int)>// 14 30:invokevirtual #10 <Method String StringBuilder.toString()>// 15 33:astore_2 System.out.println(g);// 16 34:getstatic #3 <Field PrintStream System.out>// 17 37:aload_2 // 18 38:invokevirtual #4 <Method void PrintStream.println(String)>String a = "0";// 19 41:ldc1 #11 <String "0">// 20 43:astore_3 for(int i = 1; i < 10; i++)//* 21 44:iconst_1 //* 22 45:istore 4//* 23 47:iload 4//* 24 49:bipush 10//* 25 51:icmpge 80a = (new StringBuilder()).append(a).append(i).toString();// 26 54:new #5 <Class StringBuilder>// 27 57:dup // 28 58:invokespecial #6 <Method void StringBuilder()>// 29 61:aload_3 // 30 62:invokevirtual #8 <Method StringBuilder StringBuilder.append(String)>// 31 65:iload 4// 32 67:invokevirtual #9 <Method StringBuilder StringBuilder.append(int)>// 33 70:invokevirtual #10 <Method String StringBuilder.toString()>// 34 73:astore_3 // 35 74:iinc 4 1//* 36 77:goto 47System.out.println(a);// 37 80:getstatic #3 <Field PrintStream System.out>// 38 83:aload_3 // 39 84:invokevirtual #4 <Method void PrintStream.println(String)>StringBuilder b = new StringBuilder();// 40 87:new #5 <Class StringBuilder>// 41 90:dup // 42 91:invokespecial #6 <Method void StringBuilder()>// 43 94:astore 4for(int i = 1; i < 10; i++)//* 44 96:iconst_1 //* 45 97:istore 5//* 46 99:iload 5//* 47 101:bipush 10//* 48 103:icmpge 120b.append(i);// 49 106:aload 4// 50 108:iload 5// 51 110:invokevirtual #9 <Method StringBuilder StringBuilder.append(int)>// 52 113:pop // 53 114:iinc 5 1//* 54 117:goto 99System.out.println(b);// 55 120:getstatic #3 <Field PrintStream System.out>// 56 123:aload 4// 57 125:invokevirtual #12 <Method void PrintStream.println(Object)>// 58 128:return }
}
复制代码
这里说一下分析结果。
1、无变量的字符串拼接,在编译期间值都确定了,所以 javac 工具帮我们把它直接编译成一个字符常量。
2、有变量的字符串拼接,在编译期间变量的值无法确定,所以运行期间会生成一个StringBuilder 对象。
3、循环中使用字符串拼接,循环内,每循环一次就会产生一个新的 StringBuilder 对象,对资源有一定的损耗。
4、循环外使用 StringBuilder,循环内再执行 append() 方法拼接字符串,只会成一个 StringBuilder 对象。
因此,对于有循环的字符串拼接操作,建议使用 StringBuilder 和 StringBuffer,对性能会有一定的提升。
其实上面的结论,《阿里巴巴Java开发手册》中有所提到,此文正好与该条结论相对应。
一个简单的字符串,用起来确实简单,背后付出了多少工程师的心血,在此,深深地佩服詹爷。
PS:本文原创发布于微信公众号 「Java面试那些事儿」,关注并回复「1024」,免费领学习资料。 原文地址
转载于:https://juejin.im/post/5c400d44f265da614f708e68
漫画:老板扣了我1000,因为我没记住阿里巴巴开发手册的这条规则。相关推荐
- 老板扣了我1000,因为我没记住阿里巴巴开发手册的这条规则。
来源:Java面试那些事儿 本文故事构思来源于脉脉上的一篇帖子"一行代码引发的血案". 其实关于字符串的文章,我之前也写过一篇<诡异的字符串问题>,字符串对于我们开发者 ...
- 漫画丨让你专心干技术,没让你干到35岁啊…
漫画丨让你专心干技术,没让你干到35岁啊- https://www.toutiao.com/i6934625131939774983/?tt_from=weixin&utm_campaign= ...
- 老版本微信平台服务器部署步骤(没那么坑版)
老版本微信平台服务器部署步骤(没那么坑版) By Levy 1. 用putty登陆服务器 2. 安装需要的程序(nginx/python/pip/virtualenv) 3. 使用virtual ...
- 该终端已停用_宣杭老线停用,勾庄、三墩、仓前、老余杭、瓶窑三千多亩地待开发...
一 周 速 递 1.时隔120多天,主城区土拍1月5日重启 2.杭州地铁7号线首通段开通倒计时 3.杭州地铁6号线预计年底通车 4.宣杭老线今日正式停用 5.崇贤-老余杭连接线高架桥预计明年竣工 6. ...
- 都说DBA 是越老越值钱, 那你是没干过DBA
正式干DBA 也是有些年头了,十几年是有了, 前些日子翻出最早买的一本数据库的书是2001年的.这么多年,身边的开发,项目经理,应用运维等等这些"友人", 说的最多的一句话就是, ...
- 漫画 | 产品经理频繁更改需求,我没忍住把他给砍了!
众所周知,程序员是一类思维比较特殊的群体,但他们也有不为人知的烦恼,最常见的是经常被产品经理频繁改需求.拿老板来压人等-,而这些烦恼外行人是很难理解的. 就像前些年就出现过"软件公司老板被员 ...
- 龙书啃不动?老司机带你从零入门编译原理,开发编译器
计算机只认识二进制的,但是我们平常开发中根本不会使用二进制进行开发,我们使用的都是 Java.C.Python 这类的高级语言.每种语言都会经过一系列的转换才能被计算机识别,那么到底是谁做的这项工作呢 ...
- mysql环境搭载后老出错_使用Docker在window10下搭建SWOFT开发环境,mysql连接错误
使用Docker在window10下搭建SWOFT开发环境,mysql连接错误 { "code": 0, "error": "(Swoft\\Db\\ ...
- ntnub原理怎么看_老电工由浅入深带你入门学PLC的工作原理和梯形图的编程规则...
PLC编程怎么学?很难吗?工控小白怎么入门学习PLC?需要为学习PLC编程做哪些准备?学习PLC编程时,前期一定要积累相关的理论知识,有了一定的基础,基础打扎实之后就是多练习了.今天推荐的重点,是关于 ...
最新文章
- 看我如何作死 | 将CPU、IO打爆
- Learun对快速开发平台的基本认知与设定
- 设置同一Label内涵不同颜色字体
- 产品经理跳槽面试大揭秘……
- 笔记-高项案例题-2019年下-计算题
- C语言再学习 -- C 预处理器
- 百度AI学习:三、文字识别
- 数据库零碎---mysql编码设置,与乱码分析
- 3.3 rsync同步之ssh隧道方式
- display: flex; 的兼容问题解决办法
- 探讨绝对哲学存在的必要条件
- 基于OpenCV文字特征提取
- sql如何在两张表中得到每组数据,并知道数据的个数,举例,判断有多少班级,每个班的人数
- 1067 Sort with Swap(0, i) (25 分) 好,容易出错
- java中queue与stroke,ae中stroke的用法
- Verilog 语法合集
- 健身用肌酸市场前景分析及行业研究报告
- Python实现股票查询
- 剑指 Offer 19. 正则表达式匹配 regex_match() regex()
- word2007 正文自动变为大纲一级 问题
热门文章
- python读取mysql数据_如何将mysql的数据读取python
- linux共享文件权限设置,linux – Windows更改Samba文件共享中的文件权限
- 计算机二级语义网络的研究现状与展望,计算机二级access选择题题库研究.doc
- 河北师范大学计算机专业保研率,河北省内13所高校2021届保研率一览
- python注册用户名和密码登录_python实现自动登录需要用户名和密码的网站
- python初级语法_python语法基础
- vision画流程图的软件_产品流程图的定义,作用和画法
- centos7.2 安装mysql5.6_Centos7安装mysql5.6
- html5基础知识点表单
- 1.2 函数间隔和几何间隔理解2