编码规范、常用知识整理——Java
2021/5/18 12:27:04
本文主要是介绍编码规范、常用知识整理——Java,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
编码规范、常用知识整理——Java
1.1、异常处理
如果想抛出检查型异常,则应该在方法上throws Exception或它的子类,建议子类
如果想抛出运行时异常,则应该在方法上throw RuntimeException或它的子类,建议子类
异常传播时,只会被异常本身类或直接父类捕获
service层:
不应该用异常来实现程序流程控制,service增方法统一抛出runtimerException的子类,service层返回值采用自定义对象ServiceResult
对于增删改方法且需要回滚时,才在代码中主动throw一个运行时异常
1.2、不用map传参
map作为形参,可读性非常差
1.3、用jackson代替fastjson
fastjson虽然快,但快不了多了
代码质量低
在maven仓库的使用数量上,jackson也大于fastjson
springmvc默认引入json,最少依赖原则
1.4、数组转list最高效的方式
List<String> list = new ArrayList<>();
String[] arr = {"1","2","3"};
Collections.addAll(list, arr);
1.5、list转数组
用list的toArray方法,list.size一定要等于arr.length
1.6、数组复制
System.arraycopy方法
1.7、hashmap指定大小
n为预估个数,x为初始化大小
则有公式2^x*0.75 > n > 2^(x-1)*0.75,即2^x > n*4/3 > 2^(x-1)
当n=600时,则有1024 > 800 >512
求得x=10
另外,hashmap默认初始化大小为16,可容纳2^16*0.75=49152个键值对,会造成内存浪费,故hashmap初始化时要指定大小
1.8、ArrayList指定大小
默认初始化大小是10
1.9、变量名后跟类型
如paramMap,paramList,paramArr
1.10、常量规则
类共享常量,写成private static final
类局部常量,指定final
由于string引用直接指向常量池,故不必非得写成全局常量,如果它共享概率很小,可以写成局部常量
1.11、无线循环使用for(;;)而不是while(true)
从效率上看,while(true)每次循环要判断循环条件,for(;;)循环没有判断,理论上节省机器指令
for(;;)编译之后只有一条指令,而while(true)有好几条
1.12、controller、service、dao方法命名
controller
save
remove
update
query
service
save
remove
update
get
list 用复数
count
dao
insert
delete
update
select
count
1.13、boolean属性不要加is前缀
POJO类中布尔类型的变量,都不要加is前缀
1.14、包装类之间用equals比较,不用==
由于Integer类有缓存,会复用已有对象
1.15、用包装类代替基本类型
POJO类属性使用包装类型
RPC方法的返回值和参数使用包装类型
局部变量使用基本类型
原因:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险
1.16、POJO类不要设置属性默认值
1.17、POJO类必须重写toString
如果继承了另一个POJO类,注意在前面加一下super.toString
在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题
1.18、重写equals和hashcode的情况
因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法
如果自定义对象作为Map的键,那么必须重写hashCode和equals
String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用
1.19、集合泛型定义时,在JDK7及以上,使用diamond语法或全省略
菱形泛型,即diamond,直接使用<>来指代前边已经指定的类型。
diamond方式:
HashMap<String, String> userCache = new HashMap<>(16);
全省略方式:
ArrayList<User> users = new ArrayList(10);
1.20、使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历
keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value
而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高
如果是JDK8,使用Map.foreach方法
1.21、static和final
1、public static boolean lock = false
这种写法不规范,有两种改法:
public static通常和final一起使用,可改为public static final boolean LOCK = false
改为private static boolean lock = false,并添加get/set方法
2、实例方法里不能直接操作静态变量,而应该通过get/set方法去操作
3、日志变量应该声明为private static final Logger logger
2、零散知识篇
2.1、变量在内存中的存放位置
局部变量
基本类型:引用和值都放在栈上
对象类型:引用放在栈上,对象放在堆上
全局实例变量:
基本类型:引用和值都放在堆上
对象类型:引用和对象都放在堆上
全局静态变量:
基本类型:引用和值放在堆上
对象类型:引用和值放在堆上
java7:常量池和类的静态变量放在方法区
java8:常量池和类的静态变量放在堆上
2.2、既然 JVM 有 Full GC,为什么还会出现 OutOfMemoryError?
对于强引用,当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题
为什么我请了佣人来收拾房间,我的房间还是会堆满?
那我还请佣人来干什么?
他不是号称能把我房间里的垃圾都清理干净的么?
问题是如果您房间里堆的都是宝贝(或者看起来都是宝贝)的话,佣人也没辙
2.3、序列化ID有什么用?
序列化ID起着关键的作用,它决定着是否能够成功反序列化!简单来说,java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常
如何定义:private static final long serialVersionUID = 8965308904607290970L;
如果没有显示定义:当我们一个实体类中没有显示的定义一个名为“serialVersionUID”、类型为long的变量时,Java序列化机制会根据编译时的class自动生成一个serialVersionUID作为序列化版本比较,这种情况下,只有同一次编译生成的class才会生成相同的serialVersionUID
2.4、为什么在Java中有关密码的地方更加喜欢使用char[]而不是String
String是不可变的,这也意味着在GC之前,你对这些数据不能做任何处理。因此,只要有人能够访问你的内存,那么String就有可能被他获取到。这也就是为什么要使用char数组。你可以显示地清除数据或者覆盖它。这样密码这种敏感数据即使GC还没有进行也不会再在系统留下痕迹
2.5、Integer类有缓存
public static void main(String[] args){
Integer a = 100;
Integer b = 100;
Integer c = 200;
Integer d = 200;
System.out.println(a==b);
System.out.println(c==d);
}
上面的代码竟然输出:
true
false
这确实太出乎意料了,同样的代码,只是数值不同(而且差别不太大的样子),就产生了不一样的输出,这也太离谱了。
原来,Integer中有一个静态内部类IntegerCache,在类加载的时候,它会把[-128, 127]之间的值缓存起来,而Integer a = 100这样的赋值方式,会首先调用Integer类中的静态valueOf方法,这个方法会尝试从缓存里取值,如果在这个范围之内就不用重新new一个对象了:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
2.6、BigDecimal一定不会丢失精度吗?
//会丢失精度
double a = 2.0;
double b = 1.1;
System.out.println(a-b);
//会丢失精度
BigDecimal b1 = new BigDecimal(2.0);
BigDecimal b2 = new BigDecimal(1.1);
BigDecimal res = b1.subtract(b2);
System.out.println(res.doubleValue());
//不会丢失精度
BigDecimal b3 = new BigDecimal("2.0");
BigDecimal b4 = new BigDecimal("1.1");
BigDecimal res1 = b3.subtract(b4);
System.out.println(res1.doubleValue());
//不会丢失精度
BigDecimal b5 = BigDecimal.valueOf(2.0);
BigDecimal b6 = BigDecimal.valueOf(1.1);
BigDecimal res2 = b5.subtract(b6);
System.out.println(res2.doubleValue());
注意,要用BigDecimal类的BigDecimal(String)构造方法,或使用valueOf方法
2.7、LinkedList如何实现链表?
LinkedList有内部类Node
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
2.8、java内部排序算法
Colletions.sort采用归并排序
Arrays.sort() : 基本类型数据使用快速排序法,对象数组使用归并排序
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面
快速排序思想:
2.9、subList与substring
取值都是左闭右开,即[ )
2.10、java transient关键字
让被transient关键字修饰的成员属性变量不被序列化
千锋教育整理,来源网络波波的小书房,侵权联系删除,谢谢。
这篇关于编码规范、常用知识整理——Java的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26JAVA语音识别项目资料的收集与应用
- 2024-11-26Java语音识别项目资料:入门级教程与实战指南
- 2024-11-26SpringAI:Java 开发的智能新利器
- 2024-11-26Java云原生资料:新手入门教程与实战指南
- 2024-11-26JAVA云原生资料入门教程
- 2024-11-26Mybatis官方生成器资料详解与应用教程
- 2024-11-26Mybatis一级缓存资料详解与实战教程
- 2024-11-26Mybatis一级缓存资料详解:新手快速入门
- 2024-11-26SpringBoot3+JDK17搭建后端资料详尽教程
- 2024-11-26Springboot单体架构搭建资料:新手入门教程