【Java】Best coding practices every java developer should(二)

简介: 【Java】Best coding practices every java developer should

【Java】Best coding practices every java developer should(一)https://developer.aliyun.com/article/1395275

9. 返回空集合而不是null

NPE is the most frequent exception in production with absolute leadership, do not give it a chance.

更进一步说是让整个系统不要出现空指针异常,不应该因为项目代码妥协老旧的编程风格。一定不要让空指针有可乘之机。除了返回空集合以外,还可以利用Optional的工具类包装有可能为Null的对象,显式的告诉调用者对象有可能为Null。

An empty collection might have a different meaning than no collection at all.

有时候null 也可能是“有意义”的,使用的时候也需要考虑具体情况,当然返回空集合肯定是没有任何问题的。

Collections

空集合相关的轮子在Collections可以找到答案,但是需要注意需要合理使用,JDK5之后出现了emptyXXX等集合类,但是这些类“暗藏杀机”,因为它们的效果和List.subList() 一样是immutable 的。

虽然JDK的工具类可以减少不必要的对象创建,但是假设接收方需要在收到空集合之后却还要往里面设置数据,这时候毫无疑问就会抛异常了。


/**
     * Returns an empty list (immutable).  This list is serializable.
     *
     * <p>This example illustrates the type-safe way to obtain an empty list:
     * <pre>
     *     List&lt;String&gt; s = Collections.emptyList();
     * </pre>
     *
     * @implNote
     * Implementations of this method need not create a separate <tt>List</tt>
     * object for each call.   Using this method is likely to have comparable
     * cost to using the like-named field.  (Unlike this method, the field does
     * not provide type safety.)
     *
     * @param <T> type of elements, if there were any, in the list
     * @return an empty immutable list
     *
     * @see #EMPTY_LIST
     * @since 1.5
     */
    @SuppressWarnings("unchecked")
    public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
    }

我认为emptyList()更为合理的方法名称是 immutableEmptyList()mutableEmptyList(),当然mutableEmptyList()就是new新的ArrayList()这样的方法,看起来是毫无意义的,也许JDK设计的时候也是考虑这种情况?

8. 精度选择

Most processors take almost same time in processing the operations on float and double but double offers way more precision then float that is why it is best practice to use double when precision is important otherwise you can go with float as it requires half space than double.。

大型处理器在处理double和float的时候计算速度是类似的。但是在Java中大部分情况只要是涉及浮点数计算都是闭着眼睛用BigDecimal。如果精度很重要直接无脑使用BigDecimal,double和float都会骗人。

When precision is important, use BigDecimal. Double and Float aren’t accurate. They will betray you when you least expect it. 1 + 1 can be 1.99999999999.

当精度很重要时请使用BigDecimal,Double和Float并不精确。它们会在你最不期望的时候背叛你。1+1可能是1.99999999999。

1. 项目结构

有点过于基础了。下面是Maven的经典结构,如果是Maven新手可以看看项目的基本布局

  • src/main/java: For source files
  • src/main/resources: For resource files, like properties
  • src/test/java: For test source files
  • src/test/resources: For test resource files, like properties

2. 遵循命名规范

没啥好讲的,程序员的基础素质。最好的命名规范不是参考某一个标准,而是能统一风格布局代码。

3. 不要吞异常

在异常处理时在 catch 块中编写适当且有意义的消息是精英 java 开发人员首选的 java 最佳实践。新手常常会把异常捕获之后不做任何处理,吞异常是非常危险的行为

得益于IDE的帮助,catch之后不打印任何信息的情况不是很多见,但是打印堆栈其实也是非常消耗资源的操作,同时因为是打印在控制台,如果不调用日志保存关键信息也有可能导致关键信息丢失。

16. 使用枚举替代静态常量【建议】

在Java推出枚举之前,定义一个常量基本只能使用下面的接口方式。在很多优秀框架的最早期版本中经常能看到这样的写法,并且到现在使用这种写法的不在少数 。


public interface Color {
    public static final int RED = 0xff0000;
    public static final int BLACK = 0x000000;
    public static final int WHITE = 0xffffff;
}

It’s because the purpose of interfaces is for inheritance and polymorphism, not for static stuffs like that. So the best practice recommends us to use an enum instead.

这是因为接口的目的是用于继承和多态性,而不是用于类似的静态东西。所以最佳实践建议我们使用枚举来代替。


public enum Color {
    BLACK(0x000000),
    WHITE(0xffffff),
    RED(0xff0000);
    private int code;
    Color(int code) {
        this.code = code;
    }
    public int getCode() {
        return this.code;
    }
}

使用枚举和静态常量的对比:

  • 枚举更具备描述性
  • Keep It Simple, Stupid。接口可以用于继承和多态,枚举能干的事情基本是常量定义。
  • 接口的静态常量往往有其他的用途。

很少有人会在枚举设计复杂的逻辑,因为枚举的可扩展性很差并且理解和学习成本较高

17. 按作用域划分成员变量

The best practice to organize member variables of a class by their scopes from most restrictive to least restrictive.

最好的做法是按其作用域从最严格到最不严格来组织一个类的成员变量。


