Java 常见的代码规范

1、构造器参数太多

引入Builder模式场景:当构造器有5个以上的构造参数或者目前参数不多但是以后会不断增加的情况。

public class Computer{
    protected String mBoard;
    protected String mDisplay;
    protected String mOs;
    
    static class Builder{
        protected String mBoard;
    	protected String mDisplay;
    	protected String mOs;
        
        public Builder setmOs(String mOs){
            this.mOs = mOs;
            return this;
        }
        public Builder setmBoard(String mBoard){
            this.mBoard = mBoard;
            return this;
        }
        public Builder setmDisplay(String mDisplay){
            this.mDisplay = mDisplay;
            return this;
        }
        public Computer build(){
            return new Computer(this);
        }
    }
}

调用规则如下:

Computer macbook = new Computer.Builder().setmBoard("board").setDisplay("sowhat").setmOs("Mac").build();

2、不需要实例化的类构造器要私有化

经常用到Utils类,比如Java自带的java.util.Arrays这样的类,工具类都尽量不要实例化

public class Arrays{
	private static final int MIN_ARRAY_SORT_GRAN = 8192;
	private static final int INSERTIONSORT_THRESHOLD = 7;
	private Arrays(){
	
	}
}

3、不要创建不必要的对象

1)、能用基本类型的时候尽量用基本类型。例如在做数字运算的时候,如果定义了包装类,会涉及到大量的自动拆箱与装箱,耗时会增加。

2)、对于在程序中共用的参数尽量设置为static类型的变量。

3)、对于一些耗时性较大的对象比如数据库连接池,尽量使用池化思想。

4)、对于一些内存占据较大的对象尽量少创建,因为会在eden区来回倒腾。

4、避免使用终结方法

4.1 finalize()方法:

1)、finalize()是Object的protected方法,子类可以覆盖该方法以实现资源清理的工作,GC在回收对象之前调用该方法;

2)、finalize()与C++中的析构函数是不对应的,但Java中的finalize的调用具有不确定性

3)、finalize()方法在垃圾回收器准备垃圾回收前被调用,但不一定会被调用

4)、finalize()其实是用来释放不是通过new关键字分配的内存,比如本地方法调用了c程序,该c程序通过malloc分配的内存,那么垃圾回收器就不能通过java语言来释放内存,只能在finalize()方法内通过本地方法调用c程序进行释放内存。

一个对象要被回收要经过一次标记可达法已经两次check才算死亡

总结:finalize()并不是必须要执行的,它只能执行1次或者0次,如果在finalize()中建立对象关联,则当前对象可以复活一次

4.2 System.gc

用System.gc()的时候,其实并不会马上进行垃圾回收,甚至不一定会执行垃圾回收。查看System.gc()的源码可以看到只有当justRanFinalization = true的时候系统才会真正的GC。如果要真的回收,要System.gc()和System.runFinalization()一起搭配使用。

5、类和成员的可访问性最小化

设计模式中迪米特法则(最少知识原则):要求一个对象应该对其他对象有最少的了解

意义:降低代码的耦合,由于每个对象尽量减少对其他对象的了解,因此,很容易是的系统的功能模块独立,相互之间不存在依赖关系,最常见的是成员变量的私有化。

6、使可变性最小化

尽可能的使用final来修饰一些变量,这样的话线程操作就不需要考虑同步问题,同时也对一个变量的不同setX方法也OK。

7、优先使用复合胜过继承

继承使实现代码重用的有力手段,但是使用不当会导致软件变得脆弱。在包的内部使用继承使安全的,子类和超类的实现都处于同一个程序员的控制之下。对于专门为了继承而设计,并且具有很好的文档说明的类来说,使用继承也是非常安全的。然而对于进行跨越包边界的继承,则要非常小心。“继承”在这里特指一个类扩展为另一个类。需要我们对父类十分了解才可以继承,只有子类和超类之间存在确定的父子关系时,才可以考虑使用继承。否则都应当使用复合,包装类不仅比子类更加健壮,而且功能也更加强大。

8、接口优于抽象类

