1、类的命名使用驼峰式命名的规范。

例如:UserService,但是以下情景例外:DO / BO / PO / DTO / VO。

例如说:UserPO,StudentPO(PO,VO,DTO,等这类名词需要全大写)

@Data
@Builder
public class CustomBodyDTO { private String name; private String idCode; private String status;
}

2、如果在模块或者接口,类,方法中使用了设计模式,那么请在命名的时候体现出来。

例如说:TokenFactory,LoginProxy等。

public class TokenFactory {

    public TokenDTO buildToken(LoginInfo loginInfo) {
String token = UUID.randomUUID().toString();
TokenDTO tokenDTO = TokenDTO.builder()
.token(token)
.createTime(LocalDateTime.now())
.build();
String redisKey = RedisKeyBuilder.buildTokenKey(token);
redisService.setObject(redisKey, loginInfo, Timeout.ONE_DAY * 30 * 2);
log.info("创建token成功|loginInfo={}", loginInfo.toString());
return tokenDTO;
}
}

3、Object 的 equals 方法容易抛空指针异常。

从源码来进行分析equals方法是属于Object类的,如果调用方为null,那么自然在运行的时候会抛出空指针异常的情况。

object类中的源码:

    public boolean equals(Object obj) {
return (this == obj);
}

为了避免这种现况出现,在比对的时候尽量将常量或者有确定值的对象置前。

例如说:

正确:“test”.equals(object);
错误:object.equals(“test”);

4、对于所有相同类型的包装类进行比较的时候,都是用equal来进行操作。

对于Integer类来说,当相应的变量数值范围在-128到127之间的时候,该对象会被存储在IntegerCache.cache里面,因此会有对象复用的情况发生。

所以对于包装类进行比较的时候,最好统一使用equal方法。

    private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[]; static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h; cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
} private IntegerCache() {}
} public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

5、所有的pojo类中的属性最好统一使用包装类属性类型数据。RPC方法的返回值和参数都统一使用包装类数据。局部变量中使用基本的数据类型。

对于实际的应用场景来说,例如说一个学生类,当我们设置里面的成绩字段为int类型的时候,如果学生没有考试,那么这个成绩字段应该为空,但是int默认会赋值为0,那么这个时候使用基本数据类型就容易产生误区,到底是考了0分,还是说没有参加考试。

如果换成使用包装类Integer类型的话,就可以通过null值来进行区分了。

6、当pojo类在进行编写的时候要重写相应的toString方法,如果该pojo中继承了另外的一个pojo类,那么请在相应的tostring函数中加入super.toString()方法。

通过重写toString方法有利于在日志输出的时候查看相应对象的属性内容进行逐一分析,对于一些有继承关系的对象而言,加入了super.toString方法更加有助于对该对象的理解和分析。

7、在pojo的getter和setter方法里面,不要增加业务逻辑的代码编写,这样会增加问题排查的难度。

正确做法:

public class User {
private Integer id; private String username; public Integer getId() {
return id;
} public User setId(Integer id) {
this.id = id;
return this;
} public String getUsername() {
return username;
} public User setUsername(String username) {
this.username = username;
return this;
}
}

错误做法:

public class User {
private Integer id; private String username; public Integer getId() {
return id;
} public User setId(Integer id) {
this.id = id;
return this;
} public String getUsername() {
return "key-prefix-"+username;
} public User setUsername(String username) {
this.username = "key-prefix-"+username;
return this;
}
}

8、final 可以声明类、成员变量、方法、以及本地变量。

下列情况使用 final 关键字:

  • 不允许被继承的类,如:String 类。

  • 不允许修改引用的域对象,如:POJO 类的域变量。

  • 不允许被重写的方法,如:POJO 类的 setter 方法。

  • 不允许运行过程中重新赋值的局部变量。

  • 避免上下文重复使用一个变量,使用 final 描述可以强制重新定义一个变量,方便更好地进行重构。

9、对于任何类而言,只要重写了equals就必须重写hashcode。

举例说明:

1)HashSet在存储数据的时候是存储不重复对象的,这些对象在进行判断的时候需要依赖hashcode和equals方法,因此需要重写。

2)在自定义对象作为key键时,需要重写hashcode和equals方法,例如说String类就比较适合用于做key来使用。

10、不要在 foreach 循环里进行元素的 remove/add 操作。

remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁。

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (删除元素的条件) {
iterator.remove();
}
}

11、使用HashMap的时候,可以指定集合的初始化大小。

例如说,HashMap里面需要存放10000个元素,但是由于没有进行初始化大小操作,所以在添加元素的时候,hashmap的内部会一直在进行扩容操作,影响性能。

那么为了减少扩容操作,可以在初始化的时候将hashmap的大小设置为:已知需要存储的大小/负载因子(0.75)+1

HashMap hashMap=new HashMap<>(13334);

12、Map类集合中,K/V对于null类型存储的情况:

