在编程中为所欲为[圣诞版]
众所周知,在Java中final String中的值是一成不变的。大家都知道String的+(拼接)运算会丢弃内存引用并在内存中重新开拓地址,事实上也确实如此。但final的变量真的是一成不变的吗?谨以此文打开程序员思路,跳出定式思维,希望本文会给你的程序员生涯带来新的思考。
一个简单的例子
这个例子很久远,早有前辈做过,但并不是所有的程序员都接触过。通常喜欢“猎奇”的程序员对此不会陌生。
import java.lang.reflect.Field; public class ChangeFinalString { public static void main(String[] args) throws Exception { final String s = "12345: caiyongji"; System.out.println(s); System.out.println("hashcode: " + s.hashCode()); Field f = String.class.getDeclaredField("value"); f.setAccessible(true); char[] value = (char[]) f.get(s); value[0] = (char) 20851; value[1] = (char) 27880; value[2] = (char) 20844; value[3] = (char) 20247; value[4] = (char) 21495; System.out.println(s); System.out.println("hashcode: " + s.hashCode()); } }
例子中,通过final初始化一个String,然后反射获取String类中名为value的Field,并重新赋值value。执行后,你会发现String的hashcode值没有变,String的值却变了。另外,你还会发现这几行简单代码的彩蛋。
得出结论
看!是不是觉得常规可以被打破,只要有足够的技巧就可以在编程中为所欲为?也许有些严谨的程序员会指出hashcode方法的实现依赖于JVM,并不能直接反映内存的情况。说实话,你甚至不需要记住本文的例子,我只是想打破你固有的思维模式。
然而,上面的并不是我想说的真正结论。
下面,才是“圣诞版”真正的意义。
也许有些人会觉得收获颇丰,我又掌握了一个面试问题的答案。没错,甚至像阿里、百度这样的国内巨头企业中,有一些面试官(注意是有一些),确实会问一些"final变量是不可变"这样的silly question. 他们钻研一门语言甚至知道所有具体实现的细节,甚至语言的bug。 但换个角度,在如此钻研的同时,你是否考虑了你的时间成本、女朋友以及后代?!
接口论
作为一个程序员,你是业务逻辑和代码实现的接口。没人在乎你怎么实现的业务,只在乎你的代码是否高效、准确、易用、易拓展(具体讲,比如多少ms返回结果,参数结构是否简单,是否容易添加新功能)。同理,你使用Java作为你实现业务逻辑的工具,你更可以选择Python、Node.js、Kotlin甚至Linux shell脚本,那么你是否要理解Java语言的所有实现?正如我在《如何成为10倍速的程序员》中所说的不要记忆。
我是在号召大家不求甚解吗?
是的。
反设计
如果把编程手段当成一种工具,无外乎语言、文档、框架,这些都可以当成是工具的一部分。不要试图用锤子打开螺丝钉,虽然你确实可以做到。但这是反设计的。就像这个例子一样,你可以通过reflect改变final,但说白了,这种技巧并没有什么用,它会给你带来很多麻烦,比如在拓展时、在java版本升级时考虑兼容性。
所以,在使用一种“工具”时,要尽量按照工具制造者的思维模式进行使用,所有这些所谓的“技巧”都是在反设计。
最后,专注、严谨、逻辑清晰是一个程序员的品质,但在技术迭代如此迅速的大背景下,在代码中追求极致是一个人类无法做到的(如果用掌握技巧的多来衡量的话,你永远无法掌握所有技巧,并且,在技术迭代过程中,你原本掌握的技巧也在逐步淘汰。),别忘了你生活中的朋友、家人和你的爱好。
过完圣诞就是新的一年,祝所有的程序员朋友圣诞快乐(本文写于平安夜),同时在新的一年里开启程序员新的、不一样的人生。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
一次网站性能排查实录
接到一个求助电话,说是有个阿里云上的服务器,有性能瓶颈,但又没有什么具体的数据,只是说偶尔客户端有少数连接不上,或者连接会突然中断。我的天,最怕这种状况了,还得自己去找问题表现是什么,再去找什么原因所致。----懒人可直接点此处,不必辛苦看文字 因为是线上的环境,得分两步进行。先检查,看系统或者应用存在什么明显的印迹,分析原因和处理方法;协商什么时候可以处理,处理风险是什么。 怕影响用户体验,白天还不让搞。月黑风高,家里有没暖气啊(用一块闲置显卡挖矿取暖),没办法,只好熬夜苦战一番。 通过了解,该云主机带宽12M,其他方面的配置,我自己登录看就好。 既然收到带宽,就先看它了,看了好一阵,也不到10M嘛。 其他资源配置为: (1)cpu 8core (2)内存 16G (3)硬盘 50G系统加120G外挂空间。 其中系统负载一直稳定不高,IO也还过得去,系统日志也无明显的报错信息。查看网络状态,TIME_WAIT相对于ESTABLESHED来说,高了不少(因为文章为事后所写,无法再重现了)。根据经验,大致可以判断引起TIME_OUT高的原因主要有两种:一种是系统参数(sysctl.con...
- 下一篇
恢复误删除的ESXi服务器存储VMFS卷
如果不小心误删除了VMFS卷,使用partedUtil命令恢复即可。partedUtil是VMware ESXi的命令行实用程序,可以在ESXi上直接操作本地和远程 SAN 磁盘的分区表。 【说明】只有 ESXi 5.x 上的磁盘分区才支持使用 partedUtil 命令行。命令行实用程序 fdisk 不能用于采用 VMFS5 格式的 LUN。本文用于VMware ESXi 5.x、VMware ESXi 6.0格式化为VMFS 5的卷。 当前有一台DELLR 730XD的服务器,其中10块硬盘使用RAID-50划分为2个卷,第1个卷30GB,安装ESXi 6.5.0系统,第2个卷使用剩余空间,大小29.08TB,如图1-1所示。 图1-1 VMFS卷 从图1-1中可以看到,这个29.08TB的设备名称为naa.61866da07cda6500209430db1f953ce5;30GB的设备名称是61866da07cda650020942f720a174f8c。 下面我们模拟这个操作(当前是测试机器,请勿在生产机器、有重要数据机器实验,否则由此造成的损失,本文概不负责!) (1)在“存...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合Redis,开启缓存,提高访问速度
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS8编译安装MySQL8.0.19
- CentOS关闭SELinux安全模块
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- MySQL8.0.19开启GTID主从同步CentOS8