精华内容
下载资源
问答
  • 阿里巴巴java开发规范学习

    千次阅读 2019-05-12 10:39:31
    目录 一、编程规约 ...最近回顾了下一个多月前写的新项目,发现很多地方总感觉不太规范,从代码到数据库等,因此从网上下载了这份阿里巴巴java开发规范,学习记录下。 完整版手册下载地址:https:...

    目录

    一、编程规约

    1.1 命名风格

    1.2 常量定义

    1.3 代码格式

    ​1.4 OOP规约

    1.5 集合处理

    二、异常

    三、MYSQL数据库

    3.1 建表规约

    3.2 索引规约

    3.3 SQL语句


    最近回顾了下一个多月前写的新项目,发现很多地方总感觉不太规范,从代码到数据库等,因此从网上下载了这份阿里巴巴java开发规范,学习记录下。

    完整版手册下载地址:https://102.alibaba.com/downloadFile.do?file=1528269849853/Java_manual.pdf

    本文会记录一些从中摘取的内容。

    一、编程规约

    1.1 命名风格

    1、【强制】常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。 
    正例:MAX_STOCK_COUNT
    反例:MAX_COUNT

    2、【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类 命名以它要测试的类的名称开始,以 Test 结尾。

    3、【强制】类型与中括号紧挨相连来表示数组。 
    正例:定义整形数组 int[] arrayDemo;
    反例:在 main 参数中,使用 String args[]来定义。

    4、【强制】POJO 类中布尔类型的变量,都不要加 is 前缀,否则部分框架解析会引起序列化错误。 反例:定义为基本数据类型Boolean isDeleted的属性,它的方法也是isDeleted(),RPC
    框架在反向解析的时候,“误以为”对应的属性名称是 deleted,导致属性获取不到,进而抛
    出异常。

    5、【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用 单数形式,但是类名如果有复数含义,类名可以使用复数形式。
    正例:应用工具类包名为 com.alibaba.ai.util、类名为 MessageUtils(此规则参考 spring 的框架结构)

    6、【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁 性,并加上有效的 Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是 与接口方法相关,并且是整个应用的基础常量。
    正例:接口方法签名void commit();
    接口基础常量String COMPANY = "alibaba";
    反例:接口方法定义public abstract void f();
    说明:JDK8 中接口允许有默认实现,那么这个 default 方法,是对所有实现类都有价值的默 认实现。

    7、【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。
    说明:枚举其实就是特殊的类,域成员均为常量,且构造方法被默认强制是私有。 正例:枚举名字为ProcessStatusEnum的成员名称:SUCCESS / UNKNOWN_REASON。

    8、【参考】各层命名规约:
    A) Service/DAO层方法命名规约
    1) 获取单个对象的方法用get做前缀。
    2) 获取多个对象的方法用list做前缀,复数形式结尾如:listObjects。 3) 获取统计值的方法用count做前缀。
    4) 插入的方法用save/insert做前缀。
    5) 删除的方法用remove/delete做前缀。
    6) 修改的方法用update做前缀。
    B) 领域模型命名规约
    1) 数据对象:xxxDO,xxx即为数据表名。
    2) 数据传输对象:xxxDTO,xxx为业务领域相关的名称。 3) 展示对象:xxxVO,xxx一般为网页名称。
    4) POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。

    1.2 常量定义

    1、【强制】在 long 或者 Long 赋值时,数值后使用大写的 L,不能是小写的 l,小写容易跟数字 1 混淆,造成误解。
    说明:Long a = 2l; 写的是数字的21,还是Long型的2?

    1.3 代码格式

    1、【强制】单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则: 1) 第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
    2) 运算符与下文一起换行。
    3) 方法调用的点符号与下文一起换行。
    4) 方法调用中的多个参数需要换行时,在逗号后进行。 
    5) 在括号前不要换行,见反例。
    正例:

    反例:

    2、【推荐】不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。 说明:任何情形,没有必要插入多个空行进行隔开。

    3、【强制】采用 4 个空格缩进,禁止使用 tab 字符。
    说明:如果使用 tab 缩进,必须设置 1 个 tab 为 4 个空格。IDEA 设置 tab 为 4 个空格时, 请勿勾选Use tab character;而在 eclipse 中,必须勾选insert spaces for tabs

    正例:


    1.4 OOP规约

    1、【强制】外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生 影响。接口过时必须加@Deprecated 注解,并清晰地说明采用的新接口或者新服务是什么。

    2、【强制】POJO 类必须写 toString 方法。使用 IDE 中的工具:source> generate toString 时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。 
    说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。

    3、【推荐】 类内方法定义的顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter 方法。
    说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类 关心,也可能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个 黑盒实现;因为承载的信息价值较低,所有 Service 和 DAO 的 getter/setter 方法放在类体 最后。

    4、【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。 说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象, 然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。 反例:
    String str = "start";
    for (int i = 0; i < 100; i++) {
    str = str + "hello"; }

    5、【推荐】final 可以声明类、成员变量、方法、以及本地变量,下列情况使用 final 关键字: 1) 不允许被继承的类,如:String 类。
    2) 不允许修改引用的域对象。
    3) 不允许被重写的方法,如:POJO 类的 setter 方法。
    4) 不允许运行过程中重新赋值的局部变量。
    5) 避免上下文重复使用一个变量,使用 final 描述可以强制重新定义一个变量,方便更好 地进行重构。

    1.5 集合处理

    1、【强制】ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException 异常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList。 说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList 而是 ArrayList 的一个视图,对于 SubList 子列表的所有操作最终会反映到原列表上。

    2、【强制】使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全
    一样的数组,大小就是 list.size()。
    说明:使用 toArray 带参方法,入参分配的数组空间不够大时,toArray 方法内部将重新分配
    内存空间,并返回新数组地址;如果数组元素个数大于实际所需,下标为[ list.size() ]
    的数组元素将被置为 null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集
    合元素个数一致。
    正例:
    List<String> list = new ArrayList<String>(2); list.add("guan");
    list.add("bao");
    String[] array = new String[list.size()]; array = list.toArray(array);


    3、【强制】使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方 法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。 说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList 体现的是适配器模式,只是转换接口,后台的数据仍是数组。
           String[] str = new String[] { "you", "wu" };
    List list = Arrays.asList(str); 第一种情况:list.add("yangguanbao"); 运行时异常。 第二种情况:str[0] = "gujin"; 那么list.get(0)也会随之修改。

    4、【强制】 在 JDK7 版本及以上,Comparator 实现类要满足如下三个条件,不然 Arrays.sort, Collections.sort 会报 IllegalArgumentException 异常。
    说明:三个条件如下
    1) x,y的比较结果和y,x的比较结果相反。
    2) x>y,y>z,则x>z。
    3) x=y,则x,z比较结果和y,z比较结果相同。
     反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
    new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
    return o1.getId() > o2.getId() ? 1 : -1; }
    };

    5、【参考】利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的 contains 方法进行遍历、对比、去重操作。

     

    二、异常

    1、【推荐】防止 NPE,是程序员的基本修养,注意 NPE 产生的场景: 1)返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
    反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。
    2) 数据库的查询结果可能为null。
    3) 集合里的元素即使isNotEmpty,取出的数据元素也可能为null。
    4) 远程调用返回对象时,一律要求进行空指针判断,防止NPE。
    5) 对于Session中获取的数据,建议NPE检查,避免空指针。
    6) 级联调用obj.getA().getB().getC();一连串调用,易产生NPE。
    正例:使用 JDK8 的 Optional 类来防止 NPE 问题。

     

    三、MYSQL数据库

    这也是我来寻找这篇规范的最初目的...

    3.1 建表规约

    1. 【强制】表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint (1 表示是,0 表示否)。
    说明:任何字段如果为非负数,必须是 unsigned。
    注意:POJO 类中的任何布尔类型的变量,都不要加 is 前缀,所以,需要在<resultMap>设置 从 is_xxx 到 Xxx 的映射关系。数据库表示是与否的值,使用 tinyint 类型,坚持 is_xxx 的 命名方式是为了明确其取值含义与取值范围。
    正例:表达逻辑删除的字段名 is_deleted,1 表示删除,0 表示未删除。


    2. 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、 表名、字段名,都不允许出现任何大写字母,避免节外生枝。 正例:aliyun_admin,rdc_config,level3_name 反例:AliyunAdmin,rdcConfig,level_3_name


    3. 【强制】表名不使用复数名词。 说明:表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数 形式,符合表达习惯。


    4. 【强制】禁用保留字,如 desc、range、match、delayed 等,请参考 MySQL 官方保留字。


    5. 【强制】主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名。
    说明:pk_ 即 primary key;uk_ 即 unique key;idx_ 即 index 的简称。


    6. 【强制】小数类型为 decimal,禁止使用 float 和 double。
    说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数分开存储。


    7. 【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。


    8. 【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长 度大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索 引效率。


    9. 【强制】表必备三字段:id, gmt_create, gmt_modified。 说明:其中id必为主键,类型为bigint unsigned、单表时自增、步长为1。gmt_create, gmt_modified 的类型均为 datetime 类型,前者现在时表示主动创建,后者过去分词表示被 动更新。


    10. 【推荐】表的命名最好是加上“业务名称_表的作用”。
    正例:alipay_task / force_project / trade_config


    11. 【推荐】库名与应用名称尽量一致。


    12. 【推荐】如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。


    13. 【推荐】字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循: 1)不是频繁修改的字段。
    2)不是 varchar 超长字段,更不能是 text 字段。
    正例:商品类目名称使用频率高,字段长度短,名称基本一成不变,可在相关联的表中冗余存 储类目名称,避免关联查询。


    14. 【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。


    15. 【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检 索速度。
    正例:如下表,其中无符号值可以避免误存负数,且扩大了表示范围。

     

    对象

      

    年龄区间

      

    类型

     

    字节

     

    表示范围

     
     

      

    150 岁之内

      

    tinyint unsigned

     

    1

     

    无符号值:0 到 255

     
     

      

    数百岁

      

    smallint unsigned

     

    2

     

    无符号值:0 到 65535

     
     

    恐龙化石

      

    数千万年

      

    int unsigned

     

    4

     

    无符号值:0 到约 42.9 亿

     
     

    太阳

      

    约 50 亿年

      

    bigint unsigned

     

    8

     

    无符号值:0 到约 10 的 19 次方

     

     

    3.2 索引规约

    1. 【强制】业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引。 说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明 显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必 然有脏数据产生。


    2. 【强制】超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时, 保证被关联的字段需要有索引。
    说明:即使双表 join 也要注意表索引、SQL 性能。


    3. 【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度即可。
    说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分
    度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度 来确定。


    4. 【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。 说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索 引。


    5. 【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合 索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。 正例:where a=? and b=? order by c; 索引:a_b_c 反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引 a_b 无法排序。


    6. 【推荐】利用覆盖索引来进行查询操作,避免回表。
    说明:如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览 一下就好,这个目录就是起到覆盖索引的作用。 正例:能够建立索引的种类分为主键索引、唯一索引、普通索引三种,而覆盖索引只是一种查 询的一种效果,用explain的结果,extra列会出现:using index。


    7. 【推荐】利用延迟关联或者子查询优化超多分页场景。
    说明:MySQL 并不是跳过 offset 行,而是取 offset+N 行,然后返回放弃前 offset 行,返回 N 行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过 特定阈值的页数进行 SQL 改写。
    正例:先快速定位需要获取的 id 段,然后再关联:
    SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id


    8. 【推荐】SQL 性能优化的目标:至少要达到 range 级别,要求是 ref 级别,如果可以是 consts 最好。
    说明:
    1)consts 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。 2)ref 指的是使用普通的索引(normal index)。
    3)range 对索引进行范围检索。
    反例:explain 表的结果,type=index,索引物理文件全扫描,速度非常慢,这个 index 级 别比较 range 还低,与全表扫描是小巫见大巫。


    9. 【推荐】建组合索引的时候,区分度最高的在最左边。
    正例:如果 where a=? and b=? ,如果 a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。 说明:存在非等号和等号混合时,在建索引时,请把等号条件的列前置。如:where c>? and d=? 那么即使 c 的区分度更高,也必须把 d 放在索引的最前列,即索引 idx_d_c。


    10. 【推荐】防止因字段类型不同造成的隐式转换,导致索引失效。


    11. 【参考】创建索引时避免有如下极端误解: 1)宁滥勿缺。认为一个查询就需要建一个索引。 2)宁缺勿滥。认为索引会消耗空间、严重拖慢更新和新增速度。 3)抵制惟一索引。认为业务的惟一性一律需要在应用层通过“先查后插”方式解决。

     

    3.3 SQL语句

    1. 【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。 说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。


    2. 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。


    3. 【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为 NULL,因此使用 sum()时需注意 NPE 问题。 正例:可以使用如下方式来避免sum的NPE问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;


    4. 【强制】使用 ISNULL()来判断是否为 NULL 值。 说明:NULL 与任何值的直接比较都为 NULL。
    1) NULL<>NULL的返回结果是NULL,而不是false。 2) NULL=NULL的返回结果是NULL,而不是true。 3) NULL<>1的返回结果是NULL,而不是true。


    5. 【强制】 在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。


    6. 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。 说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为 级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻 塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。


    7. 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。


    8. 【强制】数据订正(特别是删除、修改记录操作)时,要先 select,避免出现误删除,确认无误才能执行更新语句。


    9. 【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控 制在 1000 个之内。


    10. 【参考】如果有国际化需要,所有的字符存储与表示,均以 utf-8 编码,注意字符统计函数
    的区别。
    说明:
    SELECT LENGTH("轻松工作"); 返回为12
    SELECT CHARACTER_LENGTH("轻松工作"); 返回为4 如果需要存储表情,那么选择 utf8mb4 来进行存储,注意它与 utf-8 编码的区别。


    11. 【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE 无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。 说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

    展开全文
  • Java开发规范(一)

    千次阅读 2017-08-20 20:54:57
    本文摘自阿里开发规范,是阿里工程师们严格遵循的开发标准,同时也是培养自己写出高质量代码的必然要求,不让自己写出来的代码像个刚毕业的。 1、命名的风格: 1. 代码中的命名均不能以下划线或美元符号开始,也...

    本文摘自阿里开发规范,是阿里工程师们严格遵循的开发标准,同时也是培养自己写出高质量代码的必然要求,不让自己写出来的代码像个刚毕业的。


    1、命名的风格:


    1. 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。 
    反例: _name $name


    2. 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。
    说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。
    注意,即使纯拼音命名方式也要避免采用。
    正例: alibaba / taobao 等国际通用的名称,可视同英文。 
    反例: DaZhePromotion [打折] 

    3. 类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:DO / BO / DTO / VO / AO 
    正例:MarcoPolo / UserDO 
    反例:macroPolo / UserDo

    4. 方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格,必须遵从驼峰形式。 
    正例: localValue / getHttpMessage() / inputUserId


    5. 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。 
    正例: MAX_STOCK_COUNT 


    6. 抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名以它要测试的类的名称开始,以Test结尾。


    7. 中括号是数组类型的一部分,数组定义如下:String[] args; 
    反例:使用String args[]的方式来定义。


    8. POJO类中布尔类型的变量,都不要加is,否则部分框架解析会引起序列化错误。 
    反例:定义为基本数据类型Boolean isDeleted;的属性,它的方法也是isDeleted(),RPC
    框架在反向解析的时候,“以为”对应的属性名称是deleted,导致属性获取不到,进而抛出异常。


    9. 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。
    包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。 
    正例: 工具类包名为com.alibaba.open.util、类名为MessageUtils


    10. 杜绝完全不规范的缩写,避免望文不知义。 
    反例: AbstractClass“缩写”命名成AbsClass;此类随意缩写严重降低了代码的可阅读性。


    11. 如果使用到了设计模式,建议在类名中体现出具体模式。 说明:将设计模式体现在名字中,有利于阅读者快速理解架构设计思想。
    正例:public class OrderFactory; public class LoginProxy; public class ResourceObserver;


    12. 接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁性,并加上有效的Javadoc注释。
    尽量不要在接口里定义变量,如果一定要定义变量,肯定是与接口方法相关,并且是整个应用的基础常量。 
    正例:接口方法签名:void f(); 接口基础常量表示:String COMPANY = "alibaba"; 
    反例:接口方法定义:public abstract void f(); 说明:JDK8中接口允许有默认实现,那么这个default方法,是对所有实现类都有价值的默认实现。


    13. 接口和实现类的命名有两套规则: 
    1)对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别。 
    正例:CacheServiceImpl实现CacheService接口。 
    2)如果是形容能力的接口名称,取对应的形容词做接口名(通常是–able的形式)。 
    正例:AbstractTranslator实现 Translatable。


    14. 枚举类名建议带上Enum后缀,枚举成员名称需要全大写,单词间用下划线隔开。 说明:枚举其实就是特殊的常量类,且构造方法被默认强制是私有。 
    正例:枚举名字:DealStatusEnum,成员名称:SUCCESS / UNKOWN_REASON。


    15. 各层命名规约: 
    A) Service/DAO层方法命名规约 
    1) 获取单个对象的方法用get做前缀。
    2) 获取多个对象的方法用list做前缀。 
    3) 获取统计值的方法用count做前缀。 
    4) 插入的方法用save(推荐)或insert做前缀。 
    5) 删除的方法用remove(推荐)或delete做前缀。 
    6) 修改的方法用update做前缀。 
    B) 领域模型命名规约 
    1) 数据对象:xxxDO,xxx即为数据表名。 
    2) 数据传输对象:xxxDTO,xxx为业务领域相关的名称。 
    3) 展示对象:xxxVO,xxx一般为网页名称。 
    4) POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。


    2、常量定义


    1. 不允许任何魔法值(即未经定义的常量)直接出现在代码中。 
    反例: String key = "Id#taobao_" + tradeId; cache.put(key, value);


    2. long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。 
    说明:Long a = 2l; 写的是数字的21,还是Long型的2?


    3. 不要使用一个常量类维护所有常量,应该按常量功能进行归类,分开维护。
    如:缓存相关的常量放在类:CacheConsts下;系统配置相关的常量放在类:ConfigConsts下。 
    说明:大而全的常量类,非得使用查找功能才能定位到修改的常量,不利于理解和维护。


    4. 常量的复用层次有五层:跨应用共享常量、应用内共享常量、子工程内共享常量、包内共享常量、类内共享常量。 
    1) 跨应用共享常量:放置在二方库中,通常是client.jar中的constant目录下。 
    2) 应用内共享常量:放置在一方库的modules中的constant目录下。 
    反例:易懂变量也要统一定义成应用内共享常量,两位攻城师在两个类中分别定义了表示“是”的变量: 类A中:public static final String YES = "yes"; 类B中:public static final String YES = "y"; A.YES.equals(B.YES),预期是true,但实际返回为false,导致线上问题。
    3) 子工程内部共享常量:即在当前子工程的constant目录下。 
    4) 包内共享常量:即在当前包下单独的constant目录下。 
    5) 类内共享常量:直接在类内部private static final定义。


    5. 如果变量值仅在一个范围内变化,且带有名称之外的延伸属性,定义为枚举类。下面正例中的数字就是延伸信息,表示星期几。 
    正例:public Enum { MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}


    3、代码格式


    1. 大括号的使用约定。如果是大括号内为空,则简洁地写成{}即可,不需要换行;
    如果是非空代码块则: 
    1) 左大括号前不换行。 
    2) 左大括号后换行。 
    3) 右大括号前换行。 
    4) 右大括号后还有else等代码则不换行;表示终止的右大括号后必须换行。


    public static void main(String[] args) {
    {
    {

    }
    }
    }

    2. 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格。
    反例:if (空格a == b空格)
    if (1 == 2) {


    }
    3. if/for/while/switch/do等保留字与括号之间都必须加空格。


    4. 任何二目、三目运算符的左右两边都需要加一个空格。 
    说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号等。


    5. 缩进采用4个空格,禁止使用tab字符。
    说明: 如果使用 tab 缩进,必须设置 缩进,必须设置 缩进,必须设置 缩进,必须设置 缩进,必须设置 缩进,必须设置 1个 tab 为 4个空格。 
    IDEA 设置 tab 为 4个空格时, 请勿勾选 Use tab character ;而在 eclipse 中,必须勾选 insert spaces for tabs 。
    正例: (涉及1-5点)
    public static void main(String[] args) {
    // 缩进4个空格
    String say = "hello";
    // 运算符的左右必须有一个空格
    int flag = 0;
    // 关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格
    if (flag == 0) {
    System.out.println(say);
    }
    // 左大括号前加空格且不换行;左大括号后换行
    if (flag == 1) {
    System.out.println("world");
    // 右大括号前换行,右大括号后有else,不用换行
    } else {
    System.out.println("ok");


    // 在右大括号后直接结束,则必须换行
    }
    }


    6. 单行字符个数限制不超过 120 个,超出需要换行时,超出需要换行时 
    换行时遵循如下原则: 
    1) 第二行相对一缩进 4个空格,从第三行开始不再继续缩进参考示例。 
    2) 运算符与下文一起换行。 
    3) 方法调用的点符号与下文一起换行。 
    4) 在多个参数超长,在逗号后换行。 
    5) 在括号前不要换行,见反例。 
    正例:
    StringBuffer sb = new StringBuffer();
    //超过120个字符的情况下,换行缩进4个空格,并且方法前的点符号一起换行
    sb.append("zi").append("xin")...
    .append("huang")...
    .append("huang")...
    .append("huang");
    反例:
    StringBuffer sb = new StringBuffer();
    //超过120个字符的情况下,不要在括号前换行
    sb.append("zi").append("xin")...append
    ("huang");
    //参数很多的方法调用可能超过120个字符,不要在逗号前换行
    method(args1, args2, args3, ...
    , argsX);


    7. 方法参数在定义和传入时,多个参数逗号后边必须加空格。 
    正例:下例中实参的"a",后边必须要有一个空格。
    method("a", "b", "c");


    8. IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用windows格式。


    9. 没有必要增加若干空格来使某一行的字符与上一行对应位置的字符对齐。 
    正例:
    int a = 3;
    long b = 4L;
    float c = 5F;
    StringBuffer sb = new StringBuffer();
    说明:增加sb这个变量,如果需要对齐,则给a、b、c都要增加几个空格,在变量比较多的情况下,是一种累赘的事情。


    10. 方法体内的执行语句组、变量的定义语句组、不同的业务逻辑之间或者不同的语义之间插入一个空行。
    相同业务逻辑和语义之间不需要插入空行。 说明:没有必要插入多个空行进行隔开。


    4、OOP规约(面向对象编程)


    1. 避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
    直接用类名访问类的静态变量和静态方法,不要用类的对象引用访问。


    2. 所有的覆写方法,必须加@Override注解。 
    说明:getObject()与get0bject()的问题。一个是字母的O,一个是数字的0,加@Override可以准确判断是否覆盖成功。
    另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。


    3. 相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。 
    说明:可变参数必须放置在参数列表的最后。(提倡同学们尽量不用可变参数编程) 
    正例:public User getUsers(String type, Integer... ids) {...}


    4. 外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。
    接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。


    5. 不能使用过时的类或方法。 
    说明:java.net.URLDecoder 中的方法decode(String encodeStr) 这个方法已经过时,应该使用双参数decode(String source, String encode)。
    接口提供方既然明确是过时接口,那么有义务同时提供新的接口;作为调用方来说,有义务去考证过时方法的新实现是什么。


    6. Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。 
    正例: "test".equals(object); 反例: object.equals("test"); 
    说明:推荐使用java.util.Objects#equals (JDK7引入的工具类)


    7. 所有的相同类型的包装类对象之间值的比较,全部使用equals方法比较。 
    说明:对于Integer var = ? 在-128至127范围内的赋值,Integer对象是在IntegerCache.cache产生,
    会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,
    都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。


    8. 关于基本数据类型与包装数据类型的使用标准如下: 
    1) 所有的POJO类属性必须使用包装数据类型。 
    2) RPC方法的返回值和参数必须使用包装数据类型。 
    3) 所有的局部变量使用基本数据类型。 
    说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。 
    正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。
    反例:
    比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示:0%,这是不合理的,应该显示成中划线-。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。


    9. 定义DO/DTO/VO等POJO类时,不要设定任何属性默认值。 
    反例:POJO类的gmtCreate默认值为new Date();
    但是这个属性在数据提取时并没有置入具体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。


    10. 序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败;
    如果完全不兼容升级,避免反序列化混乱,那么请修改serialVersionUID值。 
    说明:注意serialVersionUID不一致会抛出序列化运行时异常。


    11. 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。


    12. POJO类必须写toString方法。使用IDE的中工具:source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。 
    说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。


    13. 使用索引访问用String的split方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。
    说明:
    String str = "a,b,c,,";
    String[] ary = str.split(",");
    //预期大于3,结果是3
    System.out.println(ary.length);


    14. 当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读。


    15.  类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法。 
    说明:公有方法是类的调用者和维护者最关心的方法,首先展示最好;
    保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法;
    而私有方法外部一般不需要特别关心,是一个黑盒实现;因为方法信息价值较低,所有Service和DAO的getter/setter方法放在类体最后。


    16. setter方法中,参数名称与类成员变量名称一致,this.成员名 = 参数名。
    在getter/setter方法中,不要增加业务逻辑,增加排查问题的难度。 
    反例:
    public Integer getData() {
    if (true) {
    return this.data + 100;
    } else {
    return this.data - 100;
    }
    }

    17. 循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。 
    说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
    反例:
    public static void main(String[] args) {
    String str = "start";
    for (int i = 0; i < 100; i++) {
    str = str + "hello";
    }
    }


    18. final可以声明类、成员变量、方法、以及本地变量,
    下列情况使用final关键字: 
    1) 不允许被继承的类,如:String类。 
    2) 不允许修改引用的域对象,如:POJO类的域变量。 
    3) 不允许被重写的方法,如:POJO类的setter方法。 
    4) 不允许运行过程中重新赋值的局部变量。 
    5) 避免上下文重复使用一个变量,使用final描述可以强制重新定义一个变量,方便更好地进行重构。


    19. 慎用Object的clone方法来拷贝对象。 
    说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现属性对象的拷贝。


    20. 类成员与方法访问控制从严: 
    1) 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。 
    2) 工具类不允许有public或default构造方法。 
    3) 类非static成员变量并且与子类共享,必须是protected。 
    4) 类非static成员变量并且仅在本类使用,必须是private。 
    5) 类static成员变量如果仅在本类使用,必须是private。 
    6) 若是static成员变量,必须考虑是否为final。 
    7) 类成员方法只供类内部调用,必须是private。 
    8) 类成员方法只对继承类公开,那么限制为protected。 
    说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。
    思考:如果是一个private的方法,想删除就删除,可是一个public的service方法,或者一个public的成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,如果无限制的到处跑,那么你会担心的。


    5、集合处理


    1. 关于hashCode和equals的处理,遵循如下规则: 
    1) 只要重写equals,就必须重写hashCode。 
    2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。 
    3) 如果自定义对象做为Map的键,那么必须重写hashCode和equals。 
    说明:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。


    2.  ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList ; 
    说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。


    3.  在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException 异常。


    4. 使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()。
    说明:使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;
    如果数组元素大于实际所需,下标为[ list.size() ]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。 
    正例:
    public static void main(String[] args) {
    List<String> list = new ArrayList<String>(2);
    list.add("guan");
    list.add("bao");
    String[] array = new String[list.size()];
    array = list.toArray(array);
    }
    反例:
    直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。


    5. 使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。 
    说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。 
    public static void main(String[] args) {
    List<String> list = new ArrayList<String>(2);
    list.add("guan");
    list.add("bao");
    String[] array = new String[list.size()];
    array = list.toArray(array);

    List list1 = Arrays.asList(array);
    }
    第一种情况:list.add("c"); 运行时异常。 
    第二种情况:str[0] = "gujin"; 那么list.get(0)也会随之修改。


    6. 泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用add方法,而<? super T>不能使用get方法,做为接口调用赋值时易出错。 
    说明:扩展说一下PECS(Producer Extends Consumer Super)原则:
    1)频繁往外读取内容的,适合用上界Extends。
    2)经常往里插入的,适合用下界Super。


    7. 不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
    正例:
    Iterator<String> it = a.iterator();
    while (it.hasNext()) {
    String temp = it.next();
    if (删除元素的条件) {
    it.remove();
    }
    }
    反例:
    List<String> a = new ArrayList<String>();
    a.add("1");
    a.add("2");
    for (String temp : a) {
    if ("1".equals(temp)) {
    a.remove(temp);
    }
    }
    说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗?
    java.util.ConcurrentModificationException



    8.  在JDK7版本及以上,Comparator要满足如下三个条件,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常。 
    说明: 
    1) x,y的比较结果和y,x的比较结果相反。 
    2) x>y,y>z,则x>z。 
    3) x=y,则x,z比较结果和y,z比较结果相同。 
    反例:
    下例中没有处理相等的情况,实际使用中可能会出现异常:
    new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
    return o1.getId() > o2.getId() ? 1 : -1;
    }
    };


    9. 集合初始化时,指定集合初始值大小。 
    说明:HashMap使用HashMap(int initialCapacity) 初始化, 
    正例:
    initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意 负载因子(即loader factor)默认 为 0.75,如果 暂时 无法确定 初始 值大小,请设置 为 16。 
    反例: 
    HashMap需要 放置 1024个元素 ,由于 没有设置容量 初始大小,随着元素不断增加容 量 7次被迫扩大, resize需要重建 hash表,严重影响性能。 表,严重影响性能。


    10. 使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。 
    说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。如果是JDK8,使用Map.foreach方法。 
    正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的是K值集合,是一个Set集合对象;entrySet()返回的是K-V值组合集合。


    11. 合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和不稳定性(unorder)带来的负面影响。 
    说明:有序性是指遍历的结果是按某种比较规则依次排列的。稳定性指集合每次遍历的元素次序是一定的。
    如:ArrayList是order/unsort;HashMap是unorder/unsort;TreeSet是order/sort。


    12. 利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。


    展开全文
  • 开发规范是所有程序员开发过程中必须掌握的技能,早期的软件开发过程可能不重视开发规范导致后期维护成本极高,现在国内的大厂都会制定自己的开发规范,完善的开发规范不仅可以提高团队效率,还可以避免很多意外的...

    开发规范是所有程序员开发过程中必须掌握的技能,早期的软件开发过程可能不重视开发规范导致后期维护成本极高,现在国内的大厂都会制定自己的开发规范,完善的开发规范不仅可以提高团队效率,还可以避免很多意外的bug问题。下面我找了几篇关于代码规范重要性的文章,大家可以参考下。

    1. 为什么谷歌要执行严格的代码编写规范
    2. 为什么要写软件开发规范?软件开发规范书怎么写?
    3. 为什么在程序开发中要注意编码规范?(知乎问答)

    本系列文章将整合 阿里巴巴《Java开发手册》 和  谷歌《Java编程规范》 ,总结Java开发过程的编码规范,并通过具体编码案例给出编码规范的原因,如果总结内容存在问题还望指出。


    Java开发规范之OOP规约篇共上中下三篇,具体内容参考 阿里巴巴《Java开发手册》的目录,同时补充 谷歌《Java编程规范》的内容,阿里巴巴规约内容比较丰富,谷歌规约很多实际内容都没有。

    1. Java开发规范之OOP规约篇(上)
    2. Java开发规范之OOP规约篇(中)
    3. Java开发规范之OOP规约篇(下)

    Java开发规范之OOP规约篇(中)

    9.DO类属性必须匹配数据库字段类型

    10.double值转化为BigDecimal对象禁止直接使用构造方法

    11.基本数据类型与包装数据类型的使用标准

    12.POJO类禁止设定任何属性默认值

    13.序列化类尽量避免修改serialVersionUID字段

    14.构造方法禁止加入任何业务逻辑

    15.POJO类必须写toString方法

    16.POJO类中禁止存在对应属性xxx的isXxx()和getXxx()方法


    本篇文章内容将承接上一篇  《Java开发规范之OOP规约篇(上)》 继续介绍面向对象程序设计中规范,如果OOP (Object Oriented Programming)含义不够了解,请参考上一篇介绍内容。

    9.DO类属性必须匹配数据库字段类型

    Alibaba规约(强制

    定义数据对象DO类时,属性类型要与数据库字段类型相匹配。

    Google规约

    未明确定义类似规范

    说明:DO(Domain Object)领域对象一般是指从现实世界中抽象出来的有形或无形的业务实,常和数据中的表结构对应,如数据库中有一个 Student 学生表,对应程序中需要有一个学生类存储对应数据,可记作 StudentDO。Java实体类的属性类型与数据库表字段类型对应表可以参考这篇文章,点击 链接 跳转查看。

    正例:数据库字段的bigint必须与类属性的Long类型相对应。

    反例::某个案例的数据库表id字段定义类型bigint unsigned,实际类对象属性为Integer,随着id越来越大,超过Integer的表示范围而溢出成为负数。

    10.double值转化为BigDecimal对象禁止直接使用构造方法

    Alibaba规约(强制

    为了防止精度损失,禁止使用构造方法BigDecimal(double)的方式把double值转化为BigDecimal对象。

    Google规约

    未明确定义类似规范

    说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。如:BigDecimal g = new BigDecimal(0.1f); 实际的存储值为:0.10000000149

    正例:优先推荐入参为String的构造方法,或使用BigDecimal的valueOf方法,此方法内部其实执行了Double的toString,而Double的toString按double的实际能表达的精度对尾数进行了截断。

    BigDecimal recommend1 = new BigDecimal("0.1"); 
    BigDecimal recommend2 = BigDecimal.valueOf(0.1);

    反例:

    BigDecimal number = new BigDecimal(0.1);
    
    System.out.println("number=" + number);
    // 输出结果  number=0.1000000000000000055511151231257827021181583404541015625

    11.基本数据类型与包装数据类型的使用标准

    Alibaba规约

    关于基本数据类型与包装数据类型的使用标准如下:

    • 强制】所有的POJO类属性必须使用包装数据类型。
    • 强制】RPC方法的返回值和参数必须使用包装数据类型。
    • 推荐】所有的局部变量使用基本数据类型。

    POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何空指针异常问题,或者入库检查,都由使用者来保证。

    Google规约

    未明确定义类似规范

    说明:POJO是Plain OrdinaryJava Object的缩写,可以简单理解为不包含业务逻辑的单纯用来存储数据的 Java类(实际就是普通JavaBean,是为了避免和EJB混淆所创造的简称)。使用POJO名称是为了避免和EJB混淆起来, 而且简称比较直接. 其中有一些属性及其getter setter方法的类,没有业务逻辑,有时可以作为VO(value -object)或DTO(Data Transform Object)来使用。

    正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有空指针异常风险。

    反例:基本数据类型有默认值导致显示异常比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。

    12.POJO类禁止设定任何属性默认值

    Alibaba规约(强制

    定义DO/DTO/VO等POJO类时,不要设定任何属性默认值

    Google规约

    未明确定义类似规范

    说明:VO(View Object,视图对象)一般作用于前台页面与表示层之间,将所有的数据封装到一起,比如表单数据,这些参数并不一定完全与数据库中表的所有字段均匹配。DTO(Data Transfer Object,数据传输对象)作用于表示层与业务层之间,Action/Controller将接收到的VO对象进行业务逻辑处理,转化或者构造成DTO对象将其传递给service层。DO(Domain Object,领域对象)作用于业务层与dao层之间,service层使用接收到的DTO数据传输对象构造或者重构DO对象,传递到DAO层。DAO(data access object,数据访问对象),负责数据库的操作并为service层提供接口。

    反例:POJO类的createTime默认值为new Date(),但是这个属性在数据提取时并没有置入具体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。

    13.序列化类尽量避免修改serialVersionUID字段

    Alibaba规约(强制

    序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改serialVersionUID值。

    Google规约

    未明确定义类似规范

    说明:serialVersionUID 用来表明类的不同版本间的兼容性,serialVersionUID不一致会抛出序列化运行时异常。

    补充: Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。当实现java.io.Serializable接口的实体(类)没有显式地定义一个名为serialVersionUID,类型为long的变量时,Java序列化机制会根据编译的class自动生成一个serialVersionUID作序列化版本比较用,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID 。

    14.构造方法禁止加入任何业务逻辑

    Alibaba规约(强制

    构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在init方法中。

    Google规约

    未明确定义类似规范

    说明:构造方法一般是类的初始化方法,如果加入业务逻辑代码将非常影响可读性,如果有必须的初始化操作方法可以创建init方法进行操作。

    15.POJO类必须写toString方法

    Alibaba规约(强制

    POJO类必须写toString方法。使用IDE中的工具:source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。

    Google规约

    未明确定义类似规范

    说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。使用lombok框架可以自动生成该方法,但有部分人认为该框架存在隐患。

     

    16.POJO类中禁止存在对应属性xxx的isXxx()和getXxx()方法

    Alibaba规约(强制

    禁止在POJO类中,同时存在对应属性xxx的isXxx()和getXxx()方法。

    Google规约

    未明确定义类似规范

    说明:框架在调用属性xxx的提取方法时,并不能确定哪个方法一定是被优先调用到。Mybatis 和 Hibernate 框架是根据获取方法找到对应属性,因此上述定义可能存在问题。

     

    展开全文
  • Java开发规范

    千次阅读 2004-07-18 15:52:00
    这是偶整理的一份开发规范文档,和各位共享,本文档还在完善中,所以如果有任何bug:)或意见、建议等请联系我,以便修改和更新 tks download:...

    这是偶整理的一份开发规范文档,和各位共享,
    本文档还在完善中,所以如果有任何bug:)或意见、建议等
    请联系我,以便修改和更新

    tks

     

     

     

    download:
    http://www.skyinn.org/downloads/JavaDevSpec.pdf

    wiki:
    http://www.skyinn.org/wiki/Wiki.jsp?page=JavaDevSpec


    -------------------------------------------------------
    目录:
    -------------------------------------------------------


    第1章 绪论 5
    1.1 目的 5
    1.2 范围 5
    1.3 版权声明 5
    1.4 参考资料 5
    1.5 概述 5
    第2章 代码组织与风格 7
    2.1 基本原则 7
    2.2 缩进 7
    2.3 长度 7
    2.4 行宽 7
    2.5 间隔 7
    2.6 对齐 7
    2.7 括号 8
    第3章 注释 9
    3.1 基本原则 9
    3.2 JAVADOC 9
    3.3 文件与包注释 9
    3.4 类、接口注释 10
    3.5 方法注释 10
    3.6 其他注释 11
    3.7 注释参考表 11
    第4章 命名 13
    4.1 基本原则 13
    4.2 文件、包 13
    4.3 类、接口 13
    4.4 字段 14
    4.5 方法 14
    4.6 异常 15
    4.7 命名约定表 15
    第5章 声明 17
    5.1 基本原则 17
    5.2 包 17
    5.3 类、接口 17
    5.4 方法 17
    5.5 字段 18
    5.6 示例 18
    第6章 类与接口 20
    6.1 基本原则 20
    6.2 抽象类与接口 20
    6.3 继承与组合 20
    6.4 构造函数和静态工厂方法 20
    6.5 TOSTRING(),EQUALS(),HASHCODE()... 20
    6.6 SINGLETON CLASS 22
    第7章 方法 23
    7.1 基本原则 23
    7.2 参数和返回值 23
    第8章 表达式与语句 24
    8.1 基本原则 24
    8.2 控制语句 24
    8.3 循环语句 25
    第9章 错误与异常 26
    9.1 基本原则 26
    9.2 已检查异常与运行时异常 26
    9.3 异常的捕捉与处理 26
    第10章 测试与BUG跟踪 27
    10.1 基本原则 27
    10.2 测试驱动开发 27
    10.3 JUNIT单元测试 27
    10.4 自动测试与持续集成 27
    10.5 BUG跟踪和缺陷处理 27
    第11章 性能与安全 28
    11.1 基本原则 28
    11.2 STRING与STRINGBUGFFER 28
    11.3 集合 28
    11.4 对象 28
    11.5 同步 28
    11.6 FINAL 28
    11.7 垃圾收集和资源释放 29
    第12章 其他 30
    12.1 目录结构 30
    12.2 CVS注释与标记 31
    12.3 31
    第13章 附录 32
    13.1 CVS标识符 32
    13.2 注释模板 32
    13.3 常用缩写简表 33
    13.4 版权声明模板 33
    13.5 示例代码 34

    展开全文
  • 阿里巴巴Java开发规范手册

    千次阅读 2017-02-19 17:05:04
    阿里巴巴 JAVA 开发手册   1 / 32    Java 开发手册  版本号 制定团队 更新日期 备 注  1.0.0 阿里巴巴集团技术部 2016.12.7 首次向 Java 业界公开   一、编程规约  (一) 命名规约  1. 【强制】...
  • 【强制】杜绝完全不规范的缩写,避免望文不知义。 反例:< 某业务代码>AbstractClass“缩写”命名成AbsClass;condition“缩写”命名成 condi,此类随意缩写严重降低了代码的可阅读性。 11. 【推荐】如果使用到了...
  • 3.【强制】杜绝完全不规范的缩写,避免望文不知义。 反例:AbstractClass“缩写”命名成AbsClass;condition“缩写”命名成 condi,此类随意缩写严重降低了代码的可阅读性。 4.【推荐】如果模块、接口、类、方法...
  • 28个Java开发常用规范技巧总结

    千次阅读 多人点赞 2019-07-04 18:05:00
    常用的规范技巧总结(参考自:华山版《Java开发手册》) 1、类的命名使用驼峰式命名的规范。 例如:UserService,但是以下情景例外:DO / BO / PO / DTO / VO。 例如说:UserPO,StudentPO(PO,VO,DTO,等这类...
  • java开发的代码规范

    千次阅读 2017-03-22 09:26:25
    java开发代码规范及部分注意事项
  • 使用String的方式,Double的toString方法会按照double的实际表达精度对尾数进行了截断。 BigDecimal recommend1 = new BigDecimal("0.1"); BigDecimal recommend2 = new BigDecimal.valueOf(0.1);
  • 1. Service / DAO 层方法命名规约 ...Plain Ordinary Java Object ...POJO 类必须写 toString 方法。如果继承了另一个 POJO 类,注意...软件开发过程中遇到的各种名词解释 GitHub地址: alibaba/p3c - GitHub
  • Java项目开发规范

    千次阅读 2012-03-13 02:01:22
    一、目的   对于代码,首要要求是它必须正确,能够按照程序员的真实思想去运行;第二个的要求是代码必须清晰易懂,使别的程序员能够容易理解代码所进行的实际工作。在软件工程领域,源程序...通过建立代码编写规范
  • 使用IDE中的工具:source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。 说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。 ...
  • 书写不规范测试代码。 13. 【推荐】在设计评审阶段,开发人员需要和测试人员一起确定单元测试范围,单元测试最好 覆盖所有测试用例。 14. 【推荐】单元测试作为一种质量保障手段,不建议项目发布后补充单元测试...
  • Java编程规范

    万次阅读 多人点赞 2017-12-18 22:13:22
    Java编程规范
  • 阿里巴巴Java开发手册快速学习

    万次阅读 2017-04-14 09:04:38
    一份好的开发规范就可以起到这样的作用,大大减少产品上线后的问题。《阿里巴巴Java开发手册》是阿里巴巴的内部编码规范,阿里官方的Java代码规范标准,这份开发手册不仅规范了一些开发细节,也提出了很多工程开发的...
  • Java代码规范

    千次阅读 2021-10-11 18:10:50
    反例: <select id="selectxxx" parameterType="com.entity.xxxx" resultType="java.lang.Integer"> select count(*) from xxxxx t where 1=1 !=null and sex !='' "> AND sex= #{sex} </if> !=null and name!='' ">...
  • Java命名规范

    千次阅读 2017-04-20 15:43:40
    最近,阿里巴巴发布了《阿里巴巴Java开发手册》,总结了阿里人多年一线实战中积累的研发流程规范,这些流程规范在一定程度上能够保证最终的项目交付质量,通过限制开发人员的编程风格、实现方式来避免研发人员在实践...
  • Java编码规范

    千次阅读 多人点赞 2014-03-13 18:05:16
    先借编码规范之名,行吐槽之实,抱歉。 写干净整洁的代码 阅读代码,眼缘很重要。...鉴于Java开发库以及流行的开源框架都用Block起始大括号不换行风格,Google也如此规范,统一为这种风格。去除没有用到的类引用 纯粹是
  • Java 开发的日志建议规范

    千次阅读 2017-06-22 23:42:05
    如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象, 会执行 toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。 正例:(条件) if (logger....
  • Google Java代码规范

    千次阅读 2018-03-09 16:09:59
    原文地址:https://google.github.io/styleguide/javaguide.htmlGIthub上GoogleCode风格的配置文件(支持Eclipse IDE和IntelliJ IDE):https://github.com/codeset/google-java-styleguide1简介本文档作为Java编程...
  • Java开发环境系列分享链接:https://pan.baidu.com/s/1jIB_5E-1g3_XrMSloF88YA 提取码:8xa5 Windows10专业版 点击下载盘云装机助手 激活: # “以管理员身份”运行cmd # "已成功卸载了产品密钥” slmgr.vbs /upk...
  • 阿里巴巴Java代码规范

    千次阅读 2019-03-14 16:25:05
    阿里巴巴Java代码规范1.及时清理不再使用的代码段或配置信息。2.不要在foreach循环里进行元素的remove/add操作,remove元素请使用Iterator方式。3. POJO类中的任何布尔类型的变量,都不要加is,否则部分框架解析会...
  • 阿里开发规范(精简版)

    万次阅读 多人点赞 2018-03-14 10:28:56
    Java开发规范 命名 【规范】类名使用UpperCamelCase 风格,必须遵从驼峰形式,但以下情形例外: ( 领域模型的相关命名 )DO / BO / DTO / VO 等。 正例: MarcoPolo / UserDO / XmlService / TcpUdpDeal / ...
  • 你知道该如何正确重写toString方法吗?阅读本文你将知道正确地写一个toString方法的原理和了解现已有的开源工具去生成正确的toString方法。
  • Java命名规范

    2008-12-13 10:34:00
    Java命名规范 任何一门语言都是用来交流的,都有自己的一套书写规范Java 也不例外。好的命名规范可以让你的程序更专业,更容易被别人理解,更好维护。了解命名规范,可以更好的学习和记忆 Java 类库中类和函数。...
  • JAVA命名规范

    千次阅读 2009-03-13 18:07:00
    今天再论坛看到了有人问JAVA命名规范,我觉得这个问题的确需要注重一下因为对于一个程序来说 程序的格式是非常重要,名字起成什么样可以看出这个人的编程能力,如果一个人的程序写的非常的乱,名字没一点规范的话会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 49,427
精华内容 19,770
关键字:

java开发规范tostring

java 订阅