集合名称 key value 说明
HashMap 允许为null 允许为null 线程不安全
TreeMap 不允许为null 允许为null 线程不安全
HashTable 不允许为null 不允许为null 线程安全
ConcurrentHashMap 不允许为null 不允许为null 线程安全

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

通关观察可以发现,HashSet底层通过将传入的值再传入到一个HashMap里面去进行操作,进入到HashMap里面之后,会先通过调用该对象的hashcode来判断是否有重复的值,如果有再进行equals判断,如果没有相同元素则插入处理。

   public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

14、线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

错误做法:

ExecutorService executors = Executors.newSingleThreadExecutor();
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

对于线程池的参数需要有深入的理解后,结合实际的机器参数来进行参数设置,从而防止在使用中出现异常。

    ExecutorService fixedExecutorService = new ThreadPoolExecutor(
1,
2,
60,
TimeUnit.SECONDS,
linkedBlockingQueue,
new MyThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);

ps:使用Executors.new方式创建线程池的缺点:

对于FixedThreadPool 和 SingleThreadPool而言

允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。

对于CachedThreadPool 和 ScheduledThreadPool而言

允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

15、使用一些日期类的时候,推荐使用LocalDateTime来替代Calendar类,或者说使用Instant来替代掉Date类。

16、尽量避免在for循环里面执行try-catch操作,可以选择将try-catch操作放在循环体外部使用。

正确做法:

try {
for (int i = 0; i < 100; i++) {
doSomeThing();
}
}catch (Exception e){
e.printStackTrace();
}

不推荐做法:

for (int i = 0; i < 100; i++) {

      try {
doSomeThing();
} catch (Exception e) {
e.printStackTrace();
}
}

17、对于大段的代码进行try-catch操作,这是一种不负责任的行为,将稳定的代码也都包围在了try-catch语句块里面没能很好的分清代码的稳定性范围。

通常我们称在运行中不会出错的代码块为稳定性代码,可能会有异常出错的部分为非稳定性代码块,后者才是try-catch重点需要关注的对象。

18、在jdk7之后,对于流这类需要关闭连接释放资源的对象,可以使用try-with-resource处理机制来应对。

例如下方代码:

  File file = new File("*****");
try (FileInputStream fin = new FileInputStream(file)) {
//执行相关操作
} catch (Exception e) {
//异常捕获操作
}

19、使用ArrayList的时候,如果清楚它的指定大小的话,可以尽量在初始化的时候进行大小指定,因为随着arraylist不断添加新的元素之后,链表的体积会不断增大扩容。

    private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

20、对于一些短信,邮件,电话,下单,支付等应用场景而言,开发的时候需要设置相关的防重复功能限制,防止出现某些恶意刷单,滥刷这类型情况。

21、对于敏感词汇发表的时候,需要考虑一些文本过滤的策略。

这一块的功能可以考虑直接接入市面上已有的成熟的UGC监控服务,或者使用公司内部自研的ugc过滤工具,防止用户发表恶意评论等情况出现。

22、在建立索引的时候,对于索引的命名需要遵循一定的规范:

索引类型 命名规则 案例
主键索引 pk_字段名,pk是指primary key pk_order_id
唯一索引 uk_字段名,uk是指 unique key uk_order_id
普通索引 idx_字段名,idx是指 index idx_order_id

23、当我们需要存储一段文本信息的时候,需要先考虑存储文本的长度。

如果文本的长度超过了5000,则不建议再选择使用varchar类型来进行存储,可以考虑使用text类型进行数据存储,这个时候可以考虑单独用一张表来进行存储数据,并且通过一个额外的主键id来对应,从而避免影响其他字段的查询。

24、在进行数据库命名的时候尽量保证数据库的名称和项目工程的名称一致。

25、在进行表结构设计的时候,只要具有唯一性质的字段都需要建立唯一索引。

这样有助于后期进行查询的时候提高查询的效率,没有唯一索引这一层的保障,即使在业务层加入了拦截,但是依然容易造成线上脏数据的产生。

26、在进行order by这类型sql查询的时候,需要注意查询索引的有序性。

关于索引的建立,可以去了解一下索引的星级评定,例如三星索引。但是个人认为索引没有所谓的最优性,需要结合实际的业务场景来设计。

27、在MySQL中,使用count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

28、在进行数据库存储引擎选择的时候,需要结合相关的应用场景来选择,如果是需要应用在select操作较多的情况下,可以选择使用MyIsAM存储引擎,如果是对于数据的insert,update,这类修改操作较多的业务场景,则优先推荐使用innodb存储引擎。目前普遍互联网公司都推荐使用innodb较多。

参考

阿里巴巴Java开发手册

内容聚合阅

1. SpringBoot内容聚合

2. 面试题内容聚合

3. 设计模式内容聚合

4. 排序算法内容聚合

5. 多线程内容聚合

 

