所有命名不得以下划线和$开始和结束。
所有命名不得以拼音或拼音英文混合。
类名使用UpperCamelCase风格。
方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase风格。
常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;
测试类命名以它要测试的类的名称开始,以 Test 结尾。
类型与中括号紧挨相连来表示数组。(定义整形数组 int[] arrayDemo。)
包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用
单数形式,但是类名如果有复数含义,类名可以使用复数形式。
杜绝完全不规范的缩写,避免望文不知义。(AbstractClass“缩写”成 AbsClass;condition“缩写”成 condi;Function 缩写”成 Fu)
在常量与变量的命名时,表示类型的名词放在词尾,以提升辨识度。(动+名词)
Service/DAO 层方法命名规约
1) 获取单个对象的方法用 get 做前缀。
2) 获取多个对象的方法用 list 做前缀,复数结尾,如:listObjects。
3) 获取统计值的方法用 count 做前缀。
4) 插入的方法用 save/insert 做前缀。推荐save。
5) 删除的方法用 remove/delete 做前缀。推荐remove。
6) 修改的方法用 update 做前缀。
大括号,单行放一起 { },多行:
1) 左大括号前不换行。
2) 左大括号后换行。
3) 右大括号前换行。
4) 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。
if/for/while/switch/do 等保留字与括号之间都必须加空格。
任何二目、三目运算符的左右两边都需要加一个空格。包括赋值运算符=、逻辑运算符&&、加减乘除符号等。
采用 4 个空格缩进。
注释的双斜线与注释内容之间有且仅有一个空格。
单行字符数限制不超过 120 个,超出需要换行,换行时遵循如下原则:
1)第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进,参考示例。
2)运算符与下文一起换行。
3)方法调用的点符号与下文一起换行。
4)方法调用中的多个参数需要换行时,在逗号后进行。
5)在括号前不要换行。
方法参数在定义和传入时,多个参数逗号后面必须加空格。
下例中实参的 args1,后边必须要有一个空格。
method(args1, args2, args3);
IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要
使用 Windows 格式。
不同逻辑、不同语义、不同业务的代码之间插入一个空行分隔开来以提升可读性。
Object 的 equals 方法容易抛空指针异常,应使用常量或确定有值的对象来调用 equals 。
正例:"test".equals(object);
反例:Object.equals("test");
说明:推荐使用 JDK7 引入的工具类 java.util.Objects#equals(Object a, Object b)
所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
任何货币金额,均以最小货币单位且整型类型来进行存储。
浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals来判断。

