idea安装阿里巴巴java规范插件的两种方式
https://blog.csdn.net/hg2726028/article/details/78303288
IDEA安装插件提示was not installed: Cannot download解决办法
https://blog.csdn.net/gao_shuang/article/details/79799234
规约错误:
1、long或者Long初始赋值时,必须使用大写的L,不能是小写的l,小写容易跟数字1混淆,造成误解。
Negative example:
//It is hard to tell whether it is number 11 or Long 1.
Long warn = 1l;
Positive example:
Long notwarn = 1L;
2、在if/else/for/while/do语句中必须使用大括号,即使只有一行代码,避免使用下面的形式:if (condition) statements;
if (flag) {
System.out.println("hello world");
}
3、所有的包装类对象之间值的比较,全部使用equals方法比较。 说明:对于Integer var=?在-128至127之间的赋值,Integer对象是在IntegerCache.cache产生,会复用已有对象,这个区间内的Integer值可以直接使用==进行判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,推荐使用equals方法进行判断。
Integer a = 235;
Integer b = 235;
if (a.equals(b)) {
// code
}
4、所有的覆写方法,必须加@Override注解。 反例:getObject()与get0bject()的问题。一个是字母的O,一个是数字的0,加@Override可以准确判断是否覆盖成功。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。
5、线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors各个方法的弊端:
1)newFixedThreadPool和newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM。
2)newCachedThreadPool和newScheduledThreadPool:
主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
Positive example 1:
//org.apache.commons.lang3.concurrent.BasicThreadFactory
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
Positive example 2:
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("demo-pool-%d").build();
//Common Thread Pool
ExecutorService pool = new ThreadPoolExecutor(5, 200,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
pool.execute(()-> System.out.println(Thread.currentThread().getName()));
pool.shutdown();//gracefully shutdown
Positive example 3:
<bean id="userThreadPool"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="queueCapacity" value="2000" />
<property name="threadFactory" value= threadFactory />
<property name="rejectedExecutionHandler">
<ref local="rejectedExecutionHandler" />
</property>
</bean>
//in code
userThreadPool.execute(thread);
6、获取当前毫秒数:System.currentTimeMillis(); 而不是new Date().getTime(); 说明:如果想获取更加精确的纳秒级时间值,用System.nanoTime。在JDK8中,针对统计时间等场景,推荐使用Instant类。
public class TimeMillisDemo {
public static void main(String args[]) {
// Positive example:
long a = System.currentTimeMillis();
// Negative example:
long b = new Date().getTime();
System.out.println(a);
System.out.println(b);
}
}
7、避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
8、Map/Set的key为自定义对象时,必须重写hashCode和equals。 关于hashCode和equals的处理,遵循如下规则:
1) 只要重写equals,就必须重写hashCode。
2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
3) 如果自定义对象做为Map的键,那么必须重写hashCode和equals。
9、Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。
public void f(String str){
String inner = "hi";
if (inner.equals(str)) {
System.out.println("hello world");
}
}
10、不能使用过时的类或方法。 说明:java.net.URLDecoder 中的方法decode(String encodeStr) 这个方法已经过时,应该使用双参数decode(String source, String encode)。接口提供方既然明确是过时接口,那么有义务同时提供新的接口;作为调用方来说,有义务去考证过时方法的新实现是什么。
11、对于Service和DAO类,基于SOA的理念,暴露出来的服务一定是接口,内部的实现类用Impl的后缀与接口区别
public interface DemoService{
void f();
}
public class DemoServiceImpl implements DemoService {
@Override
public void f(){
System.out.println("hello world");
}
}
12、常量命名应该全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长
public class ConstantNameDemo {
/**
* max stock count
*/
public static final Long MAX_STOCK_COUNT = 50000L;
13、所有的枚举类型字段必须要有注释,说明每个数据项的用途。
public enum TestEnum {
/**
* agree
*/
agree("agree"),
/**
* reject
*/
reject("reject");
private String action;
TestEnum(String action) {
this.action = action;
}
public String getAction() {
return action;
}
}
14、所有编程相关的命名均不能以下划线或美元符号开始
15、抽象类命名使用Abstract或Base开头
abstract class BaseControllerDemo{
}
abstract class AbstractActionDemo{
}
16、方法名、参数名、成员变量、局部变量都统一使用lowerCamelCase,必须遵从驼
17、线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("demo-pool-%d").build();
ExecutorService singleThreadPool = new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
singleThreadPool.execute(()-> System.out.println(Thread.currentThread().getName()));
singleThreadPool.shutdown();
18、POJO类必须写toString方法。使用工具类source> generate toString时,如果继承了另一个POJO类,注意在前面加一下super.toString。 说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。
public class ToStringDemo extends Super{
private String secondName;
@Override
public String toString() {
return super.toString() + "ToStringDemo{" + "secondName='" + secondName + '\'' + '}';
}
}
class Super {
private String firstName;
@Override
public String toString() {
return "Super{" + "firstName=" + firstName + '\'' + '}';
}
}
19、不允许任何魔法值(即未经定义的常量)直接出现在代码中。
Negative example:
//Magic values, except for predefined, are forbidden in coding.
if (key.equals("Id#taobao_1")) {
//...
}
Positive example:
String KEY_PRE = "Id#taobao_1";
if (KEY_PRE.equals(key)) {
//...
}
20、中括号是数组类型的一部分,数组定义如下:String[] args
String[] a = new String[3];
21、关于基本数据类型与包装数据类型的使用标准如下:
1) 所有的POJO类属性必须使用包装数据类型。
2) RPC方法的返回值和参数必须使用包装数据类型。
3) 所有的局部变量推荐使用基本数据类型。 说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE问题,或者入库检查,都由使用者来保证。
public class DemoDO {
String str;
Integer a;
}
22、及时清理不再使用的代码段或配置信息。 说明:对于垃圾代码或过时配置,坚决清理干净,避免程序过度臃肿,代码冗余。
Positive example: For codes which are temporarily removed and likely to be reused, use /// to add a reasonable note.
public static void hello() {
/// Business is stopped temporarily by the owner.
// Business business = new Business();
// business.active();
System.out.println("it's finished");
}
23、定义DO/DTO/VO等POJO类时,不要加任何属性默认值。
public class DemoDO {
String str;
Integer a;
}
24、所有的抽象方法(包括接口中的方法)必须要用javadoc注释、除了返回值、参数、异常说明外,还必须指出该方法做什么事情,实现什么功能。 说明:如有实现和调用注意事项,请一并说明。
/**
* fetch data by rule id
*
* @param ruleId rule id
* @param page page number
* @param jsonContext json format context
* @return Result<XxxxDO>
*/
Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);
25、所有的类都必须添加创建者信息。 说明:在设置模板时,注意IDEA的@author为${USER},而eclipse的@author为${user},大小写有区别,而日期的设置统一为yyyy/MM/dd的格式。
/**
* Demo class
*
* @author keriezhang
* @date 2016/10/31
*/
public class CodeNoteDemo {
}
26、方法内部单行注释,在被注释语句上方另起一行,使用//注释。方法内部多行注释使用/* */注释。注意与代码对齐。
public void method() {
// Put single line comment above code. (Note: align '//' comment with code)
int a = 3;
/**
* Some description about follow code. (Note: align '/**' comment with code)
*/
int b = 4;
}
27、类、类属性、类方法的注释必须使用javadoc规范,使用/**内容*/格式,不得使用//xxx方式和/*xxx*/方式。 说明:在IDE编辑窗口中,javadoc方式会提示相关注释,生成javadoc可以正确输出相应注释;在IDE中,工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。
/**
*
* XXX class function description.
*
*/
public class XxClass implements Serializable {
private static final long serialVersionUID = 113323427779853001L;
/**
* id
*/
private Long id;
/**
* title
*/
private String title;
/**
* find by id
*
* @param ruleId rule id
* @param page start from 1
* @return Result<Xxxx>
*/
public Result<Xxxx> funcA(Long ruleId, Integer page) {
return null;
}
}
28、类名使用UpperCamelCase风格,必须遵从驼峰形式,但以下情形例外:(领域模型的相关命名)DO / BO / DTO / VO / DAO
29、除常用方法(如getXxx/isXxx)等外,不要在条件判断中执行复杂的语句,将复杂逻辑判断的结果赋值给一个有意义的布尔变量,以提高可读性。 说明:很多if语句内的逻辑相当复杂,阅读者需要分析条件表达式的最终结果,才能明确什么样的条件执行什么样的语句,那么,如果阅读者分析逻辑表达式错误呢?
Negative example:
if ((file.open(fileName, "w") != null) && (...) || (...)) {
// ...
}
Positive example:
boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
//...
}
30、集合初始化时,指定集合初始值大小。 说明:HashMap使用如下构造方法进行初始化,如果暂时无法确定集合大小,那么指定默认值(16)即可。
Negative example:
Map<String, String> map = new HashMap<String, String>();
Positive example:
Map<String, String> map = new HashMap<String, String>(16);