28个Java开发常用规范技巧总结的更多相关文章

  1. java开发命名规范(转载)

    java开发命名规范 使用前注意事项: 1.  由于Java面向对象编程的特性, 在命名时应尽量选择名词 2.  驼峰命名法(Camel-Case): 当变量名或函式名是由一个或多个单字连结在一起,而 ...

  2. java开发常用jar包介绍(转载)

    jta.jar 标准JTA API必要 commons-collections.jar 集合类 必要 antlr.jar  ANother Tool for Language Recognition ...

  3. JAVA开发常用工具包

    一个有经验的Java开发人员特征之一就是善于使用已有的轮子来造车.<Effective Java>的作者Joshua Bloch曾经说过:“建议使用现有的API来开发,而不是重复造轮子”. ...

  4. Java开发常用的在线工具

    原文出处: hollischuang(@Hollis_Chuang) 作为一个Java开发人员,经常要和各种各样的工具打交道,除了我们常用的IDE工具以外,其实还有很多工具是我们在日常开发及学习过程中 ...

  5. [开发工具]Java开发常用的在线工具

    注明: 本文转自http://www.hollischuang.com/archives/1459.作为一个Java开发人员,经常要和各种各样的工具打交道,除了我们常用的IDE工具以外,其实还有很多工 ...

  6. Eclipse Java 开发平台实用技巧

    前言 在使用Eclipse开发Java程序的使用,有很多实用的技巧,能大大提高开发效率. 本文将介绍一部分技巧.更多的心得还得在具体项目中慢慢掌握,熟悉. 初始设定 这些具体的设置方法这里不说,网上很 ...

  7. idea优秀插件(Java开发常用)

    http://blog.csdn.net/sujun10/article/details/72852939 1.findBugs-IDEA 可以查看代码中基础错误,这个eclipse中也有,操作也方便 ...

  8. 【在线工具】java开发常用在线工具

    转自:常用工具页面 Java源代码搜索 Grepcode是一个面向于Java开发人员的网站,在这里你可以通过Java的projects.classes等各种关键字在线查看它对应的源码,知道对应的pro ...

  9. java开发命名规范

    使用前注意事项: 1.  由于Java面向对象编程的特性, 在命名时应尽量选择名词 2.  驼峰命名法(Camel-Case): 当变量名或函式名是由一个或多个单字连结在一起,而构成的唯一识别字时,首 ...

随机推荐

  1. Application中数据传递及内存泄漏问题

    原文地址:http://android.tgbus.com/Android/tutorial/201107/359474.shtml Application的使用 Application和Actovo ...

  2. WPF扑克牌之红桃K

    原文:WPF扑克牌之红桃K 有些什么用途呢?我想,如果你有兴趣,可用来制作WPF扑克牌游戏. 没有任何技术含量,需要做的是在Blend中绘图或者使用Illustrator,CoreDraw等矢图设计软 ...

  3. Boltzmann 玻尔兹曼机(BM)

    Hopfield + 模拟退火 ⇒ Boltimann machine(随机神经网络),由 Hinton 和他的长期合作者 Sejnowski(Hopfield 的博士生) 共同提出. 1. 基本公式 ...

  4. ubuntu12.04单卡server(mentohust认证)再加上交换机做路由软件共享上网

    最近成立了实验室的网络环境中,通过交换机连接的所有主机实验室.想要一个通过该server(单卡)做网关,使用mentohust认证外网,然后内网中的其它主机通过此网关来连接外网. 1.首先在serve ...

  5. 开源mvcpager分页控件分页实例

    最近MVC需要用到分页,然后在网上找了一圈,发现一个很好用的分页控件,在此要感谢作者的辛勤劳动. 下载Pager 这个分页控件也有Asp.net的支持,需要的去看看作者的主页 webdiyer 先看看 ...

  6. opengl编程指南 第七版 源代码bug Page35 lines.c 红宝书

    问题1:根据源代码时,我发现的时候去敲门.不正确实施效果.哪里是不正确?没有源代码glPushAttrib(GL_LINE_STIPPLE) glPopAttrib().所以会出现最后的下一次抽奖提供 ...

  7. TypeScript Array Remove

    定义一个数组 tags:any[]; 方法1:filter 删除并不留空位 this.tags = this.tags.filter(tag => tag !== removedTag); 方法 ...

  8. js css加时间戳

    为了强制更新文件,取消浏览器缓存 <link rel="stylesheet" href="~/XXX.css?time='+new Date().getTime( ...

  9. WPF中的文字修饰——上划线,中划线,基线与下划线

    原文:WPF中的文字修饰——上划线,中划线,基线与下划线 我们知道,文字的修饰包括:空心字.立体字.划线字.阴影字.加粗.倾斜等.这里只说划线字的修饰方式,按划线的位置,我们可将之分为:上划线.中划线 ...

  10. 在WPF中,如何得到任何Object对象的XAML代码?

    原文:在WPF中,如何得到任何Object对象的XAML代码? 在WPF中,可以使用System.Windows.Markup.XamlWriter.Save(objName)得到任何Object对象 ...