public class StudentManager {
    protected List<Student> listStudents;
    public int numberOfStudents;
    private String errorMessage;
    float rowHeight;
    float columnWidth;
    protected String[] columnNames;
    private int numberOfRows;
    private int numberOfColumns;
    public String title;
}

上面的成员变量定义眼花缭乱,通过作用域划分如下:


public class StudentManager {
    private String errorMessage;
    private int numberOfColumns;
    private int numberOfRows;
    float columnWidth;
    float rowHeight;
    protected String[] columnNames;
    protected List<Student> listStudents;
    public int numberOfStudents;
    public String title;
}

18. 在数字字段中使用下划线【建议】

来自Java 7的小更新可以帮助我们把冗长的数字字段写得更易读。


int maxUploadSize = 20971520;
long accountBalance = 1000000000000L;
float pi = 3.141592653589F;

和下面的代码作比较:


int maxUploadSize = 20_971_520;
long accountBalance = 1_000_000_000_000L;
float pi = 3.141_592_653_589F。

哪一个更易懂?记得在数字字面中使用下划线,以提高代码的可读性。

个人:尴尬,学了这么多年Java居然不知道有这种写法.....

总结

这里罗列一下存在争议以及印象比较深的部分:

  • StringBuilder替换字符串拼接。如果单纯拼接几个变量或者方法的结果,"+"号是完全没有问题的。
  • 虽然JDK 9 对于每次for循环new StringBuilder的BUG做了修复,但国内广泛使用JDK8的场景下依然需要避免for循环大量的字符串拼接。
  • 这种优化不是关键,请更加关注合理的架构设计,因为这一点性能损耗对于现代处理器影响真的不大。
  • 如果不需要考虑多线程的情况,更建议使用StringBuffer。
  • 精度选择,实际上不管有没有精度要求,碰到需要小数的运算建议使用BigDecimal,因为double和float的数学运算真的很容易出问题。
  • 注释
  • 训练写出易懂的代码而不是易懂的注释
  • 注释应该遵从KISS。“愚蠢”的代码最好理解。
  • 在大型的数字参数值中使用下划线,这是一个很容易忽略的Java小技巧,对于和金额有关的处理,这种写法非常有帮助。

参考

另一位读者:Best coding practices every Java developer should follow?

10 Java Core Best Practices Every Java Programmer Should Know

相关文章
|
11天前
|
Java Maven Android开发
【Azure Developer】VS Code打包Java maven Project 遇见 BUILD FAILURE
Unknown lifecycle phase "lean". You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>
|
3月前
|
Java 开发工具
【Azure Developer】Java代码访问Key Vault Secret时候的认证问题,使用 DefaultAzureCredentialBuilder 或者 ClientSecretCredentialBuilder
【Azure Developer】Java代码访问Key Vault Secret时候的认证问题,使用 DefaultAzureCredentialBuilder 或者 ClientSecretCredentialBuilder
|
3月前
|
Java Windows
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
|
3月前
|
Java Maven C++
【Azure Developer】记录一次使用Java Azure Key Vault Secret示例代码生成的Jar包,单独运行出现 no main manifest attribute, in target/demo-1.0-SNAPSHOT.jar 错误消息
【Azure Developer】记录一次使用Java Azure Key Vault Secret示例代码生成的Jar包,单独运行出现 no main manifest attribute, in target/demo-1.0-SNAPSHOT.jar 错误消息
|
3月前
|
开发工具 数据安全/隐私保护
【Azure Developer】使用MSAL4J 与 ADAL4J 的SDK时候,遇见了类型冲突问题 "java.util.Collections$SingletonList cannot be cast to java.lang.String"
【Azure Developer】使用MSAL4J 与 ADAL4J 的SDK时候,遇见了类型冲突问题 "java.util.Collections$SingletonList cannot be cast to java.lang.String"
|
3月前
|
Java API 数据安全/隐私保护
【Azure Developer】使用 adal4j(Azure Active Directory authentication library for Java)如何来获取Token呢 (通过用户名和密码方式获取Access Token)
【Azure Developer】使用 adal4j(Azure Active Directory authentication library for Java)如何来获取Token呢 (通过用户名和密码方式获取Access Token)
|
3月前
|
固态存储 Java 网络安全
【Azure Developer】使用Java SDK代码创建Azure VM (包含设置NSG,及添加数据磁盘SSD)
【Azure Developer】使用Java SDK代码创建Azure VM (包含设置NSG,及添加数据磁盘SSD)
|
3月前
|
Java 数据安全/隐私保护 Windows
【Azure Developer】使用Java代码启动Azure VM(虚拟机)
【Azure Developer】使用Java代码启动Azure VM(虚拟机)
|
3月前
|
存储 Java API
【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率
【Azure Developer】通过Azure提供的Azue Java JDK 查询虚拟机的CPU使用率和内存使用率
|
3月前
|
存储 Java 开发工具
【Azure Developer】VS Code运行Java 版Azure Storage SDK操作Blob (新建Container, 上传Blob文件,下载及清理)
【Azure Developer】VS Code运行Java 版Azure Storage SDK操作Blob (新建Container, 上传Blob文件,下载及清理)