阿里巴巴Java开发手册:编程规约.OOP

2.【强制】所有的覆写方法,必须加@Override注解。

说明:getObject()与get0bject()的问题。一个是字母的O,一个是数字的0,加@Override可以准确判断是否覆盖成功,避免外形太像导致覆写失败。另外,如果在抽象类中对方法签名进行修改,其实现类会马上编译报错。

重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。返回值类型、方法名、参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类,即要满足里氏替换原则。

如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被static修饰的方法能够被再次声明。

构造方法无法被重写。

3.【强制】相同参数类型,相同业务含义,才可以使用Java的可变参数,避免使用Object。

正例:

public List<User> listUsers(String type, Long... ids) {...}

说明:可变参数必须放置在参数列表的最后。(提倡同学们尽量不用可变参数编程)

java 可变参数是1.5版本的新特性,也就是说用户若是想定义一个方法,但是在此之前并不知道以后要用的时候想传几个参数进去,可以在方法的参数列表中写参数类型或者数组名,然后在方法内部直接用操作数组的方式操作。适用于参数个数不确定,类型确定的情况。

可参考文章:https://blog.csdn.net/w605283073/article/details/91902705

4.【强制】外部正在调用或者二方库依赖的接口,不允许修改方法签名,避免对接口调用方产生影响。接口过时必须加@Deprecated注解,并清晰地说明采用的新接口或者新服务是什么。

说明:方法签名是方法名+参数类型,比如以下这个方法

public double calculateAnswer(double wingSpan, int numberOfEngines,
                              double length, double grossTons) {
    //do the calculation here
}

方法签名就是calculateAnswer(double, int, double, double),如果修改了,调用方处的代码必然会报错。

@Deprecated注解,若某类或某方法加上该注解之后,表示此方法或类不再建议使用,调用时也会出现删除线,但并不代表不能用,只是说不推荐使用,因为还有更好的方法可以调用。不将原来的方法直接删除是因为可能在很多地方需要调用他,删除带来的工作量太大,只能使用该注解说明过时,让之后的开发者使用新的方法。

6.【强制】Object的equals方法容易抛空指针异常,应使用常量或确定有值的对象来调用equals。

正例:“test”.equals(object);
反例:object.equals(“test”);
说明:推荐使用java.util.Objects#equals(JDK7引入的工具类)
方法内部是这样

// 1. Objects.equals(Object a, Object b)
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

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

首先是对象的引用判断,其次就是调用对象自身的equals方法来比较,如果对象类型没有重写equals的话,就会调用Object的equals方法(仍然是对象的引用比较),并且还考虑了null的问题。

该工具类中还有hashCode()和toString()方法,也很简单易用

8.关于基本数据类型与包装数据类型的使用标准如下:

1) 【强制】所有的POJO类属性必须使用包装数据类型。

2) 【强制】RPC方法的返回值和参数必须使用包装数据类型。

3) 【推荐】所有的局部变量使用基本数据类型。

正例:数据库的查询结果可能是null,因为自动拆箱,用基本数据类型接收有NPE风险。

反例:比如显示成交总额涨跌情况,即正负x%,x为基本数据类型,调用的RPC服务,调用不成功时,返回的是默认值,页面显示为0%,这是不合理的,应该显示成中划线。所以包装数据类型的null值,能够表示额外的信息,如:远程调用失败,异常退出。

说明:POJO类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何NPE(NullPointException)问题,或者入库检查,都由使用者来保证。这点我们需要自己注意,在平常的开发中很少使用包装数据类型,大部分是基本数据类型,需要改正。

10.【强制】序列化类新增属性时,请不要修改serialVersionUID字段,避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改serialVersionUID值。

说明:注意serialVersionUID不一致会抛出序列化运行时异常。

serialVersionUID适用于Java的序列化机制。简单来说,Java的序列化机制是通过判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常,即是InvalidCastException。

serialVersionUID有两种显示的生成方式:

一是默认的1L,比如:

private static final long serialVersionUID = 1L; 

二是根据包名,类名,继承关系,非私有的方法和属性,以及参数,返回值等诸多因子计算得出的一个64位的哈希字段。基本上计算出来的这个值是唯一的。比如:

private static final long  serialVersionUID = xxxxL; 

这种情况下,如果Class文件(类名,方法名等)没有发生变化(增加空格,换行,增加注释等等),就算再编译多次,serialVersionUID也不会变化的,此种方式是不兼容的。

18.【推荐】循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。

反例:

String str = "start";
for (int i = 0; i < 100; i++) {
    str = str + "hello";
}

说明:上例中,反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。

String是不可变的,因为使用final关键字修饰字符数组来保存字符串,StringBuilder与StringBuffer 都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串char[]value,但是没有用final关键字修饰,所以这两种对象都是可变的。jvm会将string的连接优化成stringbuilder的append,但是会消耗资源,在循环中每次都产生一个stringbuilder。

可见:
https://www.cnblogs.com/rjhlovelife/archive/2018/06/09/9159953.html

20.【推荐】慎用Object的clone方法来拷贝对象。 说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现域对象的深度遍历式拷贝。

说明:针对引用类型,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存,修改新对象会导致原对象也改变。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
深拷贝可以通过序列化和递归重写clone方法实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值