继承使实现代码重用的有力手段,但是使用不当会导致软件变得脆弱。在包的内部使用继承使安全的,子类和超类的实现都处于同一个程序员的控制之下。对于专门为了继承而设计,并且具有很好的文档说明的类来说,使用继承也是非常安全的。然而对于进行跨越包边界的继承,则要非常小心。“继承”在这里特指一个类扩展为另一个类。需要我们对父类十分了解才可以继承,只有子类和超类之间存在确定的父子关系时,才可以考虑使用继承。否则都应当使用复合,包装类不仅比子类更加健壮,而且功能也更加强大。

9、可变参数谨慎使用

JDK5增加了可变参数的使用(variable arity method),可变参数方法接收0个或者多个指定类型的参数

可变参数机制:先创建一个数组,数组大小为调用位置所传递的参数数量,然后将参数值传递到数组中,最后将数组传递给方法。弊端如下:

1)、如果所传递的参数为null,方法里有对参数的引用(比如args[0])时,那么就会在运行时失败(编译时却检测不出错误)

2)、在对性能有要求时,我们要慎重考虑是否使用可变参数。因为,可变参数方法的调用都会引起array的内存分配和初始化,给性能带来损耗。

3)、当可变参数的使用发生变动时,(比如:以前用可变参数方法,现在用普通方法),所有参数列表的类的.class都要重新生成,因为可变参数的array的分配和初始化都是在编译期间完成的。

Effective Java建议:假设调用可变参数的方法中,有95%只是调用参数个数小于4,那么就可以将个数小于4的方法,用普通方法定义;剩余的5%,调用可变参数方法。

public void foo(){}
public void foo(int a1){}
public void foo(int a1,int a2){}
public void foo(int a1, int a2, int a3){}
public void foo(int a1, int a2, int a3,int a4,int... rest){}

10、尽量不要返回NULL,尽量返回零数组或者集合

函数如果返回了NULL,那么代码还要重新判断返回值。JDK都主动给我们提供了Collections.EMPTY_LIST。

1、返回值为null并不会有什么问题,但是在“解引用”时,调用则没有对null进行判断就会出现NullPointerException。

2、在返回值为数组或者为集合时,尽量返回长度为零的数组或者集合,而不是null,这样在调用时就能简化代码,减少不必要的麻烦,并且不必担心NPE的异常。

11、优先使用标准异常

优点:追求代码重用的考虑,在装载类的性能上面考虑。

1)、易于对官方API更加了解和使用

2)、对于用到这些API的程序而言,可读性更好,因为他们不会出现不熟悉的异常

3)、异常类越少,以为内存印记就越小,装载这些类的时间开销也就越少

12、尽量使用枚举类替换int

枚举的本质就是一个类的具体实现。

13、局部变量的作用域最小化

1)、从系统GC的角度考虑(一个变量的周期越短整个GC的过程就越快)

2)、从栈帧的局部变量表的可重用性来看,作用域越小系统的栈帧空间利用越大

3)、可以增强代码的重用性和可维护性,并降低出错的可能性

做法:1)、在第一次使用某个局部变量的地方进行声明;2)、如果还没有足够多的前置信息对一个变量进行有意义的初始化,就应该推迟这个变量的声明,直到可以初始化为止

14、精度记住不用float而用double

15、字符串少用String

16、对资源的close方法尽量分开操作。

17、数据类型的转换

基本数据类型转换为String的时候注意性能优化。比如Integer类型数据转换为String一般有三种方法:

1)、Integer.toString():性能好;

2)、String.valueOf()底层调用的是Integer.toString方法,性能中等;

3)、i+"",底层是用StringBuilder实现,先用append方法拼接,再用toString方法获取字符串,速度最慢。

18、不用对象置为NULL;

19、if判断常量在前

20、字符串的比较时建议使用"abc".equal(str)

21、尽量使用同步方法块而不是同步方法,除非我们能确定一整个方法都需要进行同步的,否则尽量使用同步代码块,避免对那些不需要进行同步的代码也进行的同步,影响代码的执行效率

22、一个方法要尽量实现单一职责

23、一定要写注释。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值