21天學會Java之(Java SE第九篇):常用類、常用API

在實際開發工作中,我們會使用到一些操作,這些操作在Java中都已經封裝好了相應的類包供我們使用。

包裝類

包裝類的定義

Java是面向對象的語言,但並不是“純面向對象”的,因爲我們經常用到的基本數據類型就不是對象。但是我們在實際應用中經常需要將基本數據轉化成對象,以便於操作。

爲了解決這個問題,Java在設計類時爲每個基本數據類型設計了一個對應的類進行代表,這樣八個和基本數據類型對應的類統稱爲包裝類,以下就是每種基礎數據類型所對應的包裝類。

基礎數據類型 包裝類
byte Byte
boolean Boolean
short Short
char Character
int Integer
long Long
float Float
double Double

包裝類的用途

  1. 作爲和基本數據類型對應的類型存在,方便涉及到對象的操作,如Object[]、集合等的操作。
  2. 包含每種基本數據類型的相關屬性如最大值、最小值等,以及相關的操作方法(這些操作方法的作用是在基本數據類型、包裝類對象、字符串之間提供相互之間的轉化!)。

以下例子歸納了包裝類的常用用法,別的不常用的方法可以查看API文檔:

public class Test {
    /** 測試Integer的用法,其他包裝類與Integer類似 */
    public void testInteger() {
        // 基本類型轉化成Integer對象
        Integer int1 = new Integer(10);
        Integer int2 = Integer.valueOf(20); // 官方推薦這種寫法
        // Integer對象轉化成int
        int a = int1.intValue();
        // 字符串轉化成Integer對象
        Integer int3 = Integer.parseInt("334");
        Integer int4 = new Integer("999");
        // Integer對象轉化成字符串
        String str1 = int3.toString();
        // 一些常見int類型相關的常量
        System.out.println("int能表示的最大整數:" + Integer.MAX_VALUE); 
    }
    public static void main(String[] args) {
        Test test  = new Test();
        test.testInteger();
    }
}

自動裝箱和拆箱

  • 自動裝箱: 基本類型的數據處於需要對象的環境中時,會自動轉爲“對象”。自動裝箱過程是通過自動調用包裝類的valueOf()方法實現的。

  • 自動拆箱: 每當需要一個值時,對象會自動轉成基本數據類型,沒必要再去顯式調用intValue()、doubleValue()等轉型方法。自動拆箱過程是通過調用包裝類的xxxValue()方法實現的(xxx代表對應的基本數據類型,如intValue()、doubleValue()等)。

    以下例子展示了自動裝拆箱的使用:

public class TestAutoBox {
	public static void main(String[] args) {
		Integer a=123;  //自動裝箱:Integer a=Integer.valueOf(123);
		int b=a;  		//自動拆箱:int b=a.intValue();
		
		Integer c=null;
		if (c!=null) {  //檢測c是否爲空值,防止空指針異常
			int d=c;  //自動拆箱:調用了intValue();
		}
	}
}

包裝類的緩存問題

整型、char類型所對應的包裝類,在自動裝箱時,對於-128~127之間的值會進行緩存處理,其目的是提高效率。

緩存處理的原理爲:如果數據在-128~127這個區間,那麼在類加載時就已經爲該區間的每個數值創建了對象,並將這256個對象存放到一個名爲cache的數組中。每當自動裝箱過程發生時(或者手動調用valueOf()時),就會先判斷數據是否在該區間,如果在則直接獲取數組中對應的包裝類對象的引用,如果不在該區間,則會通過new調用包裝類的構造方法來創建對象,可以參考以下例子更直觀的明白原理:

public class Test {
	public static void main(String[] args) {
		//緩存[-128,127]之間的數字。實際就是系統初始的時候,創建了[-128,127]之間的一個緩存數組
		//當我們調用valueOf()的時候,首先檢查是否在[-128,127]之間,如果在這個範圍則直接從緩存數組中拿出已經建好的對象
		//如果不在這個範圍,則創建新的Integer對象
		Integer in1=Integer.valueOf(-123);
		Integer in2=-123;
		System.out.println(in1==in2);  //true,-123在緩存範圍之內
		System.out.println(in1.equals(in2));  //true
		Integer in3=1234;
		Integer in4=1234;
		System.out.println(in3==in4);  //false,1234不在緩存範圍之內
		System.out.println(in3.equals(in4));  //true
	}
}

String類

在Java中沒有內置的字符串類型,而是再標準Java類庫中提供了一個預定義的類,這個類就是String類,String類對象代表不可變的Unicode字符序列,因此我們可以將String對象稱爲“不可變對象”。

String類的基本用法

public class TestString {
	public static void main(String[] args) {
		String s1=new String("abcdef");
		String s2=s1.substring(1, 5);
		System.out.println(s1);
		System.out.println(s2);
		System.out.println("#####################");
		//不是同一個對象
		System.out.println(Integer.toHexString(s1.hashCode()));
		System.out.println(Integer.toHexString(s2.hashCode()));
		System.out.println("#####################");
		
		//字符串的拼接
		String str01="abc";
		String str02=new String("def");
		String str03="abc"+"defg";
		String str04="18"+19;  //有一個字符串就不是加法,是字符串連接符,輸出1819
		//編譯器做了優化,直接在編譯的時候將字符串進行拼接
		String str1="hello"+" java";
		String str2="hello java";
		System.out.println(str1==str2);  //true
		String str3="hello";
		String str4=" java";
		//編譯的時候不知道變量中存儲的是什麼,所以沒辦法在編譯的時候優化
		String str5=str3+str4;
		System.out.println(str2==str5);  //false
		System.out.println(str2.equals(str5));  //true,做字符串比較的時候,使用equals不要使用==
	}
}

String類的常用方法

以下展示了String類常用的幾種方法,更詳細的內容在需要使用時可以查看API文檔:

public class TestStringClassVoid {
	public static void main(String[] args) {
		String str1="core Java";
		String str2="Core Java";
		System.out.println(str1.charAt(3));  //提取指定索引(3,從0開始)的字符
		System.out.println(str2.length());  //字符串的長度
		System.out.println(str1.equals(str2));  //比較兩個字符串是否相等
		System.out.println(str1.equalsIgnoreCase(str2));  //比較兩個字符串是否相等(忽略大小寫)
		System.out.println(str1.indexOf("Java"));  //字符串str1中出現Java的位置(從0開始)
		System.out.println(str1.indexOf("apple"));  //字符串str1中出現apple的位置(從0開始,沒有出現返回-1)
		String str=str1.replace(" ", "&");  //替換字符串裏的字符
		System.out.println(str);
		
		System.out.println("###################");
		String s= "";
		String s1="How are you?";
		System.out.println(s1.startsWith("How"));  //是否以"How"開頭
		System.out.println(s1.endsWith("you"));  //是否以"you"結尾
		s=s1.substring(4);  //提取子字符串:從下標爲4開始到結尾爲止(從0開始)
		System.out.println(s);
		s=s1.substring(4, 7);  //提取子字符串[4,7) 不包括7(從0開始)
		System.out.println(s);
		s=s1.toUpperCase(); //轉大寫
		System.out.println(s);
		s=s1.toLowerCase(); //轉小寫
		System.out.println(s);
		String s2="  How old are you?   ";
		s=s2.trim();  //刪收尾空格(中間的空格不會刪除)
		System.out.println(s);
		System.out.println(s2);  //因爲String是不可變字符串,所以s2不變(僅將結果賦給s,所以s2不變)	
	}
}

StringBuffer和StringBuilder

StringBuffer和StringBuilder非常類似,均代表可變的字符序列。 這兩個類都是抽象類AbstractStringBuilder的子類,方法幾乎一模一樣。

可變字符序列和不可變字符序列使用的陷阱

public class TestStringAndStringBuilder {
	public static void main(String[] args) {
		/**使用String進行字符串的拼接*/
		String str="";
		//本質上使用StringBuilder拼接,但是每次循環都會生成一個StringBuilder對象
		long num1=Runtime.getRuntime().freeMemory();  //獲取系統剩餘內存空間
		long time1=System.currentTimeMillis();  //獲取系統當前時間
		for (int i = 0; i < 5000; i++) {
			str=str+i;  //相當於產生了10000個對象,每次i要加上去要產生一個i的字符串
		}
		long num2=Runtime.getRuntime().freeMemory();
		long time2=System.currentTimeMillis();
		System.out.println("String佔用內存:"+(num1-num2));
		System.out.println("String佔用時間:"+(time2-time1));
		
		/**使用StringBuilder進行字符串的拼接*/
		StringBuilder sb=new StringBuilder();
		long num3=Runtime.getRuntime().freeMemory();  //獲取系統剩餘內存空間
		long time3=System.currentTimeMillis();  //獲取系統當前時間
		for (int i = 0; i < 5000; i++) {
			sb.append(i);
		}
		long num4=Runtime.getRuntime().freeMemory();
		long time4=System.currentTimeMillis();
		System.out.println("StringBuilder佔用內存:"+(num3-num4));
		System.out.println("StringBuilder佔用時間:"+(time4-time3));
	}
}

StringBuilder、StringBuffer的使用以及常用方法

StringBuilder和StringBuffer的方法幾乎一樣,所以以下用StringBuilder爲例:

public class TestStringBuilderVoid {
	public static void main(String[] args) {
		String str;  //private final char value[];(不可變字符序列)
		
		//StringBuilder線程不安全,效率高(一般使用它);StringBuffer線程安全,效率低
		StringBuilder str1=new StringBuilder("abcdefg");  //char[] value;(可變字符序列)
		
		System.out.println(Integer.hashCode(str1.hashCode()));
		System.out.println(str1);
		System.out.println("##############");
		str1.setCharAt(2, 'S');
		System.out.println(Integer.hashCode(str1.hashCode()));
		System.out.println(str1);
		
		System.out.println("###########常用方法############");
		StringBuilder sb=new StringBuilder();
		for (int i = 0; i < 26; i++) {
			char temp=(char)('a'+i);
			sb.append(temp);  //在可變字符序列後加一個字符
		}
		
		System.out.println(sb);
		sb.reverse();  //倒序
		System.out.println(sb);
		sb.setCharAt(3, '王');  //改變可變字符序列指定位置的字符
		System.out.println(sb);
        //因爲字符串的底層爲數組,所以它的索引值從0開始
		//鏈式調用(可反覆調用),核心就是:該方法調用了return this,把自己返回了.
		sb.insert(0, '6').insert(1, 5);  //在指定的位置插入一個字符
		System.out.println(sb);
		//同樣支持鏈式調用
		sb.delete(0, 2).delete(3, 4);  //刪除指定位置的字符
		System.out.println(sb);
	}
}

String、StringBuilder和StringBuffer的使用區別

  1. String:不可變字符序列。
  2. StringBuffer:可變字符序列,並且線程安全,但是效率低。
  3. StringBuilder:可變字符序列,線程不安全,但是效率高(一般用它)。

時間處理類

Date類(時間類)

public class TestDate {
	public static void main(String[] args) {
		Date d1=new Date(2000);
		System.out.println(d1);
		
		Date d2=new Date();
		System.out.println(d2.getTime());  //時間戳(輸出自從1970 年 1 月 1 日 00:00:00 GMT以來的指定毫秒數)
		System.out.println(d1.after(d2));  //測試此日期是否在指定日期之後
		System.out.println(d1.before(d2));  //測試此日期是否在指定日期之前
		System.out.println(d1.equals(d2));  //比較兩個日期的相等性
		
		//以後遇到時間處理:使用Candlendar類
		Date date=new Date(2020-1900,0,1);  //2020年1月1日
		System.out.println(date);
	}
}  

DateFormat類和SimpleDateFormat類(時間格式轉換)

把時間對象轉化成指定格式的字符串。反之,把指定格式的字符串轉化成時間對象。

DateFormat是一個抽象類,一般使用它的的子類SimpleDateFormat類來實現。

public class TestDateFormat {
	public static void main(String[] args) throws ParseException {
		
		//把時間對象按照“格式字符串指定的格式”轉成相應的字符串
		DateFormat df1=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		String str=df1.format(new Date(1500000));
		System.out.println(str);
		
		//把字符串按照“格式字符串指定的格式”轉成相應的時間對象
		DateFormat df2=new SimpleDateFormat("yyyy年MM月dd日 hh時mm分ss秒");
		Date date =df2.parse("2020年1月1日 1時1分1秒");
		System.out.println(date);
		
		//測試其他的格式字符.例如:利用w和D,獲得本時間對象所處年份的第幾周,第幾天.
		DateFormat df3=new SimpleDateFormat("第w周,第D天,E");
		String string=df3.format(new Date());
		System.out.println(string);
	}
}

格式字符串指定的格式如下圖示例:

Calendar(日曆類)

Calendar 類是一個抽象類,爲我們提供了關於日期計算的相關功能,比如:年、月、日、時、分、秒的展示和計算。

public class TestCalendar {
	public static void main(String[] args) {
		Calendar calendar=new GregorianCalendar(3000,0,1,1,1,1);
		int year=calendar.get(Calendar.YEAR);
		int month=calendar.get(Calendar.MONTH);  //0-11表示對應的月份.0是一月,1是二月.........11是12月.
		int day=calendar.get(Calendar.DATE);  //也可使用:DATE_OF_MONTH
		int weekday=calendar.get(Calendar.DAY_OF_WEEK);  //1-7表示對應周幾.1是星期日,2是星期一......7是星期六
		System.out.println(year+"年"+month+"月"+day+"日");
		System.out.println(weekday);
		System.out.println("##############");
		
		//設置日期的相關元素
		Calendar c1=new GregorianCalendar();
		c1.set(Calendar.YEAR, 6666);
		System.out.println(c1);
		System.out.println("##############");
		
		//日期的計算
		Calendar c2=new GregorianCalendar();
		c2.add(Calendar.YEAR, 100);
		System.out.println(c2);
		System.out.println("##############");
		
		//日期對象和時間對象的轉化
		Date date=c2.getTime();
		System.out.println(date);
		Calendar c3=new GregorianCalendar();
		c3.setTime(new Date(2000));
		System.out.println(c3);
		System.out.println("##############");
		
		printCalender(new GregorianCalendar());
		
	}
	
	
	public static void printCalender(Calendar c) {
		//打印:1918年10月10日 11:23:45 週四
		int year=c.get(Calendar.YEAR);
		int month=c.get(Calendar.MONTH)+1;  //0-11
		String monthString=month<10?"0"+month:month+"";
		int day=c.get(Calendar.DATE);
		String dayString=day<10?"0"+day:day+"";
		int hour=c.get(Calendar.HOUR);
		String hourString=hour<10?"0"+hour:hour+"";
		int minute=c.get(Calendar.MINUTE);
		String minuteString=minute<10?"0"+minute:minute+"";
		int second=c.get(Calendar.SECOND);
		String secondString=second<10?"0"+second:second+"";
		int dayweek=c.get(Calendar.DAY_OF_WEEK)-1;  //0-6
		String dayweekString="";
		switch (dayweek) {
		case 0:
			dayweekString=" 週日";
			break;
		case 1:
			dayweekString=" 週一";
			break;
		case 2:
			dayweekString=" 週二";
			break;
		case 3:
			dayweekString=" 週三";
			break;
		case 4:
			dayweekString=" 週四";
			break;
		case 5:
			dayweekString=" 週五";
			break;
		case 6:
			dayweekString=" 週六";
			break;
		}
		System.out.println(year+"年"+monthString+"月"+dayString+"日 "+hourString+":"+minuteString+":"+secondString+dayweekString);
	}
}
  • 注意事項
  1. 注意月份的表示,一月是0,二月是1,以此類推,12月是11。 因爲大多數人習慣於使用單詞而不是使用數字來表示月份,這樣程序也許更易讀,父類Calendar使用常量來表示月份:JANUARY、FEBRUARY等等。
  2. 週日代表的是一週的第一天

Math類

Math類的常用方法

public class TestMath {
	public static void main(String[] args) {
		//取整相關操作
		System.out.println(Math.ceil(3.2));  //進1法
		System.out.println(Math.floor(3.2));  //去掉小數取整
		//四捨五入
		System.out.println(Math.round(3.4));
		System.out.println(Math.round(4.5));
		
		//絕對值、開方、a的b次冪等操作
		System.out.println(Math.abs(-50));  //取絕對值
		System.out.println(Math.sqrt(9));  //開方
		System.out.println(Math.pow(2, 3));  //a的b次冪
		System.out.println(Math.pow(3, 2));  //a的b次冪
		
		//Math類中常用的常量
		System.out.println(Math.PI);
		System.out.println(Math.E);
		
		//隨機數
		System.out.println(Math.random());  //[0,1)
	}
}

Random類的常用方法

public class TestRandom {
	public static void main(String[] args) {
		Random rand=new Random();
		System.out.println(rand.nextDouble());  //隨機生成[0,1)之間的double類型的數據
		System.out.println(rand.nextInt());  //隨機生成int允許範圍之內的int類型數據
		System.out.println(rand.nextFloat());  //隨機生成[0,1)之間的float類型的數據
		System.out.println(rand.nextBoolean());  //隨機生成true或false
		System.out.println(rand.nextInt(10));  //隨機生成[0,10)之間的int類型數據
		System.out.println(20+rand.nextInt(10));  //隨機生成[20,30)之間的int類型數據
		
		System.out.println(20+(int)(rand.nextDouble()*10));  //隨機生成[20,30)之間的int類型數據(此方法計算較爲複雜)
	}
}

File類

路徑的常用表達

public class TestPath {
	public static void main(String[] args) {
		String path="D:\\test\\test.txt";
		System.out.println(path);
		System.out.println(File.separator);
		
		/*路徑的表達方式(常用)*/
		//1./
		path="D:/test/test.txt";
		System.out.println(path);
		
		//2.File.separator常量拼接
		path="D:"+File.separator+"test"+File.separator+"test.txt";
		System.out.println(path);
	}
}

File類的常用操作

public class TestFile {
	public static void main(String[] args) throws IOException {
		File file=new File("d:/a.txt");
//		File file=new File("d:\\a.txt");
		System.out.println(file);
		
		//文件重命名
		file.renameTo(new File("d:/bb.txt"));
		
		//加載當前用戶目錄
		System.out.println(System.getProperty("user.dir"));
		
		//創建新文件(默認是當前用戶目錄)
		File f=new File("gg.txt");
		f.createNewFile();
		
		System.out.println("File是否存在:"+f.exists());
		System.out.println("File是否是目錄:"+f.isDirectory());
		System.out.println("File是否是文件:"+f.isFile());
		System.out.println("File最後修改時間:"+new Date(f.lastModified()));  //返回Date類
		System.out.println("File的大小:"+f.length());
		System.out.println("File的文件名:"+f.getName());  //獲取對象的名稱
		//獲取對象的路徑(構建時傳入的是相對路徑就返回相對路徑,傳入絕對路徑就返回絕對路徑)
		System.out.println("File的目錄路徑:"+f.getPath());  //僅顯示文件名爲當前目錄路徑
		System.out.println("File的絕對目錄路徑:"+f.getAbsolutePath());  //獲取對象的絕對路徑
		//獲取對象的父路徑(即文件名稱前的路徑),構建的時候有就返回,沒有就返回null
		System.out.println(f.getParent());
		
		//文件狀態判定
		File fileStatus=new File("D:/a.txt");
		if (null== fileStatus || !fileStatus.exists()) {
			System.out.println("文件不存在!");
		}else {
			if (fileStatus.isFile()) {
				System.out.println("文件操作");
			}else {
				System.out.println("文件夾操作");
			}
		}
		System.out.println("#################");
		//文件的創建以及刪除
		File newFile=new File("newFile.txt");
		boolean flag=newFile.createNewFile();  //創建文件,如果文件已存在,則創建失敗返回false
		System.out.println(flag);
		flag=newFile.delete();  //刪除已經存在的文件
		System.out.println(flag);
		
		System.out.println("#################");
		//con和com3是操作系統的設備名,不能正確創建
		File newFileTest=new File("D:/con");
		flag=newFileTest.createNewFile();
		System.out.println(flag);
		
		//mkdir或mkdirs僅用來創建目錄不能創建文件
		File f2=new File("d:/電影/華語/大陸");
		boolean flag1=f2.mkdir();  //目錄結構中有一個不存在,則不會創建整個目錄樹
		System.out.println(flag1);  //創建失敗
		
		File f3=new File("d:/電影/華語/大陸/");
		boolean flag2=f3.mkdirs();  //目錄結構中有一個不存在也沒關係,創建整個目錄樹
		System.out.println(flag2);  //創建成功
		
		System.out.println("#############");
		File dir=new File("D:/eclipse-workspace/");
		
		//list方法返回下級名稱
		String[] subStrings=dir.list();
		for (String s : subStrings) {
			System.out.println(s);
		}
		
		System.out.println("#############");
		//listFiles返回下級的所有File對象
		File[] subFiles=dir.listFiles();
		for (File files : subFiles) {
			System.out.println(files);
		}
		
		//列出所有盤符
		File[] roots=dir.listRoots();
		for (File r : roots) {
			System.out.println(r.getAbsolutePath());
		}
	}
}

枚舉類

public class TestEnum {
	public static void main(String[] args) {
		System.out.println(Season.SPRING);
		
		Season season=Season.AUTUMN;
		switch (season) {
		case SPRING:
			System.out.println("春天");
			break;
		case SUNMMER:
			System.out.println("夏天");
			break;
		case AUTUMN:
			System.out.println("秋天");
			break;
		case WINTER:
			System.out.println("冬天");
			break;
		}
	}
}

//枚舉類型隱性地繼承自java.lang.Enum,枚舉實質上還是類
//每個被枚舉的成員實質就是一個枚舉類型的實例,默認都是public static final修飾的(常量)
enum Season{
	SPRING,SUNMMER,AUTUMN,WINTER
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章