java开发时各类工具的使用规范

工具类规范

一个项目不可能没有工具类,工具类的初衷是良好的,代码重用,但到了后面工具类越来越乱,有些项目工具类有几十个,看的眼花缭乱,还有不少重复。如何编写出好的工具类,我有几点建议:

隐藏实现

就是要定义自己的工具类,尽量不要在业务代码里面直接调用第三方的工具类。这也是解耦的一种体现。如果我们不定义自己的工具类而是直接使用第三方的工具类有2个不好的地方:

  1. 不同的人会使用不同的第三方工具库,会比较乱。
  2. 将来万一要修改工具类的实现逻辑会很痛苦。

以最简单的字符串判空为例,很多工具库都有 StringUtils工具类,如果我们使用commons的工具类,一开始我们直接使用StringUtils.isEmpty,字符串为空或者空串的时候会返回为true,后面业务改动,需要改成如果全部是空格的时候也会返回true,怎么办?我们可以改成使用StringUtils.isBlank。看上去很简单,对吧? 如果你有几十个文件都调用了,那我们要改几十个文件,是不是有点恶心?再后面发现,不只是英文空格,如果是全角的空格,也要返回为true,怎么办?StringUtils上的方法已经不能满足我们的需求了,真不好改了。。。

所以我的建议是,一开始就自己定义一个自己项目的StringUtil,里面如果不想自己写实现,可以直接调用commons的方法,如下:

public static boolean isEmpty(String str) {
 return org.apache.commons.lang3.StringUtils.isEmpty(str);
}

后面全部空格也返回true的时候,我们只需要把isEmpty改成isBlank;再后面全部全角空格的时候也返回true的话,我们增加自己的逻辑即可。我们只需要改动和测试一个地方。

在举一个真实一点的例子,如复制对象的属性方法。

一开始,如果我们自己不定义工具类方法,那么我们可以使用org.springframework.beans.BeanUtils.copyProperties(source, dest)这个工具类来实现,就一行代码,和调用自己的工具类没有什么区别。看上去很OK,对吧?

随着业务发展,我们发现这个方式的性能或者某些特性不符合我们要求,我们需要修改改成commons-beanutils包里面的方法,org.apache.commons.beanutils.BeanUtils.copyProperties(dest, source),这个时候问题来了,第一个问题,它的方法的参数顺序和之前spring的工具类是相反的,改起来非常容易出错!第二个问题,这个方法有异常抛出,必须声明,这个改起来可要命了!结果你发现,一个看上去很小的改动,改了几十个文件,每个改动还得测试一次,风险不是那么得小。有一点小奔溃了,是不是?

等你改完之后测试完了,突然有一天需要改成,复制参数的时候,有些特殊字段需要保留(如对象id)或者需要过滤掉(如密码)不复制,怎么办?这个时候我估计你要崩溃了吧?不要觉得我是凭空想象,编程活久见,你总会遇到的一天!

所以,我们需要定义自己的工具类函数,一开始我定义成这样子。

public void copyAttribute(Object source, Object dest) {

 org.springframework.beans.BeanUtils.copyProperties(source, dest);

}

后面需要修改为commons-beanutis的时候,我们改成这样即可,把参数顺序掉过来,然后处理了一下异常,我使用的是Lombok的SneakyThrows来处理异常,你也可以捕获掉抛出运行时异常,个人喜好。

@SneakyThrows
public void copyAttribute(Object source, Object dest) {
 org.apache.commons.beanutils.BeanUtils.copyProperties(dest, source);
}

再后面,复制属性的时候需要保留某些字段或者过滤掉某些字段,我们自己参考其他库实现一次即可,只改动价格和测试一个文件一个方法,风险非常可控。

还记得我之前的帖子里说的需求变更吗?你可以认为这算需求变更,但同样的需求变更,我一个小时改完测试,没有任何风险轻轻松松上线,你可能满头大汗加班加点还担心出问题。。。

使用父类/接口

上面那点隐藏实现,说到底是封装/解耦的思想,而现在说的这点是抽象的思想,做好了这点,我们就能编写出看上去很专业的工具类。这点很好理解,但是我们容易忽略。

举例,假设我们写了一个判断arraylist是否为空的函数,一开始是这样的。

public static boolean isEmpty(ArrayList<?> list) {
 return list == null || list.size() == 0;
}

这个时候,我们需要思考一下参数的类型能不能使用父类。我们看到我们只用了size方法,我们可以知道size方法再list接口上有,于是我们修改成这样。

public static boolean isEmpty(List<?> list) {
 return list == null || list.size() == 0;
}

后面发现,size方法再list的父类/接口Collection上也有,那么我们可以修改为最终这样。

public static boolean isEmpty(Collection<?> list) {
 return list == null || list.size() == 0;
}

到了这部,Collection没有父类/接口有size方法了,修改就结束了。最后我们需要把参数名字改一下,不要再使用list。改完后,所有实现了Collection都对象都可以用,最终版本如下:

public static boolean isEmpty(Collection<?> collection) {
 return collection == null || collection.size() == 0;
}

是不是看上去通用多了 ,看上去也专业多了?上面的string相关的工具类方法,使用相同的思路,我们最终修改一下,把参数类类型由String修改为CharSequence,参数名str修改为cs。如下:

public static boolean isEmpty(CharSequence cs) {
 return org.apache.commons.lang3.StringUtils.isEmpty(cs);
}

思路和方法很简单,但效果很好,写出来的工具类也显得很专业!总结一下,思路是抽象的思想,主要是修改参数类型,方法就是往上找父类/接口,一直找到顶为止,记得修改参数名。

使用重载编写衍生函数组

开发过的兄弟都知道,有一些工具库,有一堆的重载函数,调用起来非常方便,经常能直接调用,不需要做参数转换。这些是怎么样编写出来的呢?我们举例说明。

现在需要编写一个方法,输入是一个utf-8格式的文件的文件名,把里面内容输出到一个list。我们刚刚开始编写的时候,是这个样子的

public static List<String> readFile2List(String filename) throws IOException {
 List<String> list = new ArrayList<String>();

 File file = new File(filename);

 FileInputStream fileInputStream = new FileInputStream(file);

 BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream,
 "UTF-8"));

 // XXX操作

 return list;
}

我们先实现,实现完之后我们做第一个修改,很明显,utf-8格式是很可能要改的,所以我们先把它做为参数提取出去,方法一拆为二,就变成这样。

public static List<String> readFile2List(String filename) throws IOException {
 return readFile2List(filename, "UTF-8");
}

public static List<String> readFile2List(String filename, String charset)
 throws IOException {
 List<String> list = new ArrayList<String>();

 File file = new File(filename);
 FileInputStream fileInputStream = new FileInputStream(file);

 BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream,
 charset));

 // XXX操作

 return list;
}

多了一个方法,直接调用之前的方法主体,主要的代码还是只有一份,之前的调用地方不需要做任何修改!可以放心修改。

然后我们在看里面的实现,下面这2行代码里面,String类型的filename会变化为File类型,然后在变化为FileInputStream 类型之后才使用。

File file = new File(filename);
FileInputStream fileInputStream = new FileInputStream(file);

这里我们就应该想到,用户可能直接传如File类型,也可能直接传入FileInputStream类型,我们应该都需要支持,而不需要用户自己做类型的处理!在结合上一点的使用父类,把FileInputStream改成父类InputStream,我们最终的方法组如下:

package plm.common.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.IOUtils;

/**
 * 工具类编写范例,使用重载编写不同参数类型的函数组
 *
 * @author 晓风轻 https://github.com/xwjie/PLMCodeTemplate
 *
 */
public class FileUtil {

 private static final String DEFAULT_CHARSET = "UTF-8";

 public static List<String> readFile2List(String filename) throws IOException {
 return readFile2List(filename, DEFAULT_CHARSET);
 }

 public static List<String> readFile2List(String filename, String charset)
 throws IOException {
 FileInputStream fileInputStream = new FileInputStream(filename);
 return readFile2List(fileInputStream, charset);
 }

 public static List<String> readFile2List(File file) throws IOException {
 return readFile2List(file, DEFAULT_CHARSET);
 }

 public static List<String> readFile2List(File file, String charset)
 throws IOException {
 FileInputStream fileInputStream = new FileInputStream(file);
 return readFile2List(fileInputStream, charset);
 }

 public static List<String> readFile2List(InputStream fileInputStream)
 throws IOException {
 return readFile2List(fileInputStream, DEFAULT_CHARSET);
 }

 public static List<String> readFile2List(InputStream inputStream, String charset)
 throws IOException {
 List<String> list = new ArrayList<String>();

 BufferedReader br = null;
 try {
 br = new BufferedReader(new InputStreamReader(inputStream, charset));

 String s = null;
 while ((s = br.readLine()) != null) {
 list.add(s);
 }
 } finally {
 IOUtils.closeQuietly(br);
 }

 return list;
 }

}

怎么样?6个方法,实际上代码主体只有一份,但提供各种类型的入参,调用起来很方便。开发组长编写的时候,多费一点点时间,就能写来看上去很专业调用起来很方便的代码。如果开发组长不写好,开发人员发现现有的方法只能传String,她要传的是InputStream,她又不敢改原来的代码,就会copy一份然后修改一下,就多了一份重复代码。代码就是这样烂下去了。。。

关键点,多想一步,根据参数变化编写各种类型的入参函数,需要保证函数主要代码只有一份。

使用静态引入

工具类的一个问题就是容易泛滥,主要原因是开发人员找不到自己要用的方法,就自己写一个,开发人员很难记住类名,你也不可能天天代码评审。

所以要让开发人员容易找到,我们可以使用静态引入,在Eclipse里面这样导入:

物理上独立存放

这点是我的习惯,我习惯把和业务无关的代码放到独立的工程或者目录,在物理上要分开,专人维护。不是所有人都有能力写工具类,独立存放专门维护,专门的权限控制有助于保证代码的纯洁和质量。这样普通的开发人员就不会随意修改。

例如我的范例工程里面,专门建立了一个source目录存放框架代码,工具类也在里面,这里的代码,只有我一个人会去修改:

总结

几乎所有人都知道面向对象的思想有抽象封装,但几个人真正能做到,其实有心的话,处处都能体现出这些思想。编写工具类的时候需要注意参数的优化,而且大型项目里面不要在业务代码里面直接调用第三方的工具类,然后就是多想一步多走一步,考虑各种类型的入参,这样你也能编写出专业灵活的工具类!

到此这篇关于java开发时各类工具的使用规范的文章就介绍到这了,更多相关java编码时工具的使用规范内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JAVA 16位ID生成工具类含16位不重复的随机数数字+大小写

    本文介绍了Java随机数,分享给大家,也顺便做个笔记 package com.fty.util; import java.security.SecureRandom; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; public class UtilId { /** * 生成16位不重复的随机数,含数字+大小写 * @return */ public static String getGUID() {

  • Java业务校验工具实现方法

    一.背景 在我们日常接口开发过程中,可能要面对一些稍微复杂一些的业务逻辑代码的编写,在执行真正的业务逻辑前,往往要进行一系列的前期校验工作,校验可以分为参数合法性校验和业务数据校验. 参数合法性校验比如最常见的校验参数值非空校验.格式校验.最大值最小值校验等,可以通过Hibernate Validator框架实现,本文不具体讲解.业务数据校验通常与实际业务相关,比如提交订单接口,我们可能需要校验商品是否合法.库存是否足够.客户余额是否足够.还有其他的一些风控校验.我们的代码可能看起来像是这样的:

  • windows环境下java开发工具maven的安装教程图解

    Maven是什么? Maven是一个项目管理和综合工具.Maven提供了开发人员构建一个完整的生命周期框架.开发团队可以自动完成项目的基础工具建设,Maven使用标准的目录结构和默认构建生命周期. 在多个开发团队环境时,Maven可以设置按标准在非常短的时间里完成配置工作.由于大部分项目的设置都很简单,并且可重复使用,Maven让开发人员的工作更轻松,同时创建报表,检查,构建和测试自动化设置 maven是java项目依赖管理和构建工具,有了maven可以让java项目开发和构建更加便捷和高效,是

  • Java http请求封装工具类代码实例

    java实现http请求的方法常用有两种,一种则是通过java自带的标准类HttpURLConnection去实现,另一种是通过apache的httpclient去实现. 本文用httpclient去实现,需要导入httpclient和httpcore两个jar包,测试时用的httpclient-4.5.1和httpcore-4.4.3. HttpMethod.java package demo; public enum HttpMethod { GET, POST; } HttpHeader.

  • Java工具类BeanUtils库介绍及实例详解

    BeanUtils工具由Apache软件基金组织编写,提供给我们使用,主要解决的问题是:把对象的属性数据封装到对象中. 在整个J2EE的编程过程中,我们经常会从各种配置文件中读取相应的数据,需要明白的一点是从配置文件中读取到的数据都是String,但是很显然我们的应用程序中不仅仅有String一种数据类型,比如:基本数据类型(int.double.char.float等),还有自定义数据类型(引用数据类型), 那么我们必须面临的一个问题就是讲字符串类型转换为各种具体的数据类型,该怎么办呢? 有两

  • Java并发工具辅助类代码实例

    java中的并发工具类 一:等待多线程完成的CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成操作. package com.fuzhulei; import java.util.concurrent.*; ​ /** * 减法计数器,主要是countDown(计数器1) 和 await(阻塞)方法,只有当计数器减为0的时候,当前线程才可以往下继续执行. * 主要用于允许一个或多个线程等待其他线程完成操作 * @author Huxudong * @cr

  • Java常用类库Apache Commons工具类说明及使用实例详解

    Apache Commons包含了很多开源的工具,用于解决平时编程经常会遇到的问题,减少重复劳动.下面是我这几年做开发过程中自己用过的工具类做简单介绍. 组件 功能介绍 BeanUtils 提供了对于JavaBean进行各种操作,克隆对象,属性等等. Betwixt XML与Java对象之间相互转换. Codec 处理常用的编码方法的工具类包 例如DES.SHA1.MD5.Base64等. Collections java集合框架操作. Compress java提供文件打包 压缩类库. Con

  • java开发时各类工具的使用规范

    工具类规范 一个项目不可能没有工具类,工具类的初衷是良好的,代码重用,但到了后面工具类越来越乱,有些项目工具类有几十个,看的眼花缭乱,还有不少重复.如何编写出好的工具类,我有几点建议: 隐藏实现 就是要定义自己的工具类,尽量不要在业务代码里面直接调用第三方的工具类.这也是解耦的一种体现.如果我们不定义自己的工具类而是直接使用第三方的工具类有2个不好的地方: 不同的人会使用不同的第三方工具库,会比较乱. 将来万一要修改工具类的实现逻辑会很痛苦. 以最简单的字符串判空为例,很多工具库都有 Strin

  • [JAVA]十四种Java开发工具点评

    在计算机开发语言的历史中,从来没有哪种语言象Java那样受到如此众多厂商的支持,有如此多的开发工具,Java菜鸟们如初入大观园的刘姥姥,看花了眼,不知该何种选择.的确,这些工具各有所长,都没有绝对完美的,就算是老鸟也很难做出选择.在本文中我简要介绍了常见的十四种Java开发工具的特点,管中窥"器",希望能对大家有所帮助. 1.JDK (Java Development Kit) 2.Java Workshop 3.NetBeans 与Sun Java Studio 5 4.Borlan

  • Java开发工具IntelliJ IDEA安装图解

    这篇文章主要介绍了Java开发工具IntelliJ IDEA安装图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 > 开发工具概述 IDEA是一个专门针对Java的集成开发工具(IDE),由Java语言编写.所以,需要有JRE运行环境并配置好环境变量. 它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中,使用的就是IDEA进行开发. IDEA软件安装 进入官网http://www.jetbrains.com/选择需要的版本下载.

  • 使用spring boot开发时java对象和Json对象转换的问题

    将java对象转换为json对象,市面上有很多第三方jar包,如下: jackson(最常用) <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind&l

  • 推荐两款java开发实用工具 hutool 和 lombok

    一.hutool工具 摘抄一段hutool工具的简介: Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,是项目中"util"包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务. hutool-aop JDK动态代理封装,提供非IOC下的切面支持 hutool-bloomFilter 布隆过滤,提供一些Hash算法的布隆过滤 hutool-cache 简单缓存实现 hutool-core 核心,包括Bean操作.

  • 一文掌握Java开发工具Maven(简单上手)

    Maven 如果作为一个Java程序员,那么在日常的开发过程中,maven是很常见的项目构建工具.maven可以极大的提高我们的开发效率,帮助我们简化开发过程中一些解决依赖和项目部署的相关问题,所以学习掌握maven的相关知识是非常有必要的. 本文从入门安装开始,逐步深入讲解maven的相关知识. 1.安装maven 首先我们需要准备好安装包,这里推荐在官网下载:maven官网下载地址 我这里下载的是3.8.1版本的maven,不同版本的maven配置过程基本是一样的. 1.1 Windows安

  • 提升java开发效率工具lombok使用争议

    目录 引言 什么是 lombok 如何使用 lombok 的原理和滥用 引言 对使用 lombok 还是有很多争议的,有些公司不建议使用,有些公司又大量使用. 我们的想法是:可以使用,但是不要滥用. 什么是 lombok Lombok是 一种Java™实用工具,可用来帮助开发人员消除Java的冗长代码,尤其是对于简单的Java对象(POJO) . 它通过注释实现这一目的. 通过在开发环境中实现Lombok,开发人员可以节省构建诸如hashCode() 和 equals()这样的方法以及以往用来分

  • Java开发工具Eclipse使用技巧全局搜索和更替

    本文研究的主要是Eclipse中全局搜索和更替,下面看看具体操作方法. Eclipse全局搜索步骤 使用快捷键"ctrl+H"打开文件搜索对话框,选择"File Search"标签,在Containing text中输入你需要搜索的字符串,在Scope中,选择你要搜索的范围,点击Search. 在Search视图中,会列出搜索得到的结果,点击打开属性结构.双击搜索结构,就会显示源代码中的搜索结果. Eclipse全局替换步骤 在全局搜索到目标字符串后,在Search

  • 零基础学Java:Java开发工具 Eclipse 安装过程创建第一个Java项目及Eclipse的一些基础使用技巧

    一.下载https://www.eclipse.org/downloads/download.php?file=/oomph/epp/2020-06/R/eclipse-inst-win64.exe&mirror_id=1142 二.安装Eclipse 三.开始使用Eclipse,并创建第一个Java项目 src 鼠标右键 -- New --Class 四.一些基础操作 1.字体大小修改(咋一看感觉这字体太小了,看起来不舒服) Window -- Preferences 2.项目运行 3.当一些

随机推荐