一、包裝類 java是一門面向對象的語言,秉承一切皆對象的思想。 可java中有一些基本數據類型並不是對象,有時可能需要將它們變為對象。 這時就需要用到我們的包裝類了。 通過對應的包裝類可以讓基本屬性擁有對象的特性,之後可以使用相關的操作。 自動裝箱與自動拆箱 通過上面代碼我們可以看出,都是手動裝箱 ...
一、包裝類
java是一門面向對象的語言,秉承一切皆對象的思想。
可java中有一些基本數據類型並不是對象,有時可能需要將它們變為對象。
這時就需要用到我們的包裝類了。
基本數據類型 | 包裝類 |
int | Integer |
char | Character |
short | Short |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
byte | Byte |
通過對應的包裝類可以讓基本屬性擁有對象的特性,之後可以使用相關的操作。
public class TestInteger { public static void main(String[] args) { int i = 10; Integer I = new Integer(i);//轉化為Integer類型,也稱裝箱。 int temp = I.intValue(); //將I轉化為基本數據類型,也稱拆箱。 String str_i = Integer.toString(i);//將數字變字元串 int i_i = Integer.parseInt(str_i);//將字元串變數字 System.out.println(str_i); System.out.println(temp); System.out.println(i_i); System.out.println(I.MAX_VALUE);//輸出int能表示的最大值。 } }
運行結果:
10
10
10
2147483647
自動裝箱與自動拆箱
通過上面代碼我們可以看出,都是手動裝箱與拆箱的。
jdk檢查到兩邊類型符合時,會自動裝箱與拆箱無需手動拆箱。
public class TestInteger { public static void main(String[] args) { Integer I = 3; //自動裝箱 Integer I = new Integer(30; int i = I; //自動拆箱 int i = I.intValue(); System.out.println(I); System.out.println(i); System.out.println(I.MAX_VALUE);//輸出int能表示的最大值。 } }
運行結果:
3 3 2147483647
我們來看下下麵這段代碼:
public class TestInteger { public static void main(String[] args) { Integer I1 = 127; Integer I2 = 127; Integer I3 = 129; Integer I4 = 129;
Integer I5 = new Integer(127); System.out.println(I1 == I2);//此處對象比較,比較的是地址值。 System.out.println(I3 == I4);
System.out.println(I1 == I5);//此處為false System.out.println(System.identityHashCode(I1));//這裡列印的hashCode,並不是對象存儲的地址。 System.out.println(System.identityHashCode(I2));//即使是不同對象,也可能有相同的hashCode, System.out.println(System.identityHashCode(I3));//此處只是想描述它們的地址是不同的,但我也不清楚如何獲得對象記憶體地址 System.out.println(System.identityHashCode(I4));//如果有哪位仁兄知道煩請告知,不勝感謝! System.out.println(I1.equals(I2));//此處比較的是數值,//這裡用hashCode當做地址只是為了便於理解,但hashCode不是對象記憶體地址。 System.out.println(I3.equals(I4)); } }
運行結果: true false false 366712642 366712642 1829164700 2018699554 true true
我們可以看到I1 == I2,和 I3 == I4一個為false一個為true。
對此大家可能有疑問,這明顯不科學。我們來看I1,I2,I3,I4的地址。
代碼中列印的是hashCode並不是地址,這樣只是為了便於理解,就姑且把hashCode看做對象地址。
會發現I1和I2地址相同,I3,和I4地址不同,對象比較是比較地址所以才會造成這種結果。
我們看下JDK源碼中的註釋
代表[-128,127]之間的值會被緩存,如果值在這個範圍內就直接引用已經創建好了的。
我們來看JDK源碼中的一部分,high = 127,low = -128;
他會將[-128,127]每一個都提前創建好一個對象。當自動裝箱時,會檢查是否在這個的範圍內,
如果是則直接引用已經創建好了的,如果不是則創建新的對象。
但要註意一點,用new Integer(10)創建無論是否在範圍內都會新建一個對象,所以 I1 == I5 為false。
二、Date
1.Date簡介
Date是時間的核心類,主要用於表示時間。其中表示時間的是一個long型的數值faseTime,單位是ms。
其中有一個基準,為1970-1-1 00:00:00為基準。
當fastTime為1000時代表過了1秒,既1970-1-1 00:00:01。
需要表示1970-1-1 00:01:00 既fastTime = 1000 * 60;
下麵用代碼舉例說明:
import java.util.Date; public class TestDate { public static void main(String[] args) { Date date_now = new Date(); Date date_test = new Date(60000);//此處是60s即一分鐘,60000的單位是ms System.out.println(date_now); System.out.println(date_test); } }
運行結果: Sat Aug 18 21:54:02 CST 2018 Thu Jan 01 08:01:00 CST 1970
我們沒有向Date()中添加參數時,會預設傳遞一個當前時間。
如果傳遞了時間就按傳遞的參數來表示時間。
可我們在date_test中設置是60000應該是1分鐘,顯示的應該是1970-1-1 00:01:00,可最後運行顯示的是
1970-1-1 08:01:00,這是因為我們採用的是中國標準(CST)時間,而作為基準的是GMT時間,中間有八個小時的時差。
輸出改成date_test.toGMTString()就可以輸出GMT時間。1970-1-1 00:01:00
2.Date常用方法
1.getTime()
返回表示當前時間的long型數。
public class TestDate { public static void main(String[] args) { Date date_now = new Date(); Date date_test = new Date(60000); System.out.println(date_now); System.out.println(date_now.getTime());//獲得代表當前時間的long型數值 System.out.println(date_test); System.out.println(date_test.getTime());//獲得代表1970-1-1 00:01:00(GMT)時間的long型數組。 } }
運行結果: Sun Aug 19 11:16:14 CST 2018 1534648574913 Thu Jan 01 08:01:00 CST 1970 60000
2.setTime()
我們看下JDK源碼中也很容易理解,就是設置一個值。
public class TestDate { public static void main(String[] args) { Date date_test = new Date(60000); date_test.setTime(0);//設置為基準時刻(GMT) System.out.println(date_test); System.out.println(date_test.getTime());//獲得代表當前時間的long型數值。 } }
運行結果:
Thu Jan 01 08:00:00 CST 1970
0
3.after()和before()
after測試此日期是否在指定日期之後,是返回true,否返回false。
我們看下源碼中的:
return getMillisOf(this) > getMillisOf(when);
獲取此日期對象的毫秒值 > 獲取指定日期對象的毫秒值。
其實質就是比較日期的long型數值。
同樣before()也類似;
測試此日期是否在指定時間之前,是返回true,否返回false。
public class TestDate { public static void main(String[] args) { Date date_test = new Date(0); Date date_now = new Date(); System.out.println(date_now.after(date_test));//當前日期是否在1970年基準時刻之後 System.out.println(date_now.before(date_test));//當前日期是否在1970年基準時刻之前 } }
運行結果: true false
4.toString()
首先顯然這個重寫了Object類中的toString()方法。
我們看源碼中註釋部分的格式是否似曾相識?
我們來看這個:Thu Jan 01 08:00:00 CST 1970
我們會發現輸出時間時就是按照這種格式輸出的。
public class TestDate { public static void main(String[] args) { Date date_test = new Date(0); System.out.println(date_test); System.out.println(date_test.toString());//按指定格式輸出時間 } }
運行結果:
Thu Jan 01 08:00:00 CST 1970 Thu Jan 01 08:00:00 CST 1970
我們會發現調用或者不調用tiString()輸出的格式都是一樣的,說明輸出時預設調用了toString()按照指定的格式打出時間。
三、DateFormat和SimpleDateFormat
從類名的翻譯來看就可以大概看出這兩個類是做什麼的。
日期格式,簡單日期格式。可以看出這兩個類與日期格式有關
它們可以幫助我們按指定日期格式轉換。
由於DateFormat是抽象類無法直接創建對象,所以我們需要通過它的子類SimpleDateFormat創建對象。
1.format(Date);
format可以將日期轉化為指定格式的字元串。
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; public class TestSimpleDateFormat { public static void main(String[] args) { Date date = new Date(); DateFormat China_time = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");//創建一個時間格式"yyyy-MM-dd hh-mm-ss" String date_str = China_time.format(date);//將當前時間轉換為指定格式的字元串 System.out.println(date_str); } }
運行結果: 2018-08-19 03-47-47
//即yyyy-MM-dd hh-mm-ss(年月日時分秒)
可以看到最後是按照我們指定的格式輸出。 我們可以自行定義格式比如(ss -mm-hh dd-MM-yy)秒分時日月年,並且年份顯示兩位(會自動顯示後兩位)。
我們來看這一句 DateFormat China_time = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");其中有一個向上轉型。如果子類中重寫了父類的方法,那麼調用的是子類的,反之調用的是父類的。(此處子類中有同名的方法但返回值不同故不構成重寫,調用的是父類(DateFormat)中的方法。
2.parse()
將字元串轉換為指定格式的日期對象,輸入的字元串格式要和指定的格式相同。
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class TestSimpleDateFormat { public static void main(String[] args) { Date date = new Date(); DateFormat China_time = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");//創建一個時間格式"yyyy-MM-dd hh-mm-ss" String date_str = "2018-8-19 16-18-00";//字元串格式必須和設定格式相同,不然會解析錯誤 try { date = China_time.parse(date_str);//將當前字元串按指定格式轉換為時間。 } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(date); } }
運行結果:
Sun Aug 19 16:18:00 CST 2018
下麵有一張表代表了各個字母的含義:
四、Calendar與GregorianCalendar
Calendar類是一個抽象類提供了時間的展示及計算功能,同樣需要通過其子類來創建。
1.get(int filed)
filed為指定屬性,指定什麼就會根據方法的功能得到對應的數據。
例如指定field為Cnlendar.year就代表獲得當前日曆對象的年份。
import java.util.Calendar; import java.util.GregorianCalendar; public class TestCalendar { public static void main(String[] args) { Calendar now = new GregorianCalendar();//構造器沒有參數時預設傳遞當前時間 Calendar c = new GregorianCalendar(2008,8,8); //構造器有很多重載的方法可以設置年月日時分秒等... int year = c.get(Calendar.YEAR); //獲得該對象年份的值 int month = c.get(Calendar.MONTH);//獲得該對象月份的值 int day = c.get(Calendar.DAY_OF_MONTH); //獲得該對象在這個月中天數的值。 int year_now = now.get(Calendar.YEAR); int month_now = now.get(Calendar.MONTH); int day_now = now.get(Calendar.DAY_OF_MONTH); System.out.println(year + "-" + month + "-" + day);//輸出設置時間年月日的值 System.out.println(year_now + "-" + month_now + "-" + day_now);//輸出當前時間年月日的值。 } }
運行結果:
2008-8-8 2018-7-19
//我這裡當前時間時2018-8-19
看到上述大家可能會有疑問,獲取當前月的值8月應該是8呀,為什麼列印出來的確是7。
首先8月只是我們國內的說法,並不是通用的。國外沒有八月,只有August。
JDK源碼中0代表January即一月,11代表12月。所以但實際上代表八月的數值常量是7.
我們設置的8其實不是八月,我們設置的是數值8,數值8代表的是九月。
我們看下麵一個例子。
import java.util.Calendar; import java.util.GregorianCalendar; public class TestCalendar { public static void main(String[] args) { Calendar c = new GregorianCalendar(2008,Calendar.AUGUST,8);//此處設置的是8月August int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_MONTH); System.out.println(year + "-" + month + "-" + day); } }
運行結果:
2008-7-8//最後運行是7.說明代表八月的常量是7
同樣星期天的常量值是1,星期一是2,。。。星期六是7
2.getTime(),getTimeMillis()
getTimeMillis()是返回當前日曆對象的時間值,返回的是一個long型的毫秒值。
getTime() 是返回一個時間類的對象,而且其中調用了getMillis(),並將其設置為時間。
import java.util.Calendar; import java.util.GregorianCalendar; public class TestCalendar { public static void main(String[] args) { Calendar c = new GregorianCalendar(2008,Calendar.AUGUST,8);//設置時間為2008-8-8 int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_MONTH); System.out.println(c.getTimeInMillis());//獲取代表當前日曆對象的時間值 System.out.println(c.getTime()); //將日曆對象時間設置為Date類對象的時間,並返回一個Date對象。簡單說就是將Calendar類對象轉換為Date類對象。 System.out.println(year + "-" + month + "-" + day); } }
運行結果: 1218124800000 Fri Aug 08 00:00:00 CST 2008 2008-7-8
3.add(field,amount);
日期計算,這是很強大的一個方法。可以進行日期的計算,如加減一(年、月、日)。
field指定操作的屬性是年還是月還是日......,後面代表加減的數值。
import java.util.Calendar; import java.util.GregorianCalendar; public class TestCalendar { public static void main(String[] args) { Calendar c = new GregorianCalendar(2008,Calendar.AUGUST,8);//2008-8-8 System.out.println(c.getTime()); c.add(Calendar.YEAR, 1);//加一年 c.add(Calendar.MONTH,1);//加一月 c.add(Calendar.DAY_OF_MONTH, 2);//加兩天 c.add(Calendar.DATE, -1); //減一天,DATE和DAY_OF_MONTH是一樣的,它們的常量值都是5; System.out.println(c.getTime());//最後加了一年一月一天。 } }
運行結果: Fri Aug 08 00:00:00 CST 2008 Wed Sep 09 00:00:00 CST 2009
下麵有一個小小例子,剛好可以鞏固下前面學的幾個時間類。
簡易日曆,輸入年月日,輸出對應的月份的日曆。
import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Scanner; public class TestDate { public static void main(String[] args) { Date date = new Date(); //創建一個時間對象,用於存放輸入時間。 Scanner input = new Scanner(System.in); //創建一個輸入 System.out.println("請按提示格式輸入日期:例:(2000-1-1)"); String inputDateString = input.nextLine(); //輸入時間的字元串格式必須與後面指定格式相同。 DateFormat chinaTimeFormat = new SimpleDateFormat("yyyy-MM-dd");//註意此處格式 try { date = chinaTimeFormat.parse(inputDateString);//將輸入的字元串轉換成時間對象 } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } Calendar cn_InputDate = new GregorianCalendar();//創建兩個日曆對象。 Calendar cn_PrinfDate = new GregorianCalendar();//一個用於存儲輸入日期,一個用於列印。 cn_InputDate.setTime(date);//將輸入的時間設置到用於存放日期的日曆類。 System.out.println("日\t一\t二\t三\t四\t五\t六"); cn_PrinfDate.set(cn_InputDate.get(Calendar.YEAR), cn_InputDate.get(Calendar.MONTH), 1);//列印總是從1號開始,所以將輸入的日期設置為1。 for(int i = 1; i < cn_PrinfDate.get(Calendar.DAY_OF_WEEK); i++){ //需要列印的空格數。即1號從星期幾開始。 System.out.print("\t");//一個\t代表一個製表位八個空格。 } for(int i = 1; i <= getMaxDaysOfMonth(cn_InputDate.get(Calendar.YEAR),cn_InputDate.get(Calendar.MONTH));i++){//日期從1號開始列印 if(i == cn_InputDate.get(Calendar.DAY_OF_MONTH)){//如果當前要列印的i和輸入日期中的day相同就加個* System.out.printf(i + "*\t"); //\t的作用可參考:https://blog.csdn.net/hju22/article/details/79773252 }else{ System.out.printf(i + "\t"); } if(cn_PrinfDate.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY){//如果周六列印完就換行。 System.out.println(); } cn_PrinfDate.add(Calendar.DAY_OF_MONTH, 1);//每列印一天,日期增加一天。 } } private static int getMaxDaysOfMonth(int year, int month){ //獲取當前月份最大天數的函數。主要是判斷閏年與否 int M[] = {31,28,31,30,31,30,31,31,30,31,30,31}; int M2[] = {31,29,31,30,31,30,31,31,30,31,30,31}; if((year % 4 == 0) && (year % 100 != 0)){ return M2[month];//是閏年採用閏年的天數,反之採用非閏年天數。 }else { return M[month];//由於剛好get(Calendar.MONTH)獲取到月份的數值是從0開始和數組的的下標對應。 } } }