[TOC]
### **1. return 一个空的集合,而不是 null**
如果一个程序返回一个没有任何值的集合,请确保一个空集合返回,而不是空元素。这样你就不用去写一大堆 ”if else” 判断null元素。
![](https://img.kancloud.cn/bb/e4/bbe4ddc3152519082b0df284f0f02e77_640x270.png)
Java的标准库设计者已经在 Collections 类中放了一个空的 List 常量 EMPTY\_LIST,除此之外,还有 EMPTY\_MAP, EMPTY\_SET
### **2. 小心使用 String连接**
因为字符串相加或者拼接的方式都会在对象池中查找字符串是否存在,如果不存在则创建,这样在拼接的过程中会产生大量中间过程的字符串,占用内存资源。StringBuilder效率优于StringBuffer,但是StringBuffer线程安全。
### 3. 避免空指针
下面说几个空指针的几个最常见的案例及解决之道。
#### 1、字符串比较,常量放前面
~~~
if(status.equals(SUCCESS)){
}
~~~
这个时候 status 可能为 null 造成空指针异常,应该把常量放前面,就能避免空指针异常。
~~~
if(SUCCESS.equals(status)){
}
~~~
这个应该在各种开发规范里面都会提到,也是最基础的。
#### 2、初始化默认值
在对象初始化的时候给它一个默认值或者默认构造实现,如:
~~~
User user = new User();
String name = StringUtils.EMPTY;
~~~
#### 3、返回空集合
在返回一个集合的话,默认会是 null,统一规范返回一个空集合。
举个 List 例子,如:
~~~
public List getUserList(){
List list = userMapper.gerUserList();
return list == null ? new ArrayList() : list;
}
~~~
这样接收方就不用担心空指针异常了,也不会影响业务。
#### 4、断言
断言是用来检查程序的安全性的,在使用之前进行检查条件,如果不符合条件就报异常,符合就继续。
Java 中自带的断言关键字:assert,如:
~~~
assert name == null : "名称不能为空";
~~~
输出:
~~~
Exception in thread "main" java.lang.AssertionError: 名称不正确
~~~
不过默认是不启动断言检查的,需要要带上 JVM 参数:-enableassertions 才能生效。
Java 中这个用的很少,建议使用 Spring 中的,更强大,更方便好用。
Spring中的用法:
~~~
Assert.notNull(name,"名称不能为空");
~~~
#### 5、Optional
Optional 是 JDK 8 新增的新特性,再也不用 != null 来判断了,这个在一个对象里面的多个子对象连续判断的时候非常有用。
### 4. 检查null和长度
> 不管什么时候你有一个集合、数组或者其他的,确保它存在并且不为空。
> 在学习前期这样的行为对你来说可能是多此一举,但对于已经工作或者做过项目的小伙伴来说,相信这样的代码对
Java7的Objects工具类,提供类对Object的相关操作
![](https://img.kancloud.cn/6b/ab/6bab9ea68a669e6736cb4d2e3497e214_872x400.png)
### 5. switch语句末尾总是加上default
```
int num = 4;
switch (num){
case 1:
System.out.println("值为1");
break;
case 2:
System.out.println("值为2");
break;
default:
System.out.println("无此值");
}
```
### 6. 使用 String.valueOf(value) 代替 ""+value
将其他值转换成字符串时,这样String.valueOf(value)效率会更高
```
Integer num = 1;
String str = "" + num;
String string = String.valueOf(num);
System.out.println(str);
System.out.println(string);
```
### 7. 尽量使用基本数据类型代替对象
```
String str = “hello”;
```
> 上面这种方式会创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串
```
String str = new String(“hello”);
```
> 此时程序除创建字符串外,str所引用的String对象底层还包含一个char数组,这个char数组依次存放了h,e,l,l,o
### 8. 不要用 NullPointerException进行空指针捕获
> 空指针异常应该用代码规避(比如检测不为空),而不是用捕获异常的方式处理
### 9. Bean 中的链式风格
什么是链式风格?我来举个例子,看下面这个 Student 的 Bean:
~~~
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public Student setName(String name) {
this.name = name;
return this;
}
public int getAge() {
return age;
}
public Student setAge(int age) {
return this;
}
}
~~~
仔细看一下 set 方法,这样的设置便是 chain 的 style,调用的时候,可以这样使用:
~~~
Student student = new Student()
.setAge(24)
.setName("zs");
~~~
相信合理使用这样的链式代码,会更多的程序带来很好的可读性,那看一下**如果使用 Lombok 进行改善呢,请使用 @Accessors(chain = true),看如下代码:**
~~~
@Accessors(chain = true)
@Setter
@Getter
public class Student {
private String name;
private int age;
}
~~~
这样就完成了一个对于 Bean 来讲很友好的链式操作。
### 10. Lombok静态构造方法
使用lombok(@RequiredArgsConstructor 和 @NonNull):
~~~
@Accessors(chain = true)
@Setter
@Getter
@RequiredArgsConstructor(staticName = "ofName")
public class Student {
@NonNull private String name;
private int age;
}
~~~
测试代码:
~~~text
Student student = Student.ofName("zs");
~~~
这样构建出的 bean 语义是否要比直接 new 一个含参的构造方法(包含 name 的构造方法)要好很多。当然,看过很多源码以后,我想相信将静态构造方法 ofName 换成 of 会先的更加简洁:
~~~
@Accessors(chain = true)
@Setter
@Getter
@RequiredArgsConstructor(staticName = "of")
public class Student {
@NonNull private String name;
private int age;
}
~~~
测试代码:
~~~
Student student = Student.of("zs");
~~~
当然它仍然是支持链式调用的:
~~~
Student student = Student.of("zs").setAge(24);
~~~
这样来写代码,真的很简洁,并且可读性很强。
### 11. 使用 Builder
Builder 模式我不想再多解释了,读者可以看一下 Head First(《设计模式》)的建造者模式。
今天其实要说的是一种变种的 Builder 模式,那就是构建 Bean 的 Builder 模式,其实主要的思想是带着大家一起看一下 Lombok 给我们带来了什么。
看一下 Student 这个类的原始 Builder 状态:
~~~
public class Student {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static Builder builder(){
return new Builder();
}
public static class Builder{
private String name;
private int age;
public Builder name(String name){
this.name = name;
return this;
}
public Builder age(int age){
this.age = age;
return this;
}
public Student build(){
Student student = new Student();
student.setAge(age);
student.setName(name);
return student;
}
}
}
~~~
调用方式:
~~~
Student student = Student.builder().name("zs").age(24).build();
~~~
这样的 Builder 代码,让我是在恶心难受,于是我打算用 Lombok 重构这段代码:
~~~
@Builder
public class Student {
private String name;
private int age;
}
~~~
调用方式:
~~~
Student student = Student.builder().name("zs").age(24).build();
~~~
### 13. 复杂代码拆分,减少代码层级
- 计算机网络
- 基础_01
- tcp/ip
- http转https
- Let's Encrypt免费ssl证书(基于haproxy负载)
- what's the http?
- 网关
- 网络IO
- http
- 工具
- Git
- 初始本地仓库并上传
- git保存密码
- Gitflow
- maven
- 1.生命周期命令
- 聚合与继承
- 插件管理
- assembly
- 资源管理插件
- 依赖范围
- 分环境打包
- dependencyManagement
- 版本分类
- 找不到主类
- 无法加载主类
- 私服
- svn
- gradle
- 手动引入第三方jar包
- 打包exe文件
- Windows
- java
- 设计模式
- 七大原则
- 1.开闭原则
- 2. 里式替换原则
- 3. 依赖倒置原则
- 4. 单一职责原则
- 单例模式
- 工厂模式
- 简单工厂
- 工厂方法模式
- 抽象工厂模式
- 观察者模式
- 适配器模式
- 建造者模式
- 代理模式
- 适配器模式
- 命令模式
- json
- jackson
- poi
- excel
- easy-poi
- 规则
- 模板
- 合并单元格
- word
- 读取
- java基础
- 类路径与jar
- 访问控制权限
- 类加载
- 注解
- 异常处理
- String不可变
- 跨域
- transient关键字
- 二进制编码
- 泛型1
- 与或非
- final详解
- Java -jar
- 正则
- 读取jar
- map
- map计算
- hashcode计算原理
- 枚举
- 序列化
- URLClassLoader
- 环境变量和系统变量
- java高级
- java8
- 1.Lambda表达式和函数式接口
- 2.接口的默认方法和静态方法
- 3.方法引用
- 4.重复注解
- 5.类型推断
- 6.拓宽注解的应用场景
- java7-自动关闭资源机制
- 泛型
- stream
- 时区的正确理解
- StringJoiner字符串拼接
- 注解
- @RequestParam和@RequestBody的区别
- 多线程
- 概念
- 线程实现方法
- 守护线程
- 线程阻塞
- 笔试题
- 类加载
- FutureTask和Future
- 线程池
- 同步与异步
- 高效简洁的代码
- IO
- ThreadLocal
- IO
- NIO
- 图片操作
- KeyTool生成证书
- 压缩图片
- restful
- 分布式session
- app保持session
- ClassLoader.getResources 能搜索到的资源路径
- java开发规范
- jvm
- 高并发
- netty
- 多线程与多路复用
- 异步与事件驱动
- 五种IO模型
- copy on write
- code style
- 布隆过滤器
- 笔试
- 数据库
- mybatis
- mybatis与springboot整合配置
- pagehelper
- 分页数据重复问题
- Java与数据库之间映射
- 拦截器
- 拦截器应用
- jvm
- 堆内存测试
- 线程栈
- 直接内存
- 内存结构
- 内存模型
- 垃圾回收
- 调优
- 符号引用
- 运行参数
- 方法区
- 分带回收理论
- 快捷开发
- idea插件
- 注释模板
- git
- pull冲突
- push冲突
- Excel处理
- 图片处理
- 合并单元格
- easypoi
- 模板处理
- 响应式编程
- reactor
- reactor基础
- jingyan
- 规范
- 数据库