如上所示 BigDecimal 的等值比较应使用 compareTo()方法,而不是 equals()方法。
equals()方法会比较值和精度 (1.0 与 1.00 返回结果为 false) ,而 compareTo()则会忽略精度。
定义数据对象 DO 类时,属性类型要与数据库字段类型相匹配。
禁止使用构造方法 BigDecimal(double) 的方式把 double 值转化为 BigDecimal 对象。
说明:BigDecimal(double)存在精度损失风险,在精确计算或值比较的场景中可能会导致业务逻辑异常。
如:BigDecimal g = new BigDecimal(0.1F); 实际的存储值为:0.10000000149
正例:优先推荐入参为 String 的构造方法,或使用 BigDecimal 的 valueOf 方法,此方法内部其实执行了
Double 的 toString,而 Double 的 toString 按 double 的实际能表达的精度对尾数进行了截断。
BigDecimal recommend1 = new BigDecimal("0.1"); // String
BigDecimal recommend2 = BigDecimal.valueOf(0.1); // valueOf(double)
关于基本数据类型与包装数据类型的使用标准如下:
1) 【强制】所有的 POJO 类属性必须使用包装数据类型。
2) 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
3) 【推荐】所有的局部变量使用基本数据类型。
说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何 NPE (NullPointerException,空指针异常)问题,或者入库检查,都由使用者来保证。
正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
反例:某业务的交易报表上显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC(Remote Procedure Call) 服务,调用不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线-。所以包装数据类型
的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。
package java_wrapper;
public class Cat {
String name;
int month;
double weight;
}
package java_wrapper;
public class CatTest {
public static void main(String[] args) {
Cat one = new Cat();
System.out.println("小猫的昵称:"+one.name);
System.out.println("小猫的年龄:"+one.month);
System.out.println("小猫的体重:"+one.weight);
}
}
小猫的昵称:null
小猫的年龄:0
小猫的体重:0.0
package java_wrapper;
public class Cat {
String name;
Integer month;
Integer weight;
}
小猫的昵称:null
小猫的年龄:null
小猫的体重:null
| 基本类型 | 包装器类型 |
|---|---|
| boolean | Boolean |
| char | Character |
| int | Integer |
| byte | Byte |
| short | Short |
| long | Long |
| float | Float |
| double | Double |
POJO 类必须写 toString 方法。使用 IDE 中的工具:source> generate toString时,如果继承了另一个 POJO 类,注意在前面加一下 super.toString。
说明:在方法执行抛出异常时,可以直接调用 POJO 的 toString()方法打印其属性值,便于排查问题。
禁止在 POJO 类中,同时存在对应属性 xxx 的 isXxx()和 getXxx()方法。框架在调用属性 xxx 的提取方法时,并不能确定哪个方法一定是被优先调用到的。
类内方法定义的顺序依次是:公有方法或保护方法 > 私有方法 > getter / setter方法。
循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,然后进行 append
操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。
反例:
String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}
public class DemoStringBuilder2 {
public static void main(String[] args) {
StringBuilder bu=new StringBuilder();
//append方法返回的是this,调用方法的对象bu,this==bu
bu.append("abc");
System.out.println(bu); //abc
bu.append("abc");
bu.append("2");
bu.append("true");
bu.append("哈喽");
bu.append("8.8");
bu.append("abc");
System.out.println(bu); //abc2true哈喽8.8abc
//链式编程:方法返回值是一个对象,可以继续调用方法
System.out.println("abc".toUpperCase().toLowerCase().toLowerCase());
bu.append("abc").append(1).append("你好").append(789);
System.out.println(bu);
String myStr = bu.toString(); // 返回String对象
}
}
【强制】日期格式化时,传入 pattern 中表示年份统一使用小写的 y。
说明:日期格式化时,yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year(JDK7 之后
引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,返回的 YYYY
就是下一年。
正例:表示日期和时间的格式如下所示:
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
推荐使用java.util.Date;
import java.util.Date;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
Date currentTime = new Date();
System.out.println(currentTime); // 输出:Mon Feb 18 10:24:30 CST 2019
}
}
使用format()方法将日期转换为字符串
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
Date currentTime = new Date();
System.out.println(currentTime); // Mon Feb 18 13:53:50 CST 2019
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat simpleDateFormat3 = new SimpleDateFormat("yyyy/MM/dd");
System.out.println(simpleDateFormat1.format(currentTime)); // 输出2019-02-18 13:53:50.629
System.out.println(simpleDateFormat2.format(currentTime)); // 输出2019-02-18
System.out.println(simpleDateFormat3.format(currentTime)); // 输出2019/02/18
}
}
使用parse()方法将字符串转换为日期
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String strDate1 = "2019-02-18 13:58";
Date date1 = simpleDateFormat1.parse(strDate1);
System.out.println(date1); // 输出 Mon Feb 18 13:53:50 CST 2019
【强制】在日期格式中分清楚大写的 M 和小写的 m,大写的 H 和小写的 h 分别指代的意义。
1) 表示月份是大写的 M;
2) 表示分钟则是小写的 m;
3) 24 小时制的是大写的 H;
4) 12 小时制的则是小写的 h。
**【强制】获取当前毫秒数:System.currentTimeMillis(); **
【强制】判断所有集合内部的元素是否为空,使用 isEmpty()方法,而不是 size()。
正例:
正例:
Map<String, Object> map = new HashMap<>(16);
if(map.isEmpty()) {
System.out.println("no element in this map.");
}
【强制】当 switch 括号内的变量类型为 String 并且此变量为外部参数时,必须先进行 null判断。switch语句必须包含default。

三目运算符 condition? 表达式 1 : 表达式 2 中,高度注意表达式 1 和 2 在类型对齐时,
可能抛出因自动拆箱导致的 NPE 异常。

【强制】表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint
(1 表示是,0 表示否)。
unsigned是指的无符号,就是没有负数,只能用正数和0,此时unsigned修饰的字段的值可以达到的最大值是原来的最大值加1,即原来一个tinyint字段能表示的范围是:-128 ~ 127,而unsigned修饰的字段范围是 0 ~ 255.
| 数据类型 | 默认范围 | unsigned范围 |
|---|---|---|
| tinyint | -2^7 ~ 2^7-1 | 0 ~ 2^8-1 |
【强制】表名、字段名必须使用小写字母或数字 , 禁止出现数字开头,禁止两个下划线中间只
出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。
说明:MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名、表名、
字段名,都不允许出现任何大写字母,避免节外生枝。
表名不使用复数名词。
禁用保留字,如 desc、range、match、delayed 等。
【强制】主键索引名为 pk_ 字段名;唯一索引名为 uk 字段名 ; 普通索引名则为 idx 字段名。
说明:pk 即 primary key;uk 即 unique key;idx_ 即 index 的简称。
【强制】小数类型为 decimal,禁止使用 float 和 double。
说明:在存储的时候,float 和 double 都存在精度损失的问题,很可能在比较值的时候,得到不正确的
结果。如果存储的数据范围超过 decimal 的范围,建议将数据拆成整数和小数并分开存储。
【强制】如果存储的字符串长度几乎相等,使用 char 定长字符串类型。
【强制】 varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度
大于此值,定义字段类型为 text,独立出来一张表,用主键来对应,避免影响其它字段索引效
率。
【强制】表必备三字段:id, create_time, update_time。
说明:其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。create_time, update_time
的类型均为 datetime 类型,前者现在时表示主动式创建,后者过去分词表示被动式更新。
【推荐】表的命名最好是遵循“业务名称_表的作用”。正例:alipay_task / force_project / trade_config
【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的标
准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。
【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为
NULL,因此使用 sum()时需注意 NPE 问题。
正例:可以使用如下方式来避免 sum 的 NPE 问题:SELECT IFNULL(SUM(column), 0) FROM table;
【强制】使用 ISNULL() 来判断是否为 NULL 值。
【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。SQL 语句中表的别名前加 as。
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun