编码规范、常用知识整理——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的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程