警惕不规范的变量命名

就在最近,项目组开始强调开发规范了,今天分享一个变量名命名不规范的小案例,强调一下规范的重要性。

Boolean变量名命名规范

16年底,阿里公开了《Java开发规范手册》,其中有一条便是“布尔类型不能以is为前缀”。规范中没有举出例子,但是给出了原因:会导致部分序列化框架的无法解析。

看看错误的示范,会导致什么问题,以Spring中的jdbcTemplate来进行实验。

定义实体类

@Entity
public class Bar {
    @Id
    @GeneratedValue
    private Integer id;
    private Boolean isSuccess;// 注意这是错误的命名
    private boolean isSend;// 注意这是错误的命名
    public Boolean getSuccess() {
        return isSuccess;
    }
    public void setSuccess(Boolean success) {
        isSuccess = success;
    }
    public boolean isSend() {
        return isSend;
    }
    public void setSend(boolean send) {
        isSend = send;
    }
}

其中,isSuccess使用的是包装类型Boolean,而isSend使用的是原生类型boolean,而getter,setter方法是使用Intellij IDEA自动生成的,布尔类型生成getter,setter方法时略微特殊,比如原生类型的getter方式是以is开头的。生成getter,setter方法之后,其实已经有点奇怪了,不急,继续下面的实验。

在数据库中,isSuccess被映射了 is_success,isSend被映射成了 is_send,这符合我们的预期。并且为了后续的实验,我们事先准备一条记录,用于后续的查询,在mysql的方言中,布尔类型被默认自动映射成byte,1代表ture,0代表false。

id

is_success

is_send

1

1

1

使用JdbcTemplate查询

public void test(String id) {
    RowMapper<Bar> barRowMapper = new BeanPropertyRowMapper<Bar>(Bar.class);
    Bar bar = jdbcTemplate.queryForObject("select * from bar where id = ?", new Object[]{id}, barRowMapper);
    System.out.println(bar);
}

JdbcTemplate提供了BeanPropertyRowMapper完成数据库到实体类的映射,事先我重写了Bar类的toString方法,调用 test(1)看看是否能成功映射。结果如下:

Bar{id=1, isSuccess=null, isSend=false}

数据库中是实际存在这样的字段,并且值都是true,而使用JdbcTemplate,却查询不到数据,而使用常规的命名方式命名则不会有这样的问题,这便是不遵循规范导致的问题。特别是在维护老旧代码时,如果发现有is开头的boolean值,需要额外地注意。

包装类型与原生类型

再回顾一下上述的demo,原生类型和包装类型都没有封装成功,isSuccess得到了一个null值,isSend得到了一个false值。后者足够引起我们的警惕,如果说前者会引起一个NullPointerExcepiton导致程序异常,还可以引起开发者的注意,而后者很有可能一直作为一个隐藏的bug,不被人所察觉,因为boolean的默认值为false。

在类变量中,也普遍提倡使用包装类型,而原生类型的不足之处是很明显的。以Integer num;字段为例,num=null代表的含义是num字段未被保存,未定义;而num=0代表的含义是明确的,数量为0。原生类型的表达能力有限。所以提倡在局部作用域的计算中使用原生类型,而在类变量中使用包装类型。

JavaBean规范

如今的微服务的时代,都是在聊架构,聊容器编排,竟然还有人聊JavaBean,但既然说到了规范,顺带提下。

先来做个选择题,以下选项中符合JavaBean命名规范的有哪些?:

A : ebook
B : eBook
C : Ebook
D : EBook

.

.

.

.

正确答案是:A,D

怎么样,符合你的预想吗?JavaBean规范并不是像很多人想的那样,首字母小写,之后的每一个单词首字母大写这样的驼峰命名法。正确的命名规范应该是:要么前两个字母都是小写,要么前两个字母都是大写。因为英文单词中有URL,USA这样固定形式的大写词汇,所以才有了这样的规范。特别警惕B那种形式,一些诸如sNo,eBook,eMail,cId这样的命名,都是不规范的。

由此引申出了getter,setter命名的规范,除了第一节中Boolean类型的特例之外,网上还有不少文章,强调了这样的概念:eBook对应的getter,setter应当为geteBook(),seteBook(),即当类变量的首字母是小写,而第二个字母是大写时,生成的getter,setter应当是(get/set)+类变量名。但上面已经介绍过了,eBook这样的变量命名本身就是不规范的,在不规范的变量命名下强调规范的getter,setter命名,出发点就错了。有兴趣的朋友可以在eclipse,intellij idea中试试,这几种规范/不规范的变量命名,各自对应的getter,setter方法是如何的。另外需要知晓一点,IDE提供的自动生成getter,setter的机制,以及lombok这类框架的机制,都有默认的规则,在与其他反射框架配合使用时,只有双方都遵循规范,才能够配合使用,而不能笃信框架。这一点上,有部分国产的框架工具做的并不是很好。

最后说一个和JavaBean相关的取值规范,在jsp的c标签,freemarker一类的模板语法,以及一些el表达式中,${student.name}并不是取的student的name字段,而是调用了student的getName方法,这也应当被注意,student.name如何找到对应的getter方法,需要解决上一段中提到的同样的问题,建议不确定的地方多测试,尽量采取稳妥的写法。

可能有人会觉得这样的介绍类似于“茴”字有几种写法,但笔者认为恰恰是这些小的规范,容易被人忽视,才更加需要被注意。

原文发布于微信公众号 - Kirito的技术分享(cnkirito)

原文发表时间:2017-09-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java面试通关手册

深入理解原型模式 ——通过复制生成实例

Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_G...

1823
来自专栏IT派

Python字节码介绍

如果你曾经编写亦或只是使用Python语言,那么你可能已经习惯了看Python源码文件; 源码的文件名以.py结尾。或许你也已经注意到了另一种类型的文件,文件名...

1733
来自专栏大闲人柴毛毛

Java异常体系中的秘密

相信大家每天都在使用Java异常机制,也相信大家对try-catch-finally执行流程烂熟于胸。本文将介绍Java异常机制的一些细节问题,这些问题虽然很...

36010
来自专栏Python中文社区

有效的python属性管理:描述符的使用

專 欄 ❈Pytlab,Python中文社区专栏作者。主要从事科学计算与高性能计算领域的应用,主要语言为Python,C,C++。熟悉数值算法(最优化方法,蒙...

1969
来自专栏编程

享学课堂谈-Python程序员的常见错误

这些是Python初学者活生生犯的错,千百次的错。事实上,这些错误实在是太普遍了以至于我敢保证你刚开始学的时候是一定会犯的。 “那么是什么呢?”你会问,“你也会...

1919
来自专栏hbbliyong

C++为啥要使用new

1.为什么要有new? 为什么要有new?为什么要动态创建对象?为什么有时候不用new,有时候又用new,比如: // Cocos2d-x3.x的Value类,...

40612
来自专栏安恒网络空间安全讲武堂

​CTF逆向——常规逆向篇(下)

CTF逆向——常规逆向篇(下) 题目: CrackMe.exe(NSCTF reverse第一题) WHCTF2017 reverse HCTF reverse...

4895
来自专栏mini188

学习笔记:因为java匿名类学习到接口的一些小用法

在看CometD的示例代码时发现了许多有意思的代码,但说实话看别人的代码确实是件很累的事情,所以就看到这个知识点做一下记录吧。 先看一段代码: ? 代码1 这段...

2208
来自专栏令仔很忙

javascript变量:全局?还是局部?这个得注意

        如果有Var,在函数内部声明变量是局部变量,如下例,读取不到name的数据。

1053
来自专栏大内老A

yield在WCF中的错误使用——99%的开发人员都有可能犯的错误[上篇]

在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题。这里要说的是另一个问题:对于返回类型为...

1818

扫码关注云+社区

领取腾讯云代金券