有了它,Java語法也可以變得甜甜的
簡介
Hutool是一個小而全的Java工具類庫,通過靜態方法封裝,降低相關API的學習成本,提高工作效率,使Java擁有函數式語言般的優雅,讓Java語言也可以“甜甜的”。
Hutool中的工具方法來自于每個用戶的精雕細琢,它涵蓋了Java開發底層代碼中的方方面面,它既是大型項目開發中解決小問題的利器,也是小型項目中的效率擔當;
Hutool是項目中“util”包友好的替代,它節省了開發人員對項目中公用類和公用工具方法的封裝時間,使開發專注于業務,同時可以最大限度的避免封裝不完善帶來的bug。
這是官方對它的介紹,簡單點說,它通過一些封裝,將原來略顯復雜的API進一步優化,使得你在使用的時候能夠更加方便快捷,當然語法也會比原來更加簡單易懂。
包含組件
一個Java基礎工具類,對文件、流、加密解密、轉碼、正則、線程、XML等JDK方法進行封裝,組成各種Util工具類,同時提供以下組件:
可以根據需求對每個模塊單獨引入,也可以通過引入hutool-all方式引入所有模塊。
安裝
1、Maven項目
在項目的pom.xml的dependencies中加入以下內容:
2、非Maven項目
-: https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.0.7/
下載hutool-all-X.X.X.jar即可。
下面對某幾個組件的使用進行一個入門。
類型轉換
1、常用類型轉換
在傳統的類型轉換過程中,我們需要使用到包裝類的valueof()方法,例如:
String s = "1234"; int num = Integer.valueOf(s); double d = Double.valueOf(s); float f = Float.valueOf(s);
但很顯然實際情況并沒有這么簡單,在企業級的開發項目中,從前端傳遞過來的參數各式各樣,類型繁多,我們如何知曉參數類型并作對應的轉換呢?一般會先將所有參數轉成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>() {}, 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對象并返回,實現類型轉換。
接著注冊自定義的轉換器:
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、獲取年、月、日
// 獲取當前日期時間 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 false
IO操作
IO操作是Java中比較重要的操作之一,為此,Java提供了InputStream、OutputStream、Reader、Writer等接口,而實現類又非常的多,往往選擇一多,我們就不知道該如何選擇,而HuTool為我們封裝了一系列的工具類。
既然是IO流,那就離不開文件操作,HuTool為我們提供了FileUtil工具類用來解決大部分的文件操作問題。
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,該工具類主要針對輸入輸出流的一個封裝。
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是一個判斷文件類型的工具類,它并不是通過文件的擴展名來確定文件類型,而是通過讀取文件的首部幾個二進制位來判斷。
File file = FileUtil.file("C:\\Users\\Administrator\\Desktop\\eclipseworkspace\\HuToolDemo\\默認圖表.png"); String type = FileTypeUtil.getType(file); Console.log(type);
運行結果:
png
雖然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
有文件讀取,肯定就會有文件寫入,使用方法和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}
當然,對于資源訪問的封裝遠不止如此,這個放到后面說。
最后
以上內容只是HuTool項目的冰山一角,我將在下篇相關文章中繼續介紹該項目下封裝的一些工具類。
Java 數據結構
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。