请选择 进入手机版 | 继续访问电脑版

热点推荐

查看: 33|回复: 0

【java源码】有了它,Java语法也可以变得甜甜的

[复制链接]
  • TA的每日心情
    开心
    15 小时前
  • 签到天数: 133 天

    [LV.7]常住居民III

    4347

    主题

    4357

    帖子

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    16743
    发表于 2019-12-12 01:40:37 | 显示全部楼层 |阅读模式
    简介【Java吧推荐 www.java8.com
    Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。
    Hutool中的工具方法来自于每个用户的精雕细琢,它涵盖了Java开发底层代码中的方方面面,它既是大型项目开发中解决小问题的利器,也是小型项目中的效率担当;
    Hutool是项目中“util”包友好的替代,它节省了开发人员对项目中公用类和公用工具方法的封装时间,使开发专注于业务,同时可以最大限度的避免封装不完善带来的bug。
    这是官方对它的介绍,简单点说,它通过一些封装,将原来略显复杂的API进一步优化,使得你在使用的时候能够更加方便快捷,当然语法也会比原来更加简单易懂。
    包含组件
    一个Java基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类,同时提供以下组件:







    可以根据需求对每个模块单独引入,也可以通过引入hutool-all方式引入所有模块。
    安装1、Maven项目
    在项目的pom.xml的dependencies中加入以下内容:
    <dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.0.7</version>
    </dependency>2、非Maven项目


    下载hutool-all-X.X.X.jar即可。
    下面对某几个组件的使用进行一个入门。
    类型转换
    1、常用类型转换
    在传统的类型转换过程中,我们需要使用到包装类的valueof()方法,例如:




    但很显然实际情况并没有这么简单,在企业级的开发项目中,从前端传递过来的参数各式各样,类型繁多,我们如何知晓参数类型并作对应的转换呢?一般会先将所有参数转成String类型,如Web中的HttpServletRequest的getParamer()方法得到的数据类型就永远是String。转成String之后再将参数转成对应的数据类型,此时还需要考虑转换异常的问题,所以通常还需要在转换代码外面使用try-catch。
    为了使转换过程变得轻松愉快,HuTool为我们提供了类型转换工具——Convert。
    来看看使用Convert该如何进行转换:
    String s = "1234";
    int num = Convert.toInt(s);
    double d = Convert.toDouble(s);
    float f = Convert.toFloat(s);
    首先在代码风格上,Convert作了一个统一,统一使用Convert类作为工具类进行类型转换,而无需使用每个类型对应的包装类。
    当然了,Convert类的作用可远不止如此,比如:
    String[] s = { "1", "2", "3", "4", "5" };
    Integer[] intArray = Convert.toIntArray(s);
    Double[] doubleArray = Convert.toDoubleArray(s);
    Float[] floatArray = Convert.toFloatArray(s);
    Character[] charArray = Convert.toCharArray(s);
    将数组转换为任意类型的数组。
    对于集合,Convert同样支持转换:
    Object[] objs= {"hello","world","java",1};
    List<?> list = Convert.toList(objs);
    还有日期类型:
    String s = "2019-12-07";
    Date date = Convert.toDate(s);
    关于日期的处理,HuTool为我们提供了专门的工具类,这个我们放到后面说。
    2、其它类型转换
    通过Convert的convert()方法也能够实现上述的所有操作,不信我们可以试一试:
    String s = "1234";
    int num = Convert.convert(Integer.class, s);
    double d = Convert.convert(Double.class, s);
    float f = Convert.convert(Float.class, s);
    关于其它类型大家可以自己试一试,总之,通过convert()方法可以将任意类型转换为指定类型,但这种方法终归是有局限的,试问一下,我们如何将一个数组转换成List类型呢?
    我们可以通过一个重载方法convert( TypeReference reference, Object value ),该方法需要一个TypeReference对象参数,我们就可以创建TypeReference对象并通过嵌套泛型来指定需要转换的类型,比如:
    Object[] objs = { "hello", "world", "java"};
    List<String> list = Convert.convert(new TypeReference<List<String>>() {}, objs);
    Convert还提供了全角与半角符号之间的转换,比如:
    //将全角符转为半角符
    String s = "1,2,3,4,5";
    String dbc = Convert.toDBC(s);
    //将半角符转为全角符
    String sbc = Convert.toSBC(dbc);
    可以看看运行结果,更加直观:


    3、编码转换
    在一些场景下,比如表单提交,会将参数进行一个简单的加密,此时通常会使用16进制转换,当然了,我们在准备16进制转换的时候也不会自己去写,都是去百度找一个现成的。不过,有了HuTool就不需要了,它为我们提供了方法用于完成16进制的转换。
    String s = "你好世界";
    //转换为16进制字符串
    String hex = Convert.toHex(s, CharsetUtil.CHARSET_UTF_8);
    //转换为普通字符串
    String str = Convert.hexToStr(hex, CharsetUtil.CHARSET_UTF_8);
    运行结果:
    e4bda0e5a5bde4b896e7958c
    你好世界
    注意编码对象要相同,这里都使用UTF-8编码,所以顺逆的转换过程都是成功的,如果编码不同,在转为普通字符串的时候就会出现乱码。
    还有Unicode编码和字符串的转换:
    String s = "你好世界";
    //转换为Unicode编码
    String unicode = Convert.strToUnicode(s);
    //转换为普通字符串
    String str = Convert.unicodeToStr(unicode);
    运行结果:
    \\u4f60\\u597d\\u4e16\\u754c
    你好世界
    Convert类还提供了convertCharset ()用于将字符串转换为指定编码的字符串,比如在处理表单数据时通常要处理乱码问题,如下:
    String s = "你好世界";
    //将字符串先转成乱码
    String str = Convert.convertCharset(s, CharsetUtil.UTF_8, CharsetUtil.ISO_8859_1);
    //处理乱码
    String result = Convert.convertCharset(str, CharsetUtil.ISO_8859_1, CharsetUtil.UTF_8);
    运行结果:
    ????????????
    你好世界
    还有金额大小写转换的功能:
    double money = 2019.127;
    String s = Convert.digitToChinese(money);
    运行结果:
    贰仟零壹拾玖元壹角叁分
    4、自定义类型转换
    Convert类的功能是不是非常强大呢?我们继续来看,对于数据类型转换,肯定是做不到包含所有数据类型的,因为Java面向对象的特性,但是HuTool提供了自定义类型转换。
    ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
    converterRegistry.putCustom(Person.class, CustomConverter.class);
    String[] str = { "20", "张三" };
    Person person = converterRegistry.convert(Person.class, str);
    System.out.println(person);
    运行结果:
    Person [age=20, name=张三
    该转换器将一个数组类型转换为了Person对象,它是如何实现的呢?(分三步)
    • 自定义类实现Converter接口,并重写convert()方法
    • 注册自定义的转换器
    • 实现转换
    先定义一个Person类:
    public class Person {

            private int age;
            private String name;

            public int getAge() {
                    return age;
            }

            public void setAge(int age) {
                    this.age = age;
            }

            public String getName() {
                    return name;
            }

            public void setName(String name) {
                    this.name = name;
            }

            @Override
            public String toString() {
                    return "Person [age=" + age + ", name=" + name + "]";
            }
    }
    然后自定义类实现Converter接口,并重写方法:
    public class CustomConverter implements Converter<Person> {

            @Override
            public Person convert(Object value, Person person) throws IllegalArgumentException {
                    person = new Person();
                    String[] str = Convert.toStrArray(value);
                    person.setAge(Convert.toInt(str[0]));
                    person.setName(str[1]);
                    return person;
            }
    }
    该方法将传递过来的数据封装成Person对象并返回,实现类型转换。
    接着注册自定义的转换器:
    ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
    converterRegistry.putCustom(Person.class, CustomConverter.class);
    现在就可以使用我们的转换器了,也就是刚刚的代码:
    String[] str = { "20", "张三" };
    Person person = converterRegistry.convert(Person.class, str);
    System.out.println(person);
    需要转换的数据是什么样式的,完全由你自定义的转换器决定,非常灵活,可根据自己的需求随意定制。
    日期时间处理
    对于日期时间的处理,Java提供了Date类和Calendar类,但就是因为有了更多的选择,使得日期时间转换的操作变得混乱和复杂,为此,HuTool提供了DateUtil工具。
    1、Date、long、Calendar的相互转换
    使用DateUtil可以实现Date、long和Calendar之间的相互转换,如下:
    // Calendar转为Date
    Date date = DateUtil.date(Calendar.getInstance());
    // long转为Date
    Date date2 = DateUtil.date(System.currentTimeMillis());
    // Date转为Calendar
    Calendar calendar = DateUtil.calendar(date);
    // long转为Calendar
    Calendar calendar2 = DateUtil.calendar(System.currentTimeMillis());
    2、日期字符串转换为Date
    String s = "2019-12-07";
    DateTime dateTime = DateUtil.parse(s);
    System.out.println(dateTime);
    运行结果:
    2019-12-07 00:00:00
    该方法能够将日期字符串转换为Date类型,它能够自动识别以下格式的字符串:
    • yyyy-MM-dd HH:mm:ss
    • yyyy-MM-dd
    • HH:mm:ss
    • yyyy-MM-dd HH:mm
    • yyyy-MM-dd HH:mm:ss.SSS
    3、格式化日期
    格式化日期很简单,和Java的API没什么区别。
    String s = "2019-12-07";
    DateTime date = DateUtil.parse(s);

    String dateStr = DateUtil.format(date, "yyyy/MM/dd");
    System.out.println(dateStr);
    String dateStr2 = DateUtil.formatDate(date);
    System.out.println(dateStr2);
    String dateStr3 = DateUtil.formatDateTime(date);
    System.out.println(dateStr3);
    String dateStr4 = DateUtil.formatTime(date);
    System.out.println(dateStr4);
    通过format()方法可以将日期字符串转换为指定的格式,不过,DateUtil提供了其它的一些方法来作为常用的日期格式转换,看运行结果即可:
    2019/12/07
    2019-12-07
    2019-12-07 00:00:00
    00:00:00
    4、获取年、月、日
    对于年、月、日的获取,DateUtil也提供了非常简便的获取方式:
    // 获取当前日期时间
    DateTime date = DateUtil.date();
    System.out.println(date);
    // 获取年
    int year = DateUtil.year(date);
    System.out.println(year);
    // 获取月        从0开始
    int month = DateUtil.month(date);       
    System.out.println(month);
    运行结果:
    2019-12-07 21:45:42
    2019
    11
    5、日期时间偏移量
    对于日期时间的偏移,DateUtil同样能够很方便地实现,如下:
    String s = "2019-12-06 21:46:00";
    DateTime date = DateUtil.parse(s);

    // 日期往后偏移一天
    DateTime dateTime = DateUtil.offset(date, DateField.DAY_OF_MONTH, 1);
    System.out.println(dateTime);

    // 日期往后偏移两天
    DateTime dateTime2 = DateUtil.offsetDay(dateTime, 2);
    System.out.println(dateTime2);

    // 日期往后偏移一个小时
    DateTime dateTime3 = DateUtil.offsetHour(date, 1);
    System.out.println(dateTime3);
    运行结果:
    2019-12-07 21:46:00
    2019-12-09 21:46:00
    2019-12-06 22:46:00
    关于日期时间的偏移,通过offset()方法即可实现,该方法的第二个参数可传入偏移的单位,不过DateUtil还提供了一些比较常用的偏移方法,比如偏移天数、偏移小时。
    对于与当前十分接近的日期时间,DateUtil也提供了一些较为常用的方法,比如昨天、明天、上周、下周、上个月、下个月等:
    DateTime yesrerday = DateUtil.yesterday();
    System.out.println(yesrerday);
                   
    DateTime tomorrow = DateUtil.tomorrow();
    System.out.println(tomorrow);
                   
    DateTime lastMonth = DateUtil.lastMonth();
    System.out.println(lastMonth);
                   
    DateTime nextMonth = DateUtil.nextMonth();
    System.out.println(nextMonth);
                   
    DateTime lastWeek = DateUtil.lastWeek();
    System.out.println(lastWeek);
                   
    DateTime nextWeek = DateUtil.nextWeek();
    System.out.println(nextWeek);
    运行结果:
    2019-12-06 22:02:29
    2019-12-08 22:02:29
    2019-11-07 22:02:29
    2020-01-07 22:02:29
    2019-11-30 22:02:29
    2019-12-14 22:02:29
    6、计算日期时间差
    String s1 = "2019-12-06 22:15:00";
    DateTime date1 = DateUtil.parse(s1);
    String s2 = "2019-12-08 22:15:00";
    DateTime date2 = DateUtil.parse(s2);
    // 计算相差的天数
    long day = DateUtil.between(date1, date2, DateUnit.DAY);
    System.out.println(day);
    // 计算相差的小时数
    long hour = DateUtil.between(date1, date2, DateUnit.HOUR);
    System.out.println(hour);
    运行结果:
    2
    48
    对于两个日期时间的差值,通过between()方法能够很轻松地得到,该方法的第三个参数是需要计算的差值的单位。
    7、计时器
    DateUtil类还封装了计时器功能,用过传统的Timer计时器的同学就会知道,Timer计时器略显复杂,而DateUtil的封装则恰到好处。
    TimeInterval timer = DateUtil.timer();
    // 延迟2秒
    Thread.sleep(2000);
    // 花费的时间,单位:毫秒
    long interval = timer.interval();
    System.out.println(interval);
    // 花费的时间,单位:分
    long intervalMinute = timer.intervalMinute();
    System.out.println(intervalMinute);
    运行结果:
    2000
    0
    还有很多其它的方法,篇幅有限,就不一一例举了。
    8、其它
    考虑到一些比较常见的场景,例如计算一个人的年龄,判断给定年份是否为闰年,DateUtil也给出了相应的解决办法。
    int age = DateUtil.ageOfNow("1999-08-08");
    System.out.println(age);
    boolean leapYear = DateUtil.isLeapYear(2019);
    System.out.println(leapYear);
    运行结果:
    20
    falseIO操作
    IO操作是Java中比较重要的操作之一,为此,Java提供了InputStream、OutputStream、Reader、Writer等接口,而实现类又非常的多,往往选择一多,我们就不知道该如何选择,而HuTool为我们封装了一系列的工具类。
    FileUtil(文件操作工具类)
    既然是IO流,那就离不开文件操作,HuTool为我们提供了FileUtil工具类用来解决大部分的文件操作问题。
    对于文件操作的方法,有Linux基础的同学肯定非常熟悉,开源项目的作者努力将方法名与Linux保持一致,比如创建文件的方法不是createFile()而是touch()。
    File[] files = FileUtil.ls("E:");
    for (File file : files) {
            System.out.println(file);
    }
    运行结果:
    E:\$RECYCLE.BIN
    E:\androidSdk
    E:\androidstudio
    E:\b2631f36a0808f7d3cab19543d645e63
    E:\flutter
    E:\Java
    E:\MailMasterData
    E:\QLDownload
    E:\QQPCmg
    E:\QQPCmgr
    E:\qycache
    E:\System Volume Information
    E:\test.txt
    E:\Tool
    E:\迅雷下载
    ls()方法会列出给定路径下的所有目录和文件。
    FileUtil.touch("E:/test/hello.txt");
    touch()方法用于创建文件,如果父目录不存在也自动创建,比如这里的hello.txt文件,倘若E盘下没有test目录,则会先创建test文件夹,再在test目录下创建hello.txt文件。
    其它方法也如上所示使用,就不一一演示了:
    • mkdir 创建目录,会递归创建每层目录
    • del 删除文件或目录(递归删除,不判断是否为空),这个方法相当于Linux的delete命令
    • copy 拷贝文件或目录
    注意:对于del()方法,它会直接删除目录而不判断其是否为空,所以请谨慎使用。
    IOUtil(IO工具类)
    第二个便是IOUtil,该工具类主要针对输入输出流的一个封装。
    1、文件复制
    针对文件复制操作,IOUtil能够很轻松地完成。
    BufferedInputStream inputStream = FileUtil.getInputStream("C:/Users/Administrator/Desktop/eclipseworkspace/HuToolDemo/src/com/wwj/test/TestDemo.java");
    BufferedOutputStream outputStream = FileUtil.getOutputStream("E:/test.txt");
    long copySize = IoUtil.copy(inputStream, outputStream, IoUtil.DEFAULT_BUFFER_SIZE);
    这里就复制了一下当前的java文件并将其保存至E盘下的test.txt文件中。
    2、读流写流
    读流写流也是IO操作中使用频率非常高的操作,它跟传统的方式没有太大区别,只不过对调用者进行了统一。
    BufferedInputStream inputStream = FileUtil.getInputStream("C:\\Users\\Administrator\\Desktop\\eclipseworkspace\\HuToolDemo\\src\\com\\wwj\\test\\TestDemo.Java");
    BufferedOutputStream outputStream = FileUtil.getOutputStream("E:\\test.txt");
    int len = -1;
    byte[] buffer = new byte[1024];
    while ((len = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, len);
    }
    IoUtil.close(inputStream);
    IoUtil.close(outputStream);
    下面列出关于读写流操作相关的方法:
    • readBytes 返回byte数组(读取图片等)
    • readHex 读取16进制字符串
    • readObj 读取序列化对象(反序列化)
    • readLines 按行读取
    对于写流操作,IoUtil提供了两个write()的重载方法,当然也可以直接使用输出流的write()方法,而事实上,IoUtil的write()方法也是这么做的。
    我们再来看看IoUtil如何读写图片,对于图片的读写操作,它提供了readBytes()方法,使用该方法读写图片简直不要太简单:
    BufferedInputStream inputStream = FileUtil.getInputStream("C:\\Users\\Administrator\\Desktop\\eclipseworkspace\\HuToolDemo\\默认图表.png");
    BufferedOutputStream outputStream = FileUtil.getOutputStream("E:\\test.png");
    byte[] bytes = IoUtil.readBytes(inputStream);
    outputStream.write(bytes);
    IoUtil.close(inputStream);
    IoUtil.close(outputStream);
    这样即可完成图片的读写。
    IoUtil还提供了一些其它方法用于简化编程,比如:toStream()方法用于将某些对象转换为流对象;writeObjects()方法用于将可序列化对象序列化后写入到流中。
    3、释放流资源
    IO操作中的一个好习惯就是用完哪个流就关掉哪个流,而关闭操作会面临两个问题:
    • 被关闭的对象为空
    • 对象关闭失败
    而IoUtil提供的close()方法则很好地解决了这些问题,我们只需将要关闭的流传入close()方法即可。
    FileTypeUtil(文件类型判断工具类)
    FileTypeUtil是一个判断文件类型的工具类,它并不是通过文件的扩展名来确定文件类型,而是通过读取文件的首部几个二进制位来判断。
    File file = FileUtil.file("C:\\Users\\Administrator\\Desktop\\eclipseworkspace\\HuToolDemo\\默认图表.png");
    String type = FileTypeUtil.getType(file);
    Console.log(type);
    运行结果:
    pngFileReader(文件读取)
    虽然FileUtil已经提供了关于文件读写的API,但是根据职责分离原则,HuTool还是为我们提供了FileReader类专门读取文件。
    在JDK中同样提供了FileReader类,但并不好用,HuTool正是对它进行的一个升级。
    FileReader fileReader = new FileReader("test.properties");
    String result = fileReader.readString();
    System.out.println(result);
    运行结果:
    username=root
    password=123456
    该类还提供了一些常用的方法帮助文件读取:
    • readBytes
    • readString
    • readLines
    文件写入(FileWriter)
    有文件读取,肯定就会有文件写入,使用方法和FileReader是一样的,这里就不做代码演示了。
    写入方式分为追加和覆盖两种模式,追加的话可以用append()方法,覆盖可以用write()方法;当然你也可以直接使用write()方法,并将写入模式作为第二个参数传入。
    资源访问
    在Java开发中,资源访问是比较常见的操作,例如在操作数据库、整合框架的时候,需要频繁地访问配置文件,通常我们会将配置文件放在类路径下,方便访问:
    InputStream in = TestDemo.class.getResource("test.properties").openStream();
    对于资源访问这种频繁而且麻烦的操作,HuTool对其进行了封装。
    ClassPathResource resource = new ClassPathResource("test.properties");
    Properties properties = new Properties();
    properties.load(resource.getStream());
    Console.log(properties);
    运行结果:
    {password=123456, username=root}
    当然,对于资源访问的封装远不止如此,这个放到后面说。java吧 java源码篇

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表