Object類Object類概述
java.lang.Object類是所有Java類的根類,即所有子類都會直接或者間接繼承(Extends)Object類,直接繼承是不用寫extends Object,編譯器會自動新增。java.lang包下的類在使用時不需要使用import關鍵字匯入。因為Object類是根類,不需要考慮它的繼承關係,因此只需要去看看它有哪些方法即常用的方法即可,因為所有的子類都會擁有Object類的方法。
Object類所有的方法
如果你封裝了一個JavaBean(即私有化成員變數,提供get/set方法和無參構造器的類),會使用到其父類Object的equals()方法和、oString()方法和hashCode()方法而notify()方法,notifyAll()方法,wait()方法是多執行緒情況下使用。getClass()方法是反射特性會使用。
Employee JavaBean設計Employee 是一個普通的JavaBean,包含三個私有化成員變數以及get/set方法以及構造方法,該類會預設繼承java.lang.Object,因此會有父類的方法
Object類的toString()方法實現
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
當列印輸出物件時預設會呼叫物件的toString()方法
因為Employee類是我們自己封裝的一種資料型別,在進行業務系統開發時通常會檢視物件的成員變數(也叫屬性)值,而不關心物件的全類名和記憶體地址。因此一般都會去重寫java.lang.Object父類的toString()方法。
/** * 重寫父類java.lang.Object的toString()方法 * @return 物件的屬性資訊的字串 * @see Object#toString() */ @Override public String toString() { return "Employee{" + "employeeNo='" + employeeNo + '\'' + ", name='" + name + '\'' + ", age=" + age + '}'; }
重寫toString()方法以後,會列印物件的屬性值
JDK提供的API也都重寫了java.lang.Object類的toString()方法
StringBuilder重寫toString()方法
String類重寫toString()方法
equals()方法的使用java.lang.Object類的equals()方法使用==來判斷兩個物件是否相等,該方法需要傳遞一個Object類物件的引數,返回一個布林值,如果相等則返回true,不等則返回false
public boolean equals(Object obj) { return (this == obj); }
java.lang.Object類的equals()方法比較的是地址是否相等,但是日常開發中通常比較的是物件的成員變數值是否相等,如果屬性值不相等則返回false
因此如果想要判斷物件的屬性值是否相等,我們還需要重寫java.lang.Object類的equals()方法,一般重寫equals()方法都要重寫hashCode()方法。
/** * 重寫java.lang.Object的equals()方法 * @param object * @return * @see Object#equals(Object) */ @Override public boolean equals(Object object) { //如果兩個物件的地址相等則返回true if(this==object){ return true; } //方法的引數為空或者型別不一樣返回false if(null==object||this.getClass()!=object.getClass()){ return false; } Employee targetEmployee= (Employee) object; //判斷如果員工編號一樣就表示同一個員工 return Objects.equals(this.getEmployeeNo(),targetEmployee.getEmployeeNo()); } @Override public int hashCode() { return Objects.hash(employeeNo, name, age); }
重寫後再次建立兩個物件並分別呼叫==和equals()方法來判斷兩個物件的相等性
看到這裡讀者應該能夠解決一個面試題: ==和equals()方法有什麼區別。回答該問題時應該先考慮未重寫equals()前的行為和重寫equals()後的行為。
Objects類java.util.Objects類是JDK7以後新增的一個工具類,該類包含許多關於Object操作的靜態方法,也就是可以直接透過類名.方法名呼叫。
java.util.Objects類提供的方法都是空指標安全的,也就是能夠避免空指標異常。日常開發中應該儘量避免空指標異常。我們可以學習Objects類的equals()方法的實現,如果避免空指標異常。
public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
equals()方法需要兩個Object型別的引數,通常是傳遞的自己封裝的類的成員變數。equals()該方法的執行流程是
判斷兩個物件的地址是否相同,如果相同根據邏輯或的短路特性,直接返回true如果兩個物件的地址不同,則會判斷第一個引數a是不是空,如果為空則會根據邏輯與的短路特性直接返回false如果a不為空則呼叫兩個引數的equals()方法來判斷是否相等在沒有Objects提供的equals()方法前,如果使用JDK提供的API的equals()方法容易引發空指標異常
//測試String物件的相等性判斷 @Test public void testStringEquals(){ // 使用String類的equals()進行相等性判斷容易引發空指標 String str1 = null; String str2 = "tony"; log.info("str1 .equals(str2) = {}", str1.equals(str2)); }
程式執行結果
此時可以使用Objects提供的equals()方法來判斷String的相等性
/** * 使用Objects.equals()方法判斷String相等性 */ @Test public void testObjectsStringEquals(){ String str1 = null; String str2 = "tony"; log.info("Objects.equals(str1,str2) = {}", Objects.equals(str1, str2)); String str3="tony"; log.info("Objects.equals(str3,str2) = {}", Objects.equals(str3, str2)); String str4=new String("tony"); log.info("Objects.equals(str4, str2) = {}", Objects.equals(str4, str2)); }
程式執行結果
因此後面在日常開發中應該是用java.util.Objects類提供的equals()方法來比較兩個物件是否相等。這樣能夠避免空指標異常。
因為Objects的equals()方法需要兩個Object型別的引數,因此根據形參多型的特性,所有的Object子類都可以做為該方法的引數
native 方法native方法稱為本地方法,本地方法沒有方法體,我們也無法檢視其實現,當我們需要訪問C/C或者訪問作業系統底層的類庫時可以使用本地方法實現,也意味著Java語言可以透過JNI和其他語言進行互動。本地方法的作用就是當Java呼叫非Java程式碼的介面時,方法的實現是非Java實現,通常都是C/C實現。Object類中的getClass(),hashCode(),notify(),notifyAll(),wait()都是使用C/C++實現的本地方法
public final native Class<?> getClass(); public native int hashCode(); public final native void notify(); public final native void notifyAll(); public final native void wait(long timeoutMillis) throws InterruptedException;
時間日期類Date類Date類表示日期,時間精確到毫秒。Date類是JDK1.0設計的類,因為其本身有些缺陷,在Java8重新設計了一套日期API,因此Date類的很多方法都已經標記為過時了,如果方法上有個@Deprecated註解就表示該方法已經過時,在日常開發中儘量避免使用過時的方法,因為JDK或者框架會在後期的版本升級中刪除過時的方法,那樣我們的程式會無法編譯透過。
Date類有兩個常用的建構函式
public Date() { this(System.currentTimeMillis()); } public Date(long date) { fastTime = date; }
其中無引數的構造器是以當前的時間建立日期物件
/** * 測試無引數的構造器 */ @Test public void testDateNoArgsConstructMethod(){ /** * 預設以當前時間建立日期物件 */ Date currentDate=new Date(); //Wed Dec 16 15:29:07 CST 2020 // CST 表示中國標準時間 // Dec 16 表示12月16日 // Wed 表示星期三 System.out.println(currentDate); }
程式執行結果
而傳long引數的構造器用建立一個以標準時間為基準,指定偏移毫秒數對應的日期物件
標準時間指的是1970年1月1日 00:00:00 ,也就是Unix系統的誕生日,而我們偉大的祖國母親是位於東八區,因此標準時間是1970年1月1日:08:00:00 @Test public void testDateLongArgsConstructMethod(){ /** * 以標準基準時間為基準,指定偏移毫秒數對應的日期物件 * 標準基準時間是格林威治時區: 1970年1月1日 00:00:00 * 中國處於東八區: 1970年1月1日:08:00:00 */ Date offSetDate=new Date(1000); //Thu Jan 01 08:00:01 CST 1970 System.out.println(offSetDate); }
程式執行結果
Date類還提供了getTime()獲取標準當前日期距離標準基準時間的毫秒數,該方法的返回值可以用於統計程式的時間耗時,作為程式效能最佳化的依據,setTime()用於置當前日期物件距離標準基準時間的毫秒數
@Test public void testDateGetTimeMethod(){ Date now=new Date(); //獲取當前日期物件距離標準基準時間的毫秒數 long milliseconds=now.getTime(); log.info("獲取當前日期物件距離標準基準時間的毫秒數 {}",milliseconds); //設定當前日期物件距離標準基準時間1970年1月1日:08:00:00的毫秒數 now.setTime(2000); System.out.println("now = "+now); }
程式執行結果
Date類還提供了before()和after()方法用於比較兩個日期
@Test public void testDateBeforeAfterMethod(){ //以當前時間建立日期物件 Date currentDate=new Date(); System.out.println("currentDate = "+currentDate); //從1970-01-01 08:00:00 加2000毫秒 1970-01-01 08:00:02 Date customDate=new Date(2000); System.out.println("customDate = "+customDate); log.info("customDate.before(currentDate) = {}",customDate.before(currentDate)); log.info("customDate.after(currentDate) = {}",customDate.after(currentDate)); }
程式執行結果
DateFormat類java.text.DateFormat類是一個日期/時間格式化的抽象類,其應用場景是當Web前端傳遞過來的日期都是字串形式,Java後端接收時需要按照指定的格式進行日期轉換後儲存到資料庫。由於DateFormat是一個抽象類,因此需要使用該類的子類SimpleDateFormat來實現日期/時間格式化。也就是將字串日期和Date日期相互轉換。
在建立SimpleDateFormat物件時需要傳入指定的日期格式引數
public SimpleDateFormat(String pattern) { this(pattern, Locale.getDefault(Locale.Category.FORMAT)); }
常用的日期格式有yyyy年MM月dd日 HH時mm分ss秒和 yyyy-MM-dd HH:mm:ss
y 表示年M 表示月d 表示日HH 表示小時mm 表示分鐘ss 表示秒鐘SimpleDateFormat提供了format()方法用於將日期轉換為字串
/** * 標準日期格式常量 */ public static final String DEFAULT_PATTERN="yyyy-MM-dd HH:mm:ss"; /** * * 使用SimpleDateFormat的format()方法實現日期轉字串 * */ @Test public void testSimpleDateFormatDateToString(){ //按照指定的日期格式建立日期格式化物件 DateFormat dateFormatDefaultPattern =new SimpleDateFormat(DEFAULT_PATTERN); //呼叫format()方法將日期轉換為字串 //日期物件使用的是匿名物件 String defaultPatternDateToStr=dateFormatDefaultPattern.format(new Date()); log.info("defaultPatternDateToStr = {}",defaultPatternDateToStr); }
程式執行結果
SimpleDateFormat提供了parse()方法用以將字串轉換為日期
/** * 使用SimpleDateFormat的parse()方法將日期轉換為字串 * @throws ParseException */ @Test public void testSimpleDateFormatStringToDate()throws ParseException{ //建立日期字串 String dateStr= "2020-12-16 16:02:00"; //按照指定的格式建立日期格式化物件 DateFormat dateFormatDefaultPattern =new SimpleDateFormat(DEFAULT_PATTERN); //透過parse()方法講將字串轉換為日期物件 Date stringToDateResult =dateFormatDefaultPattern.parse(dateStr); System.out.println("stringToDateResult = "+stringToDateResult); }
程式執行結果
一個日期和格式化的案例:從鍵盤讀取使用者輸入的生日,然後計算天數
程式實現思路
建立Scanner物件呼叫netxtLine()方法獲取使用者輸入的生日字串使用SimpleDateFormat的parse()方法將生日字串轉換為Date日期呼叫Date日期物件的getTime()方法獲取系統基準時間到生日的毫秒數呼叫當前日期物件額getTime()方法獲取系統基準時間到當前時間的毫秒數當前時間的毫秒數減去生日毫秒數後求天數。程式實現程式碼
Calendar類java.uti.Calendar是一個抽象類,用於表示日曆,包含日日期/時間資訊,可以進行日期的運算。
Calendar不能建立物件,一般是使用它的子類:java.util.GregorianCalendar類
有兩種方法可以建立GregorianCalendar物件
/** * 獲取日曆物件的兩種方法 */ @Test public void testCreateCalendar() { // 當前系統時間的日曆物件 Calendar calendarInstance = Calendar.getInstance(); Calendar calendar=new GregorianCalendar(); System.out.println(calendar); }
當建立GregorianCalendar物件後列印輸出該物件會看到如下資訊
java.util.GregorianCalendar[time=1608110761595,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[ id="Asia/Shanghai", offset=28800000, dstSavings=0, useDaylight=false, transitions=31, lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2020,MONTH=11,WEEK_OF_YEAR=51,WEEK_OF_MONTH=3,DAY_OF_MONTH=16,DAY_OF_YEAR=351,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=3,AM_PM=1,HOUR=5,HOUR_OF_DAY=17,MINUTE=26,SECOND=1,MILLISECOND=595,ZONE_OFFSET=28800000,DST_OFFSET=0]
關於GregorianCalendar物件關於日期/時間的屬性名/屬性值說明
time=1608110761595 表示當前時間距離標準基準時間的毫秒數ZoneInfo 用於描述時區資訊,當前時區是亞洲/上海,比標準基準時間晚8個小時MONTH=11 表示今天是今年的12月份,GregorianCalendar物件的月分是從0開始WEEK_OF_YEAR=51 表示今天是今年的51周WEEK_OF_MONTH=3 表示今天是這個月的第三週DAY_OF_WEEK=4 表示今天是這周的第四天,因為外國是從週日到週六,也就是說週日是一週的第一天,而今天(2020/12/16)按照外國人的演算法就是週四DAY_OF_MONTH=16 表示今天是這個月的16天DAY_OF_YEAR=351 表示今天是今天的351天,難過的2020馬上就要結束了DAY_OF_WEEK_IN_MONTH=3 表示今天是這個月的第三週GregorianCalendar 提供了get()方法用於獲取日曆的日期/時間資訊
/** * 透過GregorianCalendar物件的get方法獲取日曆的日期/時間資訊 * * @see GregorianCalendar#get(int) */ @Test public void testCalendarGetMethod() { // 當前系統時間的日曆物件 Calendar calendarInstance = Calendar.getInstance(); int year = calendarInstance.get(Calendar.YEAR); int month = calendarInstance.get(Calendar.MONTH); int day = calendarInstance.get(Calendar.DAY_OF_MONTH); int hour=calendarInstance.get(Calendar.HOUR_OF_DAY); int minute = calendarInstance.get(Calendar.MINUTE); int second=calendarInstance.get(Calendar.SECOND); System.out.printf("透過GregorianCalendar物件的get()方法獲取日期資訊:%d年%d月%d日 %d時%d分%d秒", year, month, day,hour,minute,second); }
程式執行結果
GregorianCalendar 提供了set()方法設定指定的日期/時間,add()方法增加日期/時間
/** 修改日曆對應日期 add 增加日期/時間 set 設定指定的日期/時間 */ @Test public void testCalendarUpdate() { Calendar calendarInstance = Calendar.getInstance(); // 將年份設定為1999 calendarInstance.set(Calendar.YEAR, 1999); System.out.println("將年份設定為1999 當前年份是" + calendarInstance.get(Calendar.YEAR)); // 將當前的年份加兩年 calendarInstance.add(Calendar.YEAR, 2); System.out.println("將當前的年份加兩年 當前年份是" + calendarInstance.get(Calendar.YEAR)); // 將當年的年份減少2年 calendarInstance.add(Calendar.YEAR, -2); System.out.println("將當年的年份減少2年 當前年份是" + calendarInstance.get(Calendar.YEAR)); }
GregorianCalendar 還提供了setTime()的方法用於透過傳遞一個Date日期的引數來設定日曆
/** 獲取距離標準時間2小時的日曆物件 */ @Test public void testCalendarSetTimeMethod() { Calendar calendarInstance = Calendar.getInstance(); // 首先獲取距離標準時間2小時的日期 Date date = new Date(1000 * 60 * 60 * 2); // 呼叫日曆物件的setTime()方法設定日曆物件設定的日期 calendarInstance.setTime(date); log.info(calendarInstance); }
程式執行結果
GregorianCalendar 也提供了用於兩個日曆物件的比較方法:before()和after()
/** before() 判斷此Calendar表示的時間是否在指定的Object表示的時間之前 ,返回布林值。 */ @Test public void testCalendarBefore() { Calendar source = Calendar.getInstance(); System.out.printf("透過GregorianCalendar物件的get()方法獲取source日期資訊:%d年%d月%d日\n", source.get(Calendar.YEAR), source.get(Calendar.MONTH), source.get(Calendar.DAY_OF_MONTH)); //以標準基準時間偏移24小時建立日曆物件 Calendar target = Calendar.getInstance(); Date date = new Date(1000 * 60 * 60 * 24); target.setTime(date); System.out.printf( "透過GregorianCalendar物件的get()方法獲取target日期資訊:%d年%d月%d日\n", target.get(Calendar.YEAR), target.get(Calendar.MONTH), target.get(Calendar.DAY_OF_MONTH)); boolean beforeResult = source.before(target); System.out.println("source.before(target)= "+beforeResult); boolean afterResult = source.after(target); System.out.println("source.after(target)= "+afterResult); }
程式執行結果
Math類java.lang.Math類提供了一些關於數學運算的靜態方法,即它的方法都是使用static修飾的,直接透過類名.方法名呼叫即可。
在日常開發中常用的Math提供的方法如下
Math.abs()求一個數值的絕對值 /** Math.abs()求一個數值的絕對值 */ @Test public void testMathAbsMethod() { System.out.println("10的絕對值是"+Math.abs(10)); System.out.println("-10的絕對值是"+Math.abs(-10)); System.out.println("2.0的絕對值是"+Math.abs(2.0)); System.out.println("-2.0的絕對值是"+Math.abs(-2.0)); }
程式執行結果
Math.ceil() 向上取整Math.floor() 向下取整/** Math.ceil() 向上取整 大於這個數的最小整數 */ /** Math.floor() 向下取整 小於這個數的最小整數 */ @Test public void testMathCeilFloorMethod() { //3.2向上取整就是4.0 System.out.println("3.2向上取整的結果是"+Math.ceil(3.2)); //-3.2向上取整就是-3 System.out.println("-3.2向上取整的結果是"+Math.ceil(-3.2)); //3.2向下取整就是3.0 System.out.println("3.2向下取整的結果是"+Math.floor(3.2)); }
程式執行結果
Math.pow(m,n) 求m的n次冪/** * Math.pow(m,n) 計算m的n次方 */ @Test public void testMathPowMethod() { //計算2的3次方 System.out.println("2.0的3.0次冪的結果是"+Math.pow(2.0,3.0)); }
程式執行結果
Math.round() 四捨五入 /** * Math.round() 四捨五入 */ @Test public void testMathRoundMethod() { System.out.println("3四捨五入的結果是"+Math.round(3)); System.out.println("99四捨五入的結果是"+Math.round(99)); System.out.println("3.49四捨五入的結果是"+Math.round(3.49)); System.out.println("3.50四捨五入的結果是"+Math.round(3.50)); }
程式執行結果
Math.max()求兩個數的最大值Math.min() 求兩個數的最小值 /** * Math.max()獲取最大值 * Math.min()獲取最小值 */ @Test public void testMatMaxMinMethod() { System.out.println("10,20的最大值是"+Math.max(10,20)); System.out.println("10,20的最小值是"+Math.min(10,20)); }
程式執行結果
System類java.lang.System類表示系統,不能例項化,因此該類提供了大量的靜態方法用於獲取或者去作業系統。
System.getProperty()方法來獲取系統的屬性首先使用System.getProperties().list(System.out);將所有的系統屬性輸出在終端後,使用System.getProperty()方法根據屬性名獲取屬性值 /** * 獲取系統屬性 */ @Test public void testSystemGetProperties() { //將所有的系統屬性輸出在終端上 System.getProperties().list(System.out); System.out.println("當前Java程式依賴的JDK版本是"+System.getProperty("java.version")); System.out.println("當前Java程式依賴的JVM是"+System.getProperty("java.vm.name")); System.out.println("當前Java程式依賴的作業系統版本是"+System.getProperty("os.name")); System.out.println("當前Java程式的位元組碼版本是"+System.getProperty("java.class.version")); }
程式執行結果
程式執行結果
System.getenv()獲取系統所有環境變數 /** * 獲取系統環境變數 */ @Test public void testSystemGetEnv() { // 將所有的系統屬性輸出在終端上 System.out.println(System.getenv()); }
程式執行結果
System.arraycopy()方法實現陣列的複製@Test public void testSystemArrayCopyMethod(){ int[]source={1,2,3,4,5,6,7,8}; int[] target={10,20,30,40,50,60,70,80}; //將source的5,6,7,8複製到target的50,60,70,80 System.arraycopy(source,4,target,4,4); //輸出結果 [10, 20, 30, 40, 5, 6, 7, 8] System.out.println("target = "+Arrays.toString(target)); }
程式執行結果
System.currentTimeMillis()方法用於獲取當前時間到標準基準時間的毫秒數,等價於呼叫Date物件的getTime()方法 @Test public void testSystemCurrentTimeMillisMethod(){ //獲取當前時間到標準基準時間的毫秒數 // 等價與new Date().getTime(); System.out.println(System.currentTimeMillis()); System.out.println(new Date().getTime()); }
程式執行結果
我們可以基於System.currentTimeMillis()方法實現計算某段程式的耗時
/** * 統計程式耗時 */ @Test public void tesSystemOutStatisticTime(){ long start=System.currentTimeMillis(); for (int i = 0; i <100; i++) { System.out.println("i = "+i); } long end=System.currentTimeMillis(); log.info("程式耗時 {}毫秒",(end-start)); }
程式執行結果
包裝類之前學習的八種基本資料型別都不具備面向物件的特徵:沒有屬性和方法,也沒法建立物件,更沒有面向物件的三大特徵:封裝、繼承和多型。但是基本資料型別也有它的優勢,主要在於儲存方面。因此大佬們設計了8種基本資料型別的包裝類,包裝類就是將基本資料型別轉換為對應的引用資料型別。
byte的包裝類是java.lang.Byteshort的包裝類是java.lang.Shortchar的包裝類是java.lang.Charint的包裝類是java.lang.Integerlong的包裝類是java.lang.Longfloat的包裝類是java.lang.Floatdouble的包裝類是java.lang.Double這裡以開發中常用的Integer類來說明包裝類的使用
Integer類定義了其佔據的位元組數,取值範圍的常量,如果你忘記了int的取值範圍,可以直接檢視Integer類的原始碼,或者直接透過Integer類呼叫對應的常量獲取
/** * Integer類定義了其佔據的位元組數,取值範圍的常量 */ @Test public void testIntegerConstants(){ System.out.printf("int佔據的位元組數量是%d,int儲存的最小值是%d,int儲存的最大值是%d\n",Integer.BYTES,Integer.MIN_VALUE,Integer.MAX_VALUE); }
Integer類也定義了方法用於實現將int和Integer的相互轉換
valueOf()方法實現將int轉換為IntegerintValue()方法實現將Integer轉換為int /** int和Integer的相互轉換 */ @Test public void testIntegerCast() { // 使用valueOf()方法將int轉換為Integer Integer integer = Integer.valueOf(123); System.out.println("integer = " + integer); // intValue()方法將Integer轉換為int int intValue = integer.intValue(); System.out.println("intValue = " + intValue); }
程式執行結果
但是日常開發中經常使用的是字串和Integer之間的轉換,因為前臺傳過來的都是字串型別的資料
parseInt()方法用於將字串轉換為Integer @Test public void testIntegerStringCast(){ // 使用valueOf()方法將String轉換為Integer Integer value = Integer.valueOf("123"); System.out.println("value = " + value); // 日常開發中常用的方法是將字串轉換為Integer物件 Integer integerValue=Integer.parseInt("999"); System.out.println("integerValue = "+integerValue); }
程式執行結果
JDK1.5以後支援了自動拆箱和裝箱
自動拆箱: 將包裝類自動轉換為對應的基本資料型別自動裝箱:將基本資料型別自動轉換為對應的包裝類型別 /** * 自動拆箱和裝箱 */ @Test public void testAutoBox(){ //自動裝箱:將long自動轉換為java.lang.Long Long longValueRef=70_00000000L; //自動拆箱:將java.lang.Long自動轉換為long long longValue=longValueRef; System.out.printf("longValue = %d longValueRef = %d\n",longValue,longValueRef); }
程式執行結果
在日常開發中還會使用到基本資料型別和字串之間的相互轉換
String.valueOf()靜態方法用於將基本資料型別轉換為String /** * 基本資料型別轉換為String */ @Test public void testPrimitiveTypeCast(){ int intValue=123; String stringValueInt=String.valueOf(intValue); long longValue=123456789L; String stringValueLong=String.valueOf(longValue); System.out.printf("stringValueInt = %s stringValueLong = %s \n",stringValueInt,stringValueLong); }
程式執行結果
除了Character類以外,其他所有的包裝類都提供了valueOf()靜態方法用於將字串轉換為對應的包裝類型別 /** * 字串轉包裝類 */ @Test public void testStringCastWrapperClass(){ String str="123"; Byte byteRef=Byte.valueOf(str); Long longRef=Long.valueOf(str); System.out.printf("byteRef = %d longRef =%d\n",byteRef,longRef); }
程式執行結果
除了Character以外,其他所有包裝類都提供了parseXX()靜態方法將字串引數轉換為任意的基本資料型別 /** * 字串轉換為基本資料型別 */ @Test public void testStringCastPrimitiveType(){ String str="123"; long longValue=Long.parseLong(str); double doubleValue=Double.parseDouble(str); byte byteValue=Byte.parseByte(str); System.out.println("longValue = "+longValue); System.out.println("doubleValue = "+doubleValue); System.out.println("byteValue = "+byteValue); String bool="boolean"; boolean blValue=Boolean.parseBoolean(bool); System.out.println("blValue = "+blValue); }
程式執行結果
BigInteger類java.math.BigInteger類表示一個超大的整數,也就是支援任意精度的整數。
當Integer,Long型別的整數不能滿足儲存和計算的要求,此時可以使用字串的整數構建一個BigInteger物件。
/** * BigInteger構造器的使用 */ @Test public void testBigIntegerConstruct() { Integer intMax = Integer.MAX_VALUE; Long longMax = Long.MAX_VALUE; System.out.printf("int表示的最大值是%d long 表示的最大值是%d\n", intMax, longMax); //此處會編譯錯誤,超過了long的表示範圍 // long value=9223372036854775808L; BigInteger source=new BigInteger("9223372036854775808"); BigInteger target=new BigInteger("9223372036854775809"); log.info("source = {} target = {}",source,target); }
程式執行結果
構造BigInteger物件之後可以使用其提供的方法完成大整數的算術運算
/** * 使用BigInteger完成兩個大整數的算術運算 */ @Test public void testBigIntegerArithmetic(){ BigInteger source=new BigInteger("9223372036854775808"); BigInteger target=new BigInteger("100"); log.info("source = {} target = {}",source,target); BigInteger addResult=source.add(target); log.info("addResult = {}",addResult); BigInteger subtractResult=source.subtract(target); log.info("subtractResult = {}",subtractResult); BigInteger multiplyResult=source.multiply(target); log.info("multiplyResult = {}",multiplyResult); BigInteger divideResult=source.divide(target); log.info("divideResult = {}",divideResult); }
程式執行結果
BigDecimal類浮點數在運算時得到的是一個無限接近結果的近似值,也就是存在精度問題。
/** * 浮點數的運算結果是不精確的 * 0.09 + 0.01 = 0.09999999999999999 * 1.0 - 0.32 = 0.6799999999999999 * 1.015 * 100 = 101.49999999999999 * 1.301 / 100 = 0.013009999999999999 */ @Test public void testFloatPrecision(){ System.out.println("0.09 + 0.01 = "+(0.09 + 0.01 )); System.out.println("1.0 - 0.32 = "+(1.0-0.32 )); System.out.println("1.015 * 100 = "+(1.015 * 100 )); System.out.println("1.301 / 100 = "+(1.301 / 100 )); }
程式執行結果
BigDecimal類表示任意精度的十進位制浮點數,可以解決浮點數運算的精度問題。
/** * 使用BigDecimal進行任意精度浮點數的算術運算 */ @Test public void testBigDecimalArithmetic(){ BigDecimal source=new BigDecimal("0.09"); BigDecimal target=new BigDecimal("0.01"); log.info("source = {} target = {}",source,target); BigDecimal addResult=source.add(target); log.info("addResult = {}",addResult); source=new BigDecimal("1.0"); target=new BigDecimal("0.32"); log.info("source = {} target = {}",source,target); BigDecimal subtractResult=source.subtract(target); log.info("subtractResult = {}",subtractResult); source=new BigDecimal("1.015"); target=new BigDecimal("100"); log.info("source = {} target = {}",source,target); BigDecimal multiplyResult=source.multiply(target); log.info("multiplyResult = {}",multiplyResult); source=new BigDecimal("1.301"); target=new BigDecimal("100"); BigDecimal divideResult=source.divide(target); log.info("divideResult = {}",divideResult); }
程式執行結果
但是使用字串引數的構造器建立BigDecimal物件時在進行除法運算如果除不盡。例如10/3=3.3333 就會拋一個算術異常
/** * 除法除不盡就會拋異常 */ @Test public void testBigDecimalDivideMethod(){ BigDecimal source=new BigDecimal("10"); BigDecimal target=new BigDecimal("3"); BigDecimal divideResult=source.divide(target); System.out.println(divideResult); }
程式執行結果
為了解決BigDecimal除法的算術異常(ArithmeticException),可以使用BigDecimal過載的devide()方法。
/** * 使用過載的divide方法解決除法除不盡的算術異常 */ @Test public void testBigDecimalOverrideDivideMethod(){ BigDecimal source=new BigDecimal("10"); BigDecimal target=new BigDecimal("3"); /** * 過載的divide方法引數說明 * divisor 除數對應的BigDecimal物件 * scale 精確的位數 * roundingMode:取捨模式 */ //計算結果四捨五入 保留2位, BigDecimal divideResult=source.divide(target,2, RoundingMode.HALF_UP); log.info("divideResult = {}",divideResult); }
程式執行結果
在使用BigDecimal是需要注意,不能使用double型別的引數建立BigDecimal物件,其運算的結果也是不精確的
/** * 使用浮點數引數的構造器只能獲得更加無限接近的結果,但是還是有精度損失問題 */ @Test public void testBigDecimalFloatConstruct(){ BigDecimal source= new BigDecimal(0.09); BigDecimal target= new BigDecimal(0.01); BigDecimal addResult=source.add(target); System.out.println("0.09 + 0.01 ="+addResult); }
程式執行結果
Arrays類java.util.Array類是JDK提供的一個工具類,用於陣列的常用操作:排序,查詢,複製,比較,等等。
Arrays.sort()方法可以實現陣列元素的升序排序,該方法支援八種基本資料型別的陣列元素 /** 陣列升序排序 */ @Test public void testArraySort() { int[] numbers = {1, 2, 4, 5, 6, 7, 8, 9, 6, 3}; // 將整型陣列按照升序排序 Arrays.sort(numbers); // 將陣列以字串列印在終端 System.out.println(Arrays.toString(numbers)); }
程式執行結果
Arrays.binarySearch()方法可以實現陣列元素二分法查詢,查詢之前需要對陣列進行排序,該方法支援八種基本資料型別的陣列元素 /** 陣列二分法查詢 */ @Test public void testArrayBinarySearch() { int[] numbers = {1, 2, 4, 5, 6, 7, 8, 9, 6, 3}; // 將整型陣列按照升序排序 Arrays.sort(numbers); // 將陣列以字串列印在終端 System.out.println(Arrays.toString(numbers)); //使用二分法查詢指定的數字5,返回5在陣列中的索引 int key =5 ; int index = Arrays.binarySearch(numbers, 5); System.out.printf("%d在陣列中的索引位置是%d\n",key,index); }
程式執行結果