小知识 | Java中的“魔数”
转载自 小知识 | Java中的“魔数”
在编程过程中,我们可能经常听到“魔数”这个词,那么这个词到底指的是什么呢?什么数叫做魔数呢?
一、标识文件类型的“魔数”
大多数情况下,我们都是通过扩展名来识别一个文件的类型的,比如我们看到一个.txt类型的文件我们就知道他是一个纯文本文件。但是,扩展名是可以修改的,那一旦一个文件的扩展名被修改过,那么怎么识别一个文件的类型呢。这就用到了我们提到的“魔数”。
很多类型的文件,其起始的几个字节的内容是固定的(或是有意填充,或是本就如此)。因此这几个字节的内容也被称为魔数 (magic number),因为根据这几个字节的内容就可以确定文件类型。有了这些魔术数字,我们就可以很方便的区别不同的文件。
为了方便虚拟机识别一个文件是否是class类型的文件,SUN公司规定每个class文件都必须以一个word(四个字节)作为开始,这个数字就是魔数。魔数是由四个字节的无符号数组成的,而class文件的名字还挺好听的的,其魔数就是0xCAFEBABE
读者可以随便编译一个class文件,然后然后用十六进制编辑器打开编译后的class文件,基本格式如下:
如何使用16进制打开class文件:使用 vim test.class ,然后在交互模式下,输入:%!xxd 即可。
二、代码中的魔数
在有些代码中,有一些数字常量或者字符串,他们没有注释,并且从命名上也看不出什么意思,很可能在过一段时间之后谁也不知道这个常量或者字符串代表什么意思。我们就称这个常量或者字符串为魔数。
在《阿里巴巴Java开发手册》中也有关于魔数的要求:
所有需要使用魔数的地方,都可以使用枚举或者静态变量来代替。譬如一个很简单的根据职位计算薪水的方法:
public int getSalary(String title, int grade) { if ("Programmer".equals(title)){ return grade * 500 + 700; }
else if ("Tester".equals(title)){ return grade * 500 + 800; }
else if ("Analyst".equals(title)){ return grade * 800 + 1000; }}
在这个方法里面,"Programmer","Tester"和"Analyst"是所谓的魔字符串(Magic String),而500, 700,800和1000就是所谓的魔数(Magic Number)了。 咋一看,代码这样写也没有什么问题,但是,仔细思考一下就会发现,如果这种随手捻来的字符串和数字散布于程序当中,随处可见的话,是会有很多弊病的。
如果我们使用常量来代替上面的魔数的话,代码就会清爽很多,而且,下次修改的时候只需要修改常量值就可以了。
public int getSalary(String title, int grade) { if (Constants.TITLE_PROGRAMMER.equals(title)){ return grade * Constants.BASE_SALARY_LOW + Constants.ALLOWANCE_LOW; } else if (Constants.TITLE_TESTER.equals(title)){ return grade * Constants.BASE_SALARY_LOW + Constants.ALLOWANCE_MEDIUM; } else if (Constants.TITLE_ANALYST.equals(title)){ return grade * Constants.BASE_SALARY_HIGH + Constants.ALLOWANCE_HIGH; }}
在代码中使用魔数,不仅使代码的可读性大大降低,还可能导致各种问题。所以在代码中,我们要尽量避免产生魔数。
小知识 | Java中的“魔数”相关推荐
- 聊聊编程中的 “魔数”
大家好,我是鱼皮,无意间在网上看到了这么一张图: 刚看到这段代码时,我是比较吃惊的,作者竟然使用了一个英文单词 deadbeef 来定义宏常量! 我本来以为只是一位幽默的程序员的小玩笑,但后来查阅资料 ...
- Java中实现十进制数转换为二进制的几种办法
Java中实现十进制数转换为二进制 第一种:除基倒取余法 这是最符合我们平时的数学逻辑思维的,即输入一个十进制数n,每次用n除以2,把余数记下来,再用商去除以2...依次循环,直到商为0结束,把余数倒 ...
- Java中实现十进制数转换为二进制
Java中实现十进制数转换为二进制 第一种:除基倒取余法 这是最符合我们平时的数学逻辑思维的,即输入一个十进制数n,每次用n除以2,把余数记下来,再用商去除以2-依次循环,直到商为0结束,把余数倒着依 ...
- java定义一个eat方法_小黄鸭系列java基础知识 | java中的方法
前言 今天我们要探讨的问题,是java基础语法的最后一个问题,也就是java中的方法,今天主要从以下几个方面来介绍: 方法是什么(定义) 方法的分类 方法的调用 应该说,学完今天的知识,你至少应该看懂 ...
- c语言冷门小知识,生活中的冷门小知识有哪些
其实生活中充满了冷门知识,比如喝醋能够防止晕车.花生可以祛牙黄等等.下面是学习啦小编为大家整理的关于生活中的冷门小知识,希望大家喜欢! 生活中的冷门小知识 洗衣机强档比弱档节能 很多人没注意,在同样长 ...
- java中的冰雹数,java实现第七届蓝桥杯打印数字
打印数字 打印数字 小明写了一个有趣的程序,给定一串数字. 它可以输出这串数字拼出放大的自己的样子. 比如"2016"会输出为: 00000 1 6666 2 0 0 1 1 6 ...
- java中对象字节数_JAVA中求解对象所占字节大小
该类为cache4j缓存框架中的工具类方法,该方法实现了两个接口 接口1:计算对象在内存中所占字节数 接口2:复制对象,实现深度克隆效果,实现原理为先序列化对象,然后在反序列化对象:返回一个新的对象, ...
- 在Java中实现两数相乘
要实现两数相乘算总额:input1.value() * input2.value() 如果直接获取到两个input值相乘,那么结果就有一点点小偏差,是因为精度缺失 $("#totalSum& ...
- python中函数的参数_Python小知识-Python中的函数参数(基础篇)
0 总述 这个题目分为2篇,第一篇基本上是概念以及实例,有个相对系统的认识,第二篇想写的深入一些,不同参数类型的区别以及和c/c++的函数参数对比下异同-下面开始是第一篇的内容啦- Python中的函 ...
最新文章
- 牛客练习赛81 小Q与彼岸花 (分块+可持久化01trie)
- Fikker 站长缓存无法缓存用 IIS 做 Web 服务器的 PHP 页面的解决方法
- Vue创建组件的三种方式
- 6、函数返回值、this、递归及回调函数
- 互联网分布式架构--演进过程
- LeetCode Algorithm 剑指 Offer 25. 合并两个排序的链表
- TCP/IP的二层负载
- Seata AT模式
- 按钮自动居中布局_CSS布局技巧
- java的编辑框丢失焦点_java – 捕获EditText丢失焦点
- 在Ubuntu 16.04 安装python3.6 环境并设置为默认
- android的fragment讲解
- 岁月的脚步,被时间冲刷——如何修复EM ?
- Redis配置文件redis.conf参数详解
- 第三方支付接口现号,第三方支付接口对接,第三方支付接口申请
- RunApi在发送请求的时候添加Token
- matlab怎样编程形成软件_Matlab编程笔记之GUI程序转exe
- 用SRS搭建流媒体系统
- 基于51单片机的数字气压计
- Scaled-YOLOv4: Scaling Cross Stage Partial Network