栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java语言编程规范理解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java语言编程规范理解

二、代码风格 格式
  1. 一个源文件按顺序包含版权、package、import、顶层类,且用空行
    分隔

一个源文件中应按顺序包含以下信息:

  1. 许可证或版权信息;
  2. package语句,且语句内不换行;
  3. import语句,且语句内不换行,不能用通配符*;
  4. 顶级类(只有一个),所在.java源文件与它同名。
  1. 应用于类、方法、类属性的每个注解独占一行
  2. 类和成员修饰符(如果存在)按Java语言规范建议的顺序显示

public protected private abstract default static final transient volatile synchronized
native strictfp

  1. 数字字面量应该设置合适的后缀, long 类型应该使用L作为后缀

long值必须使用L后缀,不能使用l做后缀,d、f不强制采用大写。


三、编程实践 3.1 声明和初始化
  1. 每行声明一个变量
  2. 局部变量被声明在接近它们首次使用的行

类的成员变量要集中声明

  1. 禁止C风格的数组声明
  2. 避免枚举常量序号的产生依赖于ordinal()方法

ordinal返回的枚举常量的排列序号。如果有特殊不能使用。

  1. 禁止将mutable对象定义为常量

mutable:可变。

// 反例:Result类为可变的不能用public static final修饰
class Result {
    private int resultCode;
    private String resultMsg;

    public Result(int resultCode, String resultMsg) {
        reset(resultCode, resultMsg);
    }

    public void reset(int resultCode, String resultMsg) {
        this.resultCode = resultCode;
        this.resultMsg = resultMsg;
    }
}
// Result是一个mutable类,实例出来的SUCCESS即便用了public static final修饰,也仍是mutable对象
public static final Result SUCCESS = new Result(0, "Success");

public void foo() {
    SUCCESS.reset(101, "Failure"); // 不当使用:此时,SUCCESS这个“常量”已经被改变
// 后续代码再引用SUCCESS将带来业务异常
    if (bar() == SUCCESS) {
    ...
    }
}
// 反例:List、Map等大多都是mutable类,定义常量应该使用Collections.unmodifiableList() 、 Collections.unmodifiableMap()转化为不可变对象。
// java10以后提供了of()方法,返回的是不可变对象。
public static final List EMPTY_RESULT_LIST = new ArrayList<>();
public static final List RESULT_LIST = Arrays.asList("result1", "result2");
// 正确示例
// 使用Collections.unmodifiableList()以保证EMPTY_RESULT_LIST不可变
public static final List EMPTY_RESULT_LIST =
Collections.unmodifiableList(new ArrayList<>());
// 更自然的写法:Collections.emptyList()
public static final List EMPTY_RESULT_LIST = Collections.emptyList();
public static final List PRIME_NUMS = List.of(2, 3, 5, 7, 11, 13, 17, 19);
// List.of, Set.of, Map.of
3.2 数据类型 3.2.1 整数
  1. 数值运算时,避免整数溢出。

可能溢出:加减乘除、取绝对值
解决方法:先决条件检测、Math类安全方法、向上类型转换、BigInteger方法
Math.multiplyExact()方法乘积时候不溢出返回结果,溢出的时候抛出异常ArithmeticException。

  1. 除法和模运算除数不能为0
3.2.2 浮点数
  1. 禁止使用浮点数做循环计数器
  2. 精确计算使用BigDecimal,不要使用float和double

构造BigDecimal的时候应该使用字符串格式的数组,即BigDecimal(String val)

  1. 浮点型数据判断相等不要直接使用==,浮点型包装类型不要用equals()或者flt.compareTo(another)==0作相等的比较

可在一定误差范围内判断是否相等;符号不同不能使用精度范围;判断浮点数是否为0的时候,可以直接比较。

  1. 禁止与NaN进行比较运算,相等操作使用Double或Float的isNaN()方法

NaN(Not a Number) <,<=,>.>=,==会返回false,!=会返回true。

3.2.3 字符串
  1. 不要再代码中硬编码用于表示换行、文件路径分隔的字符

ing使用println()来代替华航夫,或者System.lineSeparator()获取运行时环境的换行符。分隔符可以使用java.io.File的separator和pathSeprator静态属性。

  1. 字符串大小写转化、数字格式化为西方数字时,必须加上Locale.ROOT或者Locale.ENGLISH

大小写转化建议显示指定Locale.Root .toUpperCase(Locale.ROOT) .format(Locale.ROOT, "%d", 2)
字符串转化的时候建议一次性转化,不能转化为字符数组转化。

  1. 字符与字节的互相转化操作,要指明正确的编码方式

data.getBytes(StandardCharsets.UTF_8) new String(buf, StandardCharsets.UTF_8) new InputStreamReader(fis, StandardCharsets.UTF_8)

  1. 内存中的敏感信息使用完毕后应立即清0

用string存储敏感信息,清理可通过反射、调用JNI接口等方式实现;推荐使用char[]byte[]存储,容易清理,直接Arrays.fill(value, (char) 0x00)

3.2.4 类型使用与转换
  1. 基本类型优于包装类型,注意合理使用包装类型
  2. 明确地进行类型转换,避免依赖隐式类型转换

不要把复合赋值运算符应用于byte、short、char类型的变量

  1. 在引用类型乡下转换前用instanceof进行判断。

不判断可能会因为类型不匹配而导致运行期异常 java.lang.ClassCastException.

3.3表达式
  1. 不要在单个表达式中对相同的变量赋值超过一次
  2. 用括号明确表达式的操作顺序,避免过分依赖默认优先级

一元运算、不涉及多种运算符、极简三元表达式或条件表达式,不需要使用括号。
位操作、拿其他执行结果作布尔比较的,需要加括号。

  1. 条件表达式?:的第2和第3个操作数应使用相同的类型。

不一样的操作数类型,会导致意料之外的类型转换,也可能会因为自动拆箱导致NullPointerException

  1. 表达式的比较,应该遵循左侧倾向于变化、右侧倾向于不变的原则
  2. 禁止直接使用可能为null的对象,防止出现空指针引用

通过预检查的方式进行消解,而不是try…catch处理

  1. 代码中不应使用断言assert

断言判断为false的时候会抛出AssertionError,会导致异常退出。在以下两种场景下不应该使用断言
1.运行态错误检查;2.逻辑代码执行

3.4控制语句
  1. 不要再控制性条件表达式执行赋值操作或执行复杂的条件判断
  2. 含else if分支的条件判断应在最后加一个else分支
  3. switch语句要有default分支
  4. 禁止使用空的无限循环
3.5方法 3.5.1方法设计
  1. 方法要简短

代码行数不超过50行(非空非注释);参数不超过5个;最大嵌套深度不超过4层。

  1. 不要使用已标注为@Deprecated的方法、类、类的属性。
3.5.2方法参数和返回值
  1. 不应把方法的参数当做临时变量

为了减轻疏忽导致再次赋值,可在参数前加final关键字;引用类型修改,允许修改内部属性。

  1. 谨慎使用可变数量参数

接受0到n个参数;当使用可变数量参数时,应避免使用固定数量的同类型参数对方法进行重载,导致代码不读。

  1. 对于返回数组或者容器的方法,应返回长度为0的数组或者容器,代替返回null。

可以为null的时候应该添加注释充分说明;有些不得不override的方法,可不加;已经用@Nullable等注解为可空的,可不加注释。

  1. 使用Optional代替null作为返回值或者可能的缺失值;禁止对Optional对象赋值为null。

不应该返回 Optional 、 Optional 、 Optional ,而应该使用
OptionalInt 、 OptionalLong 、 OptionalDouble

3.6类、接口与面向对象编程 3.6.1类
  1. 应避免定义public且非final的类属性
  2. 不要在父类的构造方法中调用可能被子类覆写的方法

由于在java中,子类初始化时,会调用父类的构造方法。如果调用,会导致子类初始化未完成而导致异常。

  1. 构造方法如果有多个,尽量重用
  2. 避免在无关的变量或无关的概念之间重用名字,避免隐藏、遮蔽、遮掩。

覆写override—子类与父类间;(子类示例方法覆写父类中非private非static的方法)
重载overload—类内部;(重载的时候放在一起;引起歧义换方法:可变参数、包装类型)
隐藏hide—子类与父类间;(属性、静态方法、内部类。相当于输出父类)
遮蔽shadow—类内部;(变量、方法、类:局部变量会遮蔽全局变量)
遮掩obscure—类内部;(变量、包、方法、类型)

  1. 避免基本类型与其包装类型的同名重载方法

重载如果有自动装箱和泛型场景下,各个重载方法之间的边界变模糊,所以避免使用。

  1. 覆写equals方法时,要同时覆写hashCode方法

如果不正确覆写hashCode方法,则会导致效率低下甚至出错。
hashCode约定:同一次运行,同一个对象equal不变,多次调用hashCode返回值必须相同;两个对象的equal方法相等,则hashCode返回值必相同;如果两个对象调用equal方法不相等,则对这两个对象的hashCode方法不要求返回值不同,但是出于减少哈希碰撞的性能考虑,最好不同。

  1. 子类覆写父类方法或实现接口时必须加上@Override注解

编译器就发现问题。

  1. 正确实现单例模式

确保同一个进程内,单例类只有一个对象,并且该对象对所有其他对象提供访问。
要求:构造方法私有;防止对象在初始化被多个线程同时运行;确保该对象不可序列化;确保该对象无法克隆。

  1. 使用类名调用静态方法,而不要使用实例或表达式来调用。

使用实例调用静态方法时,父子类有同名静态方法,实例调用实际用的是父类的静态方法。(静态属性同理)

3.6.2接口
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/346321.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号