Java-J2SE專題複習

J2SE-->J2EEjava

因爲一些類很是的經常使用,因此將其放置在java.lang包中,而且自動導入java.lang中的全部類。程序員

一、數組和集合類正則表達式

1.一、數組編程

    數組的定義數組

//定義了一個num1變量能夠存儲3個int類型的數字
		int[] num1 = new int[3]; //定義的時候肯定大小
		int num[] = new int[4]; //不建議使用
		num1[0] = 10;
		num1[1] = 11;
		num1[2] = 12;
		System.out.println(num1[0]+","+num1[1]+","+num1[2]);
		
		int[] num2 = {13,14,15}; //定義的時候直接賦初始值
		System.out.println(num2[0]+","+num2[1]+","+num2[2]);

    

    數組的遍歷緩存

//num2.length獲取數組的長度
		for(int i=0;i<num2.length;i++) {
			System.out.println(num2[i]);
		}

1.二、集合類安全

    集合類能夠提供一些方便的操做來替代數組,集合類都在java.util包中,主要的結構服務器

List簡介網絡

List list = new ArrayList();
  //經過add()添加元素
  list.add("123");
  list.add("234");
  list.add("345");
  list.add("456");
  
  list.remove("345");
  //經過size()能夠獲取列表的長度,注意size()是方法
  for(int i=0;i<list.size();i++) {
   //經過get()能夠獲取某一位置的元素
   //get()的元素是Object的,因此須要進行強制類型轉換
   String str = (String)list.get(i);
   System.out.println(str);
  }

    以上操做是有風險的多線程

list.add("456");
list.add(111);

    因爲是基於Object來添加的,因此也能夠添加其它類型的值,這個時候在進行強制類型轉換

    的時候,就會拋出異常。

泛型:使用泛型能夠有效的解決基於Object添加的問題,泛型是在JDK1.5以後纔出現的。

//使用了泛型後,說明這個list中只能添加String類型的值
		List<String> list = new ArrayList<String>();
		list.add("123");
		list.add("abc");
		list.add("456");
		
		for(int i=0;i<list.size();i++) {
			//使用了泛型,就不用進行強制類型轉換了
			String str = list.get(i);
			System.out.println(str);
		}

封裝類

對於8種基本數據類型,都提供了相應的封裝類來將這些基本數據類型封裝爲對象。

特別注意:在JDK1.5以後提供了自動的封裝和解封裝,若是是1.4以前均須要手動解封裝。

    

Integer num1 = 10; //JDK1.5以後提供了自動封裝
		Integer num2 = new Integer(10); 
                //JDK1.5以前的版本要建立Integer須要經過構造函數
		
		int num3 = num1; //JDK1.5以後會自動將Integer轉換爲int
		int num4 = num2.intValue(); 
                //JDK1.5以前須要使用Integer的intValue()方法轉換
		
		String str = "123";
		System.out.println(str+1);
		//parseInt是一個static的方法,能夠將字符串轉換爲整型
		int a = Integer.parseInt(str);
		/*
		 * 對於其餘封裝類而言均有相應的parseXXX來將字符串轉換爲其它類型的值
		 */
		
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		list.add(4);
		list.add(5);
		//此處若是僅僅使用remove(2)會移除下標爲2的元素
                //若是要移除對象須要將2轉換爲Integer
		list.remove(new Integer(2));

Iterator迭代器

對於全部的集合類,都提供了一個基於迭代器的遍歷方式。

    

//建立一個迭代器,因爲Collection經過iterator方法建立迭代器,因此全部集合類都擁有這個方法
		Iterator<String> it = str.iterator();
		//Iterator中有hasNext()來檢查元素是否存在
		while(it.hasNext()) {
			//經過next()方法能夠獲取下一個元素
			String s = it.next();
			System.out.println(s);
		}
		
		/*
		 * Set沒有順序,因此沒有get()方法
		 * for(int i=0;i<str.size();i++) {
			String s = str.g
		}*/
//List也可使用迭代器
		Iterator<Integer> it = list.iterator();
		for(;it.hasNext();) {
			int num = it.next();
			System.out.println(num);
		}

一、使用迭代器會有一個問題,不太方便獲取下標;

二、在列表數據的時侯,須要刪除元素時,不建議使用迭代器的方式。

//List也可使用迭代器
		Iterator<Integer> it = list.iterator();
		for(;it.hasNext();) {
			int num = it.next();
			//刪除時會報錯
			/*if(num==3) {
				list.remove(new Integer(num));
			}*/
			System.out.println(num);
		}

在JDK1.5以後又提供一種加強的for循環來遍歷列表和數組,原理基於迭代器。

List<String> strs = new ArrayList<String>();
		strs.add("abc");
		strs.add("def");
		strs.add("ghj");
		//會使用str來遍歷集合中的每個元素
		for(String str:strs) {
			System.out.println(str);
		}
		System.out.println("===============憂傷的分割線===================");
		Set<String> sets = new HashSet<String>();
		sets.add("qwe");
		sets.add("asd");
		sets.add("zxc");
		for(String str:sets) {
			System.out.println(str);
		}
		System.out.println("--------------------傲嬌的分割線---------------------");
		Integer[] nums = {2,3,4,5,6,7};
		for(Integer num:nums) {
			System.out.println(num);
		}

Set和List

/*
 * List和Set的區別
 * 一、List有序而Set無序
 * 二、Set不能添加劇復的元素,List能夠添加劇復的元素
 */
public class TestListSet {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("aaaa");
		list.add("bbbb");
		list.add("cccc");
		list.add("dddd");
		list.add("aaaa");
		for(String str:list) {
			System.out.println(str);
		}
		System.out.println("---------------------------------");
		Set<String> set = new HashSet<String>();
		set.add("abcd");
		set.add("acbd");
		set.add("adbc");
		set.add("cabd");
		set.add("abcd");
		for(String str:set) {
			System.out.println(str);
		}
		
		//去掉List中重複的元素
		List<Integer> ls = Arrays.asList(1,2,3,4,5,6,5,4,3,2,1);
//		Set<Integer> ss = new HashSet(ls);
		Set<Integer> ss = new HashSet<Integer>();
		ss.addAll(ls);
		for(Integer num:ss) {
			System.out.println(num);
		}
	}

Map

//Map存儲的是鍵值對,key和value
		Map<Integer,String> maps = new HashMap<Integer,String>();
		//使用put方法添加值
		maps.put(1, "張三");
		maps.put(2, "李四");
		maps.put(3, "王五");
		maps.put(4, "趙六");
		//使用get(key)能夠獲得value
		System.out.println(maps.get(3));
		
		//keySet能夠將maps中的key轉換爲Set的一組列表
		Set<Integer> keys = maps.keySet();
		//遍歷Set能夠獲得相應的key,使用maps.get(key)能夠獲得value
		for(Integer i:keys) {
			System.out.println(maps.get(i));
		}
		
		//此時不會增長,會覆蓋
		maps.put(4, "老七");
		System.out.println("----------------------");
		//keySet能夠將maps中的key轉換爲Set的一組列表
		keys = maps.keySet();
		//遍歷Set能夠獲得相應的key,使用maps.get(key)能夠獲得value
		for(Integer i:keys) {
			System.out.println(maps.get(i));
		}
		
		System.out.println(maps.containsKey(4));
		System.out.println(maps.containsValue("老七"));

二、異常處理

使用異常的緣由

傳統的處理方式是使用if else來進行判斷,這樣將會有大量的if嵌套,會嚴重影響代碼的編寫效率和可讀性。

Java的異常處理方式

try {
    //把可能發生異常的代碼放到try語句塊中
} catch() {  //爲不一樣的異常使用不一樣的catch來進行捕獲
} catch() {
} catch() {

}

2.一、異常的概念

Java中全部的異常都是class,而且都繼承於Exception。

異常都是對象,有兩個重要的方法。

try {
			result = a/b;
			System.out.println("有異常,這裏不輸出!");
		} catch(ArithmeticException e) {
			//打印相應的異常錯誤信息,message是exception的一個屬性
			System.out.println(e.getMessage());
			//打印異常發生的軌跡
			e.printStackTrace();
		}

2.二、異常的產生

異常所有都是類,它是經過在代碼中使用throw拋出的。

2.三、異常的建立

寫一個類讓其繼承Exception。

//寫一個類繼承Exception
public class MyException extends Exception {
	
	//覆蓋父類的構造方法
	public MyException() {
		super();
	}

	public MyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
	}

	public MyException(String message, Throwable cause) {
		super(message, cause);
	}

	public MyException(String message) {
		super(message);
	}

	public MyException(Throwable cause) {
		super(cause);
	}

2.四、異常的處理

有兩種方式能夠處理異常

一、try catch

二、聲明爲拋出(聲明方法會有異常,方法上面的異常聲明使用異常的類型來聲明)

非運行時刻異常,須要程序員手動處理。

try {
			//此處依然會有異常,若是不處理,須要在main函數上聲明拋出,
			//可是強烈建議不要在main函數上面拋出異常
			buyCoffeeAndWater(-300,500);
			buyWater(1);
			buyCola(-1);
		} catch (MyException e) {
			System.out.println(e.getMessage());
		} catch (MyRunException e) {
			System.out.println(e.getMessage());
		}
	}
	
	//方法上面是聲明該方法可能產生的異常
	public static void buyWater(int size) throws MyException {
		//非運行時刻異常,不會自動拋出,得程序員手動處理
		if(size<0) {
			//此處拋出的是一個異常對象
			throw new MyException("瓶裏沒水了!!!");
		}
		System.out.println("買了一瓶"+size+"ml的水");
	}

運行時刻異常

public static void buyCola(int size) {
		if(size<0) {
			//運行時刻異常,不用程序員手動處理,虛擬機會自動拋出
			throw new MyRunException("可樂過時了!!!");
		}
		System.out.println("買了一瓶"+size+"L的可樂");
	}

2.五、異常的多態

//拋出異常能夠經過多態來處理
	public static void buyCoffeeAndWater(int coffeeSize,int waterSize) throws Exception {
		if(coffeeSize<0) {
			throw new MyException2("咖啡涼了!!!");
		}
		if(waterSize<0) {
			throw new MyException("水喝完了");
		}
		System.out.println("買了一杯"+coffeeSize+"ml的咖啡和一瓶"+waterSize+"ml的水");
	}
try {
			buyCoffeeAndWater(-300,500);
			buyWater(1);
			buyCola(-1);
			//捕獲和拋出異常都支持多態,
			//可是捕獲順序若是先捕獲了父類異常就沒法再捕獲子類異常了
		} catch (MyException e) {
			System.out.println(e.getMessage());
		} catch (MyRunException e) {
			System.out.println(e.getMessage());
		} catch (MyException2 e) {
			System.out.println(e.getMessage());
		} catch (Exception e) {
			System.out.println(e.getMessage());

2.六、finally

finally是無論怎麼樣都會被執行的代碼,因此通常用來釋放資源。

} catch (Exception e) {
			System.out.println(e.getMessage());
		} finally {
			//finally語句塊中的內容無論怎麼樣都會被執行
			//因此finally中的代碼通常用來釋放資源
			System.out.println("一直運行");
		}
		//能夠不要catch直接加finally
		try {
			System.out.println("hello");
		} finally {
			System.out.println("能夠運行");
		}

三、I/O

File類:用來處理文件夾和建立刪除文件的,不能用來編輯文件。

經常使用方法:

//建立文件
			f.createNewFile();
			//判斷文件是否存在
			System.out.println(f.exists());
			//刪除文件
			//f.delete();
			//獲取文件名
			System.out.println(f.getName());
			//獲取文件夾路徑
			System.out.println(f.getParent());
			//能夠獲取該文件的父類文件夾對象
			File pf = f.getParentFile();
			//判斷文件是不是文件夾
			System.out.println(pf.isDirectory());
			
			File f2 = new File("d:/test/a");
			//建立一個目錄
			f2.mkdir();
			File f3 = new File("d:/test/b/c/d/e/f");
			//若是父目錄不存在,會先建立父目錄再建立相應的子目錄
			f3.mkdirs();
			//若是刪除的是目錄,目錄不爲空就沒法刪除
			/*
			 * 正確刪除文件夾的操做是遞歸刪除全部的文件和子文件夾
			 */
			f3.delete();
			//重命名文件--->能夠用來作剪切,可是不建議使用
			f.renameTo(new File("d:/test/a/1.txt"));

文件列表:

//list()用來列表一組文件名,能夠傳入一個實現FilenameFilter的類完成文件的過濾
		String[] fns = f.list(new JavaFileFilter());
		for(String fn:fns) {
			System.out.println(fn);
		}
		System.out.println("------------------------");
		//列表一組文件對象
		File[] fs = f.listFiles();
		for(File file:fs) {
			System.out.println(file.getName()+":"+file.length());
		}
	}
}

/**
 * 寫一個類實現FilenameFilter專門用來過濾文件
 * @author PM
 *
 */
class JavaFileFilter implements FilenameFilter {
	@Override
	public boolean accept(File dir, String name) {
		// 過濾的結果是返回爲true的值
		if(name.endsWith(".java")) return true;
		return false;
	}
}

內部類:有些類在外部是不被容許訪問的,能夠把這些類寫在類的內部,提升安全性。

普通內部類:

public void run() {
		//在非static的方法中才能訪問內部類
		File f = new File("D:\\test\\j2se");
		String[] fns = f.list(new JavaFileFilter());
		for(String fn:fns) {
			System.out.println(fn);
		}
		System.out.println("------------------------");
	}
	
	
	/**
	 * 若是這個類僅僅只是在某個類的內部能夠訪問,能夠直接將該類寫在類的內部
	 * 這個類在外部就沒法訪問,這種類叫作內部類.
	 * 內部類要在static以後才能聲明,因此不能在static的方法中使用內部類
	 * @author PM
	 *
	 */
	private class JavaFileFilter implements FilenameFilter {
		@Override
		public boolean accept(File dir, String name) {
			// 過濾的結果是返回爲true的值
			if(name.endsWith(".java")) return true;
			return false;
		}

匿名內部類:

File f = new File("D:\\test\\j2se");
		/**
		 * 匿名的內部類,該類沒有名稱,是在代碼返回以前就給它實現了
		 * 這種方式存在的惟一意義就是隻有一個方法會涉及到該類才建議這樣寫
		 * 若是有兩個或者多個方法會使用,均建議使用內部類
		 */
		String[] fns = f.list(new FilenameFilter(){//實現的開始
			//特別注意:是在語句返回以前就完成了實現的
			@Override
			public boolean accept(File dir, String name) {
				if(name.endsWith(".java")) return true;
				return false;
			}
		});//實現的結束
		for(String fn:fns) {
			System.out.println(fn);
		}

過濾文件夾:

File[] fs = f.listFiles(new FileFilter(){
			//過濾文件夾,可使用FileFilter,操做方式和FilenameFilter相似
			@Override
			public boolean accept(File pathname) {
				if(pathname.isDirectory()) return true;
				return false;
			}
			
		});

流的分類:按照方向分類、按照類型分類、按照操做方式分類、轉換流。

按照方向分類:輸入流、輸出流。

輸入流:這是一個字節流操做的很是標準過程

FileInputStream fis = null;
		try {
			//一、建立一個文件輸入流
			fis = new FileInputStream("D:\\test\\j2se\\aaa.txt");
			//二、建立一個字節數組用來存儲讀取的信息
			byte[] buf = new byte[1024];
			//三、使用len讀取的長度
			int len = 0;
			//四、循環讀取數據
			//只要len>=0說明就讀取到元素,能夠直接對元素進行操做
			while((len=fis.read(buf))>=0) {
				//五、經過控制檯輸出數據,必須說明輸出的長度
				//若是輸出文件亂碼,要修改文件輸入流編碼格式與輸出格式編碼一致
				System.out.write(buf, 0, len);
			}
			//六、讀取完成以後必須關閉流釋放資源
			fis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				//在這個位置關閉流
				if(fis!=null) fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

輸出流:

FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream("D:\\RmDownloads\\WeChat2.0.exe");
			//建立一個文件輸出流
			fos = new FileOutputStream("D:\\test\\j2se\\mm.exe");
			byte[] buf = new byte[1024];
			int len = 0;
			//將數據經過輸入流讀取到程序
			while((len=fis.read(buf))>=0) {
				//將數據經過輸出流輸出,此時是一個文件輸出流,就把數據輸出到了文件
				fos.write(buf,0,len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(fis!=null) fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(fos!=null) fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

按照類型分類:字節流、字符流

字節流:經過字節讀取數據,一般是經過XXXStream

字符流:經過字符來讀取數據,Writer和Reader

只要處理的數據是字符數據,所有使用字符流。

BufferedReader br = null;
		PrintWriter out = null;
		try {
			/*字符流用來讀取字符數據,對於輸入字符流而言,最爲經常使用操做方法是使用BufferedRead
			 * 由於該流有一個readLine()方法
			 */
			br = new BufferedReader(new FileReader("D:\\test\\read.txt"));
			//BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\test\\1.txt"));
			out = new PrintWriter(new BufferedWriter(new FileWriter("D:\\test\\1.txt")));
			String str = null;
			//BufferedReader中有一個方法叫作readLine()
			//能夠一行一行的讀取數據而且返回字符串
			while((str=br.readLine())!=null) {
				System.out.println(str);
				//使用bw輸出不會換行,得再調用bw.newLine()才能換行
				//bw.write(str);
				//bw.newLine();
				//對於字符流而言,讀數據用BufferedReader,寫數據用PrintWriter
				out.println(str);
			}
			//bw.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(br!=null) br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if(out!=null) out.close();
		}

按照操做方式分類:節點流、過濾流

節點流:能夠直接建立的流

過濾流:能夠裝飾節點流,增長相應的功能

FileInputStream fis = null;
		//過濾流不能獨立的建立對象,過濾流都須要依賴於已經建立好的節點流
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			fis = new FileInputStream("D:\\RmDownloads\\WeChat2.0.exe");
			//在文件輸入流的基礎上建立一個緩存流,以此提升效率
			bis = new BufferedInputStream(fis);
			//輸出流也能夠用過濾流
			bos = new BufferedOutputStream(new FileOutputStream("D:\\test\\j2se\\11.exe"));
			byte[] buf = new byte[1024];
			int len = 0;
			while((len=bis.read(buf))>=0) {
				bos.write(buf,0,len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			/*
			 * 對於緩衝流必定要關閉,否則若是緩衝區不滿就不會刷新,
			 * 不少時候就沒有值,能夠經過bos.flush()刷新緩衝區
			 */
			//當關閉流的時候會自動flush
			try {
				if(bis!=null) bis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if(bos!=null) bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

轉換流:將字節流轉換爲字符流    InputStreamReader  OutputStreamWriter

BufferedReader br = null;
		try {
			//把字節流轉換爲字符流,方便進行字符的處理
			br = new BufferedReader(new InputStreamReader(System.in));
			String str = null;
			while((str=br.readLine())!=null) {
				if(str.equals("exit")) break;
				System.out.println(str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(br!=null) br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

流的操做

字節流的經常使用操做:

讀:

byte[] buf = new byte[1024];
			int len = 0;
			//將數據經過輸入流讀取到程序
			while((len=fis.read(buf))>=0) { //將數據都入到緩衝區
				//將數據經過輸出流輸出,此時是一個文件輸出流,就把數據輸出到了文件
				fos.write(buf,0,len);
			}

寫:

//將數據經過輸出流輸出,此時是一個文件輸出流,就把數據輸出到了文件
				fos.write(buf,0,len); //寫的長度必定要加

字符流的經常使用操做:

讀數據使用BufferedRead,由於有readLine()方法,寫數據使用PrintWriter,可使用println.

具體使用參照字符流的操做介紹。

標準流的經常使用操做:

System.in是標準輸入流,可是因爲是字節流,不方便操做,因此一般狀況會將其轉換爲字符流

來處理,經過轉換流轉換,而後再使用BufferedReader來封裝。

BufferedReader br = null;
		try {
			//把字節流轉換爲字符流,方便進行字符的處理
			br = new BufferedReader(new InputStreamReader(System.in)); //標準輸入流
			String str = null;
			//一行一行的讀取數據,而且輸出輸入的數據
			//直到數據是exit表示退出
			while((str=br.readLine())!=null) {
				if(str.equals("exit")) break;
				System.out.println(str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(br!=null) br.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

經常使用流

文件流(File):很是經常使用,進行文件的讀寫操做

緩衝流(Buffered):過濾流用來提升效率的

數據流:用來讀取基本數據類型DataOutputStream和DataInputStream,數據流是過濾流

FileOutputStream fos = null;
		DataOutputStream dos = null;
		DataInputStream dis = null;
		try {
			fos = new FileOutputStream("D:\\test\\j2se\\num.data");
			//若是但願存儲基本數據類型就使用DataOutputStream,也是過濾流
			dos = new DataOutputStream(fos);
			dos.writeInt(1231231231);
			dos.writeInt(1111);
			dos.writeInt(2222);
			dos.writeInt(3333);
			dos.writeInt(4444);
			dos.writeInt(5555);
			//從文件讀取基本數據類型使用DataInputStream,一樣是過濾流
			dis = new DataInputStream(new FileInputStream("D:\\test\\j2se\\num.data"));
			int a = dis.readInt();
			System.out.println(a);
			//經過一個指針在文件中讀取
			System.out.println(dis.readInt());
			System.out.println(dis.readInt());
			System.out.println(dis.readLong());
			System.out.println(dis.readInt());
			//System.out.println(dis.readInt()); //讀到頭就會報錯
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(dos!=null) dos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

對象流(Object):對象流能夠完成對對象的存儲。

一、必須實現Serializable接口

/**
 * 若是但願把一個對象經過ObjectOutputStream寫到文件中,
 * 這個對象必須實現Serializable接口
 * 該接口沒有任何方法,只是告訴java能夠存儲該對象
 * @author OS
 *
 */
public class Student implements Serializable {
	private static final long serialVersionUID = 5839862437697748379L;
	private int id;
	private String name;
	//只要一個屬性經過transient設置以後這個屬性就不會被存儲
	private transient int money;

二、能夠把一些屬性設置爲transient,此時這個屬性就不會被存儲

//只要一個屬性經過transient設置以後這個屬性就不會被存儲
	private transient int money;

讀取和存儲對象可使用ObjectOutputStream和ObjectInputStream讀取,若是要從文件中讀取,須要用這兩個流封裝一下文件流。

ObjectOutputStream oos = null;
		try {
			//建立一個文件輸出流,而且把這個對象輸出到文件stu.save中去
			oos = new ObjectOutputStream(new FileOutputStream("d:/test/stu.save"));
			//直接將對象寫到文件中
			//注意:對象必須實現Serializable接口
			oos.writeObject(stu);

四、GUI

Frame和JFrame

一、Frame:Frame是整個圖用戶界面的主要窗口,這個是基於awt的。

//全部的組件都是放在frame中的
		Frame frame = new Frame();
		//設置標題
		frame.setTitle("hello world");
		//設置窗口大小
		frame.setSize(200, 100);
		//設置窗口位置
		frame.setLocation(100, 100);
		//將窗口顯示
		frame.setVisible(true);
		//注意:沒法關閉窗口

二、JFrame

/**
 * JFrame的操做和Frame的操做基本同樣,可是這個是基於swing這個包的
 * @author os
 *
 */
//基於Swing的圖形組件都是以J開頭的,操做方式和awt基本相似
public class TestJFrame extends JFrame {
	public static void main(String[] args) {
		new TestJFrame();
	}
	
	public TestJFrame() {
		this.setTitle("sdfdsfds");
		this.setSize(200, 200);
		this.setLocation(200, 200);
		this.setBackground(Color.RED);
		//JFrame提供這個方法來關閉窗口
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);

三、常見的編寫方式

/**
 * 對於Frame的編程而言,比較經常使用的方式是繼承Frame類
 * 而且在構造函數或者新編寫一個函數來設置Frame的信息
 * @author os
 *
 */
public class TestFrame02 extends Frame {
	public static void main(String[] args) {
		new TestFrame02();
	}
	
	//在這個方法中來設置相應的窗口屬性
	public TestFrame02() {
		this.setTitle("hello xm");
		this.setSize(200, 200);
		this.setLocation(300, 500);
		this.setVisible(true);

四、添加組件:全部的圖形組件均可以在容器上經過add添加

public class TestJButton extends JFrame {
	//經常使用的編寫方式是,統一把相應的容器組件設置爲屬性
	private JButton jb1,jb2;
	public static void main(String[] args) {
		new TestJButton();
	}
	
	public TestJButton() {
		this.setTitle("按鈕測試");
		this.setSize(500, 500);
		this.setLocation(100, 100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//建立兩個按鈕
		jb1 = new JButton("hello");
		jb2 = new JButton("world");
		//將按鈕加到frame中
		this.add(jb2);
		this.add(jb1);
		
		this.setVisible(true);

佈局

BorderLayout:Frame的默認佈局是BorderLayout

直接執行add方法,默認會添加到center中。

public TestBorderLayout() {
		this.setTitle("按鈕測試");
		this.setSize(500, 500);
		this.setLocation(100, 100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//設置該Frame的佈局爲BorderLayout,默認佈局就是BorderLayout。
		//可是若是但願設置垂直和水平間距,須要建立一個BorderLayout設置。
		this.setLayout(new BorderLayout(10,5));
		//建立兩個按鈕
		jb1 = new JButton("北方");
		jb2 = new JButton("南方");
		jb3 = new JButton("西方");
		jb4 = new JButton("東方");
		jb5 = new JButton("正中");
		//將按鈕加到frame中
		//第二個參數用來設置這個組件放置到哪一個位置
		this.add(jb1,BorderLayout.NORTH);
		this.add(jb2,BorderLayout.SOUTH);
		this.add(jb3,BorderLayout.WEST);
		this.add(jb4,BorderLayout.EAST);
		this.add(jb5,BorderLayout.CENTER);
		
		this.setVisible(true);

FlowLayout

public TestFlowLayout() {
		this.setTitle("測試按鈕");
		this.setSize(500, 500);
		this.setLocation(100, 100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//FlowLayout是經過流式佈局來顯示組件,第一個參數是對齊方式
		//第二個參數是水平間距,第三個參數是垂直間距
		this.setLayout(new FlowLayout(FlowLayout.CENTER,20,30));
		jb1 = new JButton("添加");
		jb2 = new JButton("修改");
		jb3 = new JButton("刪除");
		jb4 = new JButton("列表");
		jb5 = new JButton("查詢");
		this.add(jb1);
		this.add(jb2);
		this.add(jb3);
		this.add(jb4);
		this.add(jb5);
		
		this.setVisible(true);
	}

GridLayout

public TestGridLayout() {
		this.setTitle("表格佈局");
		this.setSize(500, 500);
		this.setLocation(100, 100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//表格佈局,一共兩行三列
		this.setLayout(new GridLayout(2, 3,10,15));

常見簡單佈局和經常使用組件

JPanel:用JPanel能夠完成特定的佈局,JPanel是一個容器對象,能夠添加元素和設定佈局,

默認佈局是FlowLayout。

this.setTitle("用戶登陸");
		this.setSize(320, 150);
		this.setLocation(100, 100);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setResizable(false);
		//三個JPanel,每一個JPanel中放置不一樣的元素
		//整個frame是GridLayout
		this.setLayout(new GridLayout(3, 1));

JLabel:文本標籤只能使用JLabel。

JTextField:文本域組件,能夠輸入內容。

初始化時能夠定義有多少個字符。

jtf = new JTextField(20);

JPasswordField:密碼域,操做和JTextField相似,只是輸入的是密碼。

JTextArea和JScrollPane

JTextArea:表示多行文本域。

JScrollPane:表示滾動條,在GUI中滾動條須要本身定義。

jta = new JTextArea();
		//建立滾動條時直接將須要滾動的對象經過構造函數傳入
		jsp = new JScrollPane(jta);
		//直接添加滾動條就等於添加了滾動條中的組件
		this.add(jsp);

JComboBox:表示下拉列表框。

傳入一個對象數組:

jcb = new JComboBox<String>(new String[]{"ABC","DEF","GHI"});

菜單的操做

JMenuBar   JMenu    JMenuItem

事件處理

窗口事件:

//定義了一個監聽器的類,專門用來實現WindowListener
class MyWindowListener implements WindowListener {

	@Override
	public void windowOpened(WindowEvent e) {
		System.out.println("Opened");
	}

	@Override
	public void windowClosing(WindowEvent e) {
		System.out.println("Closing");
		System.exit(0);
	}
//爲frame添加窗口監聽事件,此時,當窗口發生改變時,會自動執行相應的操做
		frame.addWindowListener(new MyWindowListener());

內部類實現

public TestFrameEvent01() {
		this.setTitle("hello");
		this.setSize(200, 200);
		this.setLocation(100, 100);
		this.addWindowListener(new MyWindowListener());
		this.setVisible(true);
	}
	
	//因爲這個類其實沒有任何被外部所訪問的意義,因此直接使用內部類
	class MyWindowListener implements WindowListener {

適配器

//若是直接實現WindowListener,會致使實現裏面的全部方法,可是不少方法都沒用,
	//此時JAVA就提供了一種適配器(Adapter)的方案來解決這種問題,
	//每個監聽器接口都存在一個適配器的類,這個類中對全部的方法進行空的實現
	class MyWindowListener extends WindowAdapter {

		@Override
		public void windowClosing(WindowEvent e) {
			System.out.println("Closing");
			System.exit(0);
		}

匿名內部類

//WindowListener除了關閉以外,其它地方都用不到,能夠直接設置爲匿名內部類
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});

ActionListener:ActionListener事件是按鈕按下的事件。

//沒有adapter,由於只有一個須要實現的方法,actionPerformed()
	class MyBtnListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("aaa");
		}
	}
jb1 = new JButton("登陸");
		jb1.addActionListener(new MyBtnListener());
		jb2 = new JButton("取消");
		jb2.addActionListener(new MyBtn2Listener());

事件的統一處理方式

class MyBtnListener implements ActionListener {

		@Override
		//定義一個事件監聽類,經過參數e.getSource()來獲取事件源,
		//而且進行判斷作不一樣的處理
		public void actionPerformed(ActionEvent e) {
			//e.getSource()能夠獲取哪一個監聽對象觸發事件
			//System.out.println(e.getSource());
			if(e.getSource()==jb1) {
				//System.out.println("login");
				System.out.println("Username:"+jtf.getText());
				System.out.println("Password:"+new String(jpf.getPassword()));
			} else if(e.getSource()==jb2) {
				//System.out.println("cancel");
				jtf.setText("");
				jpf.setText("");
			}



		//相同的監聽對象
		jb1 = new JButton("登陸");
		jb1.addActionListener(new MyBtnListener());
		jb2 = new JButton("取消");
		jb2.addActionListener(new MyBtnListener());

鍵盤事件:KeyListener是鍵盤事件

private class MyKeyEvent extends KeyAdapter {
		@Override
		public void keyPressed(KeyEvent e) {
			super.keyPressed(e);
			//e的getKeyCode用來獲取究竟按下了哪個鍵
			//KeyEvent對象的一組常量能夠獲取具體的鍵
			if(e.getKeyCode()==KeyEvent.VK_UP) {
				System.out.println("上");
			} else if(e.getKeyCode()==KeyEvent.VK_DOWN) {
				System.out.println("下");
			} else if(e.getKeyCode()==KeyEvent.VK_LEFT) {
				System.out.println("左");
			} else if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
				System.out.println("右");
			}



		//爲窗口增長這個事件
		this.addKeyListener(new MyKeyEvent());

繪圖

步驟:

一、建立一個內部類繼承JPanel

private class MyPanel extends JPanel {
		//覆蓋paint方法
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			g.setColor(Color.BLACK);
			g.drawRect(10, 10, 200, 200);
			g.setColor(Color.BLUE);
			g.fillOval(20, 20, 40, 40);
		}
	}

二、覆蓋整個JPanel的paint()方法

private class MyPanel extends JPanel {
		//覆蓋paint方法
		//Graphics g 一支畫筆,用它來畫圖
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			g.setColor(Color.BLACK);
			g.drawRect(10, 10, 200, 200);
			g.setColor(Color.BLUE);
			g.fillOval(20, 20, 40, 40);
		}
	}

三、將這個panel添加到Frame中

mp = new MyPanel();
		this.add(mp);

捕獲鍵盤事件

一、定義一個面板,而且畫一個小球

private class MyPanel extends JPanel {
		//把x和y座標定義成變量
		private int x;
		private int y;
		
		public MyPanel(int x, int y) {
			//super();
			this.x = x;
			this.y = y;
		}
		
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			g.setColor(Color.RED);
			g.fillOval(x, y, 20, 20);
		}
	}

二、將畫板添加到窗口

mp = new MyPanel(10,10);
		this.add(mp);

三、爲窗口添加鍵盤事件

private class MyKeyEvent extends KeyAdapter {
		//監聽鍵盤的按下事件
		@Override
		public void keyPressed(KeyEvent e) {
			//根據鍵盤的按鈕來肯定畫板中圓球的座標
			if(e.getKeyCode()==KeyEvent.VK_UP) {			
				mp.y-=5;
			} else if(e.getKeyCode()==KeyEvent.VK_DOWN) {
				mp.y+=5;
			} else if(e.getKeyCode()==KeyEvent.VK_LEFT) {
				mp.x-=5;
			} else if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
				mp.x+=5;
			}

四、重畫畫板

//讓面板刷新
			mp.repaint();//最重要的步驟,畫完以後必定要重畫面板

五、完整代碼

public TestMoveCircle() {
		this.setTitle("移動的小球");
		this.setSize(500, 500);
		this.setLocation(100, 100);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		mp = new MyPanel(10,10);
		this.add(mp);
		this.addKeyListener(new MyKeyEvent());
		
		this.setVisible(true);
	}
	
	private class MyKeyEvent extends KeyAdapter {
		//監聽鍵盤的按下事件
		@Override
		public void keyPressed(KeyEvent e) {
			//根據鍵盤的按鈕來肯定畫板中圓球的座標
			if(e.getKeyCode()==KeyEvent.VK_UP) {			
				mp.y-=5;
			} else if(e.getKeyCode()==KeyEvent.VK_DOWN) {
				mp.y+=5;
			} else if(e.getKeyCode()==KeyEvent.VK_LEFT) {
				mp.x-=5;
			} else if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
				mp.x+=5;
			}
			//讓面板刷新
			mp.repaint();//最重要的步驟,畫完以後必定要重畫面板
		}
	} 
	
	private class MyPanel extends JPanel {
		//把x和y座標定義成變量
		private int x;
		private int y;
		
		public MyPanel(int x, int y) {
			//super();
			this.x = x;
			this.y = y;
		}
		
		@Override
		public void paint(Graphics g) {
			super.paint(g);
			g.setColor(Color.RED);
			g.fillOval(x, y, 20, 20);
		}
	}

五、多線程:多線程指的是有多條分支在同時進行。

5.一、多線程的編寫:

第一種方式

1、讓一個類繼承相應的Thread類,這個類就是多線程的類。

class FirstThread extends Thread {
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("first:"+i);
		}
	}
}

2、覆蓋這個類的run()方法,run()方法中的代碼就是基於多線程的代碼。

class FirstThread extends Thread {
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			System.out.println("first:"+i);
		}
	}
}

3、建立這個對象,而且使用start()開啓線程(特別注意不是使用run())

public static void main(String[] args) {
		FirstThread ft = new FirstThread();
		//此處是使用start()來開始啓動線程,不是使用run
		ft.start();
		//此時是函數調用
		//ft.run();
		
		for(int i=0;i<100;i++) {
			System.out.println("main:"+i);
		}
	}

第二種方式

實現Runnable接口

/*
	 * 第二種方式,是讓一個實現Runnable接口。而且實現run()方法。
	 */
	class MyThread implements Runnable {

		@Override
		public void run() {
			for(int i=0;i<100;i++) {
				System.out.println("mt:"+i);
			}
		}



	public void begin() {
		/*
		 * 該方式的使用,因爲MyThread沒有start()方法,
		 * 因此須要將其放置到一個Thread類中運行
		 */
		MyThread mt = new MyThread();
		//放到一個Thread類中
		Thread t = new Thread(mt);
		//依然是使用start()方法啓動
		t.start();
		for(int i=0;i<100;i++) {
			System.out.println("main:"+i);
		}

5.二、多線程的名稱

class ThirdThread extends Thread {
	//Thread都有一個名稱,只要繼承Thread就能夠調用super的方法設置名稱
	public ThirdThread(String name) {
		super(name);
	}
	@Override
	public void run() {
		for(int i=0;i<100;i++) {
			//Thread的名稱
			System.out.println(this.getName()+":"+i);
		}
	}



	public void begin() {
		/*
		 * 該方式的使用,因爲MyThread沒有start()方法,
		 * 因此須要將其放置到一個Thread類中運行
		 */
		MyThread mt = new MyThread();
		//放到一個Thread類中,構造函數的第二個參數就是線程的名稱
		Thread t = new Thread(mt,"小二");
		t.start();
		for(int i=0;i<100;i++) {
			System.out.println("main:"+i);
		}
	}
	/*
	 * 第二種方式,是讓一個實現Runnable接口。而且實現run()方法。
	 */
	class MyThread implements Runnable {

		@Override
		public void run() {
			for(int i=0;i<100;i++) {
				//沒有name屬性,能夠經過Thread.currentThread()來獲取當前線程
				System.out.println(Thread.currentThread().getName()+":"+i);
			}
		}

5.三、線程的調度

public static void main(String[] args) {
		new TestStatus().run();
	}
	
	public void run() {
		MyThread mt = new MyThread("abcde");
		mt.start();
		new MyThread02("dddddddddddd").start();
		/*try {
			//一直等待該線程執行完纔去執行其餘線程
			mt.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}*/
		for(int i=0;i<20;i++) {
			System.out.println("main:"+i);
			Thread.yield();
		}
	}
	
	class MyThread extends Thread {
		public MyThread(String name) {
			super(name);
		}
		@Override
		public void run() {
			for(int i=0;i<10;i++) {
				System.out.println(this.getName()+":"+i);
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	class MyThread02 extends Thread {
		public MyThread02(String name) {
			super(name);
		}
		@Override
		public void run() {
			for(int i=0;i<100;i++) {
				System.out.println(this.getName()+":"+i);
			}
		}
	}

5.四、兩種線程的區別

public void run() {
		//每一個成員變量都有不一樣的存儲空間
		MyThread mt1 = new MyThread("mt1");//每一個線程都是獨享相應的存儲空間
		mt1.start();
		MyThread mt2 = new MyThread("mt2");//每一個線程都是獨享相應的存儲空間
		mt2.start();
		/*for(int i=0;i<10;i++) {
			System.out.println("main:"+i);
		}*/
	}
	
	class MyThread extends Thread {
		private int index = 0;//每一個線程都是獨享相應的存儲空間
		public MyThread(String name) {
			super(name);
		}
		@Override
		public void run() {
			for(;index<10;index++) {
				System.out.println(Thread.currentThread().getName()+":"+index);
			}
		}




	public void run() {
		//共享mt的成員變量
		//只有一個MyThread對象,因此每一個線程都是共享這個MyThread類的空間的
		MyThread mt = new MyThread();
		new Thread(mt,"mt1").start();
		new Thread(mt,"mt2").start();
		/*for(int i=0;i<10;i++) {
			System.out.println("main:"+i);
		}*/
	}
	
	private class MyThread implements Runnable {
		//只有一個MyThread對象,因此每一個線程都是共享這個MyThread類的空間的
		private int index;
		@Override
		public void run() {
			for(;index<10;index++) {
				System.out.println(Thread.currentThread().getName()+":"+index);
			}
		}

5.五、線程的中止

public void run() {
		MyThread mt = new MyThread();
		Thread tmt = new Thread(mt);
		tmt.start();
		while(true) {
			if(mt.index>=500) {
				System.out.println("----");
				//讓線程中止
				mt.stopThread();//調用中止的方法
				break;
			}
		}
	}
	
	class MyThread implements Runnable {
		int index = 0;
		//經過一個變量來控制線程的中止
		private boolean flag = true;
		@Override
		public void run() {
			for(index=0;index<1000;index++) {
				if(!flag) {
					break;
				}
				System.out.println("index:"+index);
			}
		}
		
		public void stopThread() {
			//在這個位置釋放資源
			flag = false;//經過這個變量控制線程的中止
		}
	}

5.六、線程的同步

//同步方法,默認使用this做爲鑰匙
		public synchronized void getMoney() {
			//也能夠直接使用this來做爲鑰匙,任何一個對象均可以作鑰匙
			//synchronized (this) {
				System.out.println(Thread.currentThread().getName()+"取了"+getMoney+"元");
				curMoney+=getMoney;
				//當兩個線程同時修改某個變量時就會出現同步的問題,
				//須要使用同步塊進行同步。
				//若是使用同步塊會影響效率
				int temp = saveMoney - getMoney;
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				saveMoney = temp;
				times++;
				System.out.println("3:"+times);
			//}
		}
		
		/*
		 * 使用同步方法其實就等於
		 * public void getMoney() {
		 *直接傳入一個對象做爲同步塊的鑰匙
			synchronized (this) {
				System.out.println(Thread.currentThread().getName()+"取了"+getMoney+"元");
				curMoney+=getMoney;
				int temp = saveMoney - getMoney;
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				saveMoney = temp;
				times++;
				System.out.println("3:"+times);
			}
		 */

5.七、死鎖

/*
 * 避免死鎖的最佳方式,不要出現同步的嵌套,
 * 讓同步塊儘量大(效率會下降)
 */
public class TestDeadLock {
	public static void main(String[] args) {
		new TestDeadLock().run();
	}
	
	public void run() {
		MyThread mt = new MyThread();
		new Thread(mt,"張三").start();
		new Thread(mt,"李四").start();
	}
	
	class MyThread implements Runnable {
		private Object k1 = new Object();
		private Object k2 = new Object();
		private boolean flag = true;
		
		@Override
		public void run() {
			if(flag) {
				flag = false;
				synchronized (k1) {
					System.out.println(Thread.currentThread().getName()+":k1");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					synchronized (k2) {
						System.out.println(Thread.currentThread().getName()+":k2");
					}
				}
			} else {
				flag = true;
				synchronized (k2) {
					System.out.println(Thread.currentThread().getName()+":k2");
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					synchronized (k1) {
						System.out.println(Thread.currentThread().getName()+":k1");
					}
				}
			}
		}
	}

5.八、生產者和消費者

第一:後臺線程

第二:notify和wait

public void make() {
		synchronized (d) {
			if(d.isEmpty()) {
				int index = ran.nextInt(foods.length);
				String f = foods[index];
				System.out.println(name+"製做了"+f);
				d.setFood(f);
				d.setEmpty(false);
				d.notify();
				try {
					Thread.sleep(2000);
					d.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				/*不能依賴於sleep來控制線程
				 * try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}*/
			} else {
				try {
					d.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}


	public void eat() {
		synchronized (d) {
			if(!d.isEmpty()) {
				String food = d.getFood();
				System.out.println(name+"正在享受"+food);
				d.setEmpty(true);
				d.notify();
				try {
					Thread.sleep(2000);
					d.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			} else {
				try {
					d.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}


		Disk d = new Disk();
		Cooker co = new Cooker("廚神",d);
		Custom cu = new Custom("吃貨",d);
		Thread cot = new Thread(co);
		Thread cut = new Thread(cu);
		//cut爲後臺線程,只要全部的線程結束,這個線程就自動結束
		cut.setDaemon(true);
		cot.start();
		cut.start();
public class Clock implements Runnable {
	private boolean wakeup;

	public boolean isWakeup() {
		return wakeup;
	}

	public void setWakeup(boolean wakeup) {
		this.wakeup = wakeup;
	}

	public Clock() {
		wakeup = false;
	}
	
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			wake();
		}
	}
	
	public synchronized void wake() {
		try {
			if(!wakeup) {
				for(int i=0;i<3;i++) {
					System.out.println("起牀了!");
				}
				wakeup = true;
				this.notify();
				this.wait();
			} else {
				this.wait();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

public class Person implements Runnable {
	private Clock c;

	public Clock getC() {
		return c;
	}

	public void setC(Clock c) {
		this.c = c;
	}

	public Person(Clock c) {
		this.c = c;
	}
	
	@Override
	public void run() {
		while(true) {
			operator();
		}
	}
	
	public void operator() {
		synchronized(c) {
			try {
				if(c.isWakeup()) {
					//System.out.println(c.isWakeup());
					System.out.println("知道了!");
					c.setWakeup(false);
					Thread.sleep(3000);
					c.notify();
					c.wait();
				} else {
					c.wait();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Clock c = new Clock();
		Person p = new Person(c);
		
		Thread ct = new Thread(c);
		Thread pt = new Thread(p);
		pt.setDaemon(true);
		ct.start();
		pt.start();
		
	}
public class Answer implements Runnable {
	private String name;
	private Asker asker;
	private String[] answers;
	
	public String getName() {
		return name;
	}

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

	public Asker getAsker() {
		return asker;
	}

	public void setAsker(Asker asker) {
		this.asker = asker;
	}

	public Answer(String name, Asker asker) {
		this.name = name;
		this.asker = asker;
		answers = new String[]{"好熱啊!","大聖,等等我!","上帝笑了!","吃俺老孫一棒!",
				"師傅!師傅","睡覺好舒服!","請你嚴肅點!","逗你玩!","天亮了!","好好好!"};
	}

	@Override
	public void run() {
		while(true) {
			answer();
		}
	}
	
	public void answer() {
		synchronized (asker) {
			try {
				if(asker.isAsk()) {
					String q = asker.getQuestion();
					if(q.indexOf("王八蛋")>0) {
						System.out.println("你丫纔是王八蛋呢!!!");
					} else {
						int index = Asker.ran.nextInt(answers.length);
						String a = answers[index];
						System.out.println(name+":'"+a+"'");
					}
					asker.setAsk(false);
					Thread.sleep(2000);
					asker.notify();
					asker.wait();
				} else {
					asker.wait();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}


public class Asker implements Runnable {
	private String name;
	private String[] questions;
	private String question;
	private boolean isAsk;
	public static Random ran = new Random();
	
	public String getQuestion() {
		return question;
	}

	public void setQuestion(String question) {
		this.question = question;
	}

	public String getName() {
		return name;
	}

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

	public String[] getQuestions() {
		return questions;
	}

	public void setQuestions(String[] questions) {
		this.questions = questions;
	}

	public boolean isAsk() {
		return isAsk;
	}

	public void setAsk(boolean isAsk) {
		this.isAsk = isAsk;
	}

	public Asker(String name) {
		this.name = name;
		questions = new String[]{"你好嗎?","你吃了嗎?","你是猴子派來的救兵嗎?","你是王八蛋嗎?"
				,"今每天氣好嗎?","中國足球隊贏了嗎?","朝鮮人民奔小康了嗎?","汽油又漲價了嗎"};
		isAsk = false;
	}

	@Override
	public void run() {
		for(int i=0;i<20;i++) {
			ask();
		}
	}
	
	public void ask() {
		synchronized (this) {
			try {
				if(!isAsk) {
					int index = ran.nextInt(questions.length);
					question = questions[index];
					System.out.println(name+":'"+question+"'");
					Thread.sleep(2000);
					isAsk = true;
					this.notify();
					this.wait();
				} else {
					this.wait();
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}


	public static void main(String[] args) {
		Asker asker = new Asker("春哥");
		Answer ans = new Answer("鳳姐",asker);
		Thread ast = new Thread(asker);
		Thread ant = new Thread(ans);
		ant.setDaemon(true);
		ast.start();
		ant.start();
	}

六、網絡編程

6.1網絡編程步驟

一、創建服務端和客戶端

兩個類,一個是客戶端,一個是服務端

二、編寫server端的程序

public static void main(String[] args) {
		//服務器端就是建立相應的ServerSocket
		ServerSocket ss = null;
		Socket s = null;
		try {
			ss = new ServerSocket(5858);
			//由於服務器端通常都是不中止工做的,因此須要使用死循環
			while(true) {
				try{
					//此處就接收了一個客戶端的請求
					s = ss.accept();
					String name = s.getInetAddress().getHostAddress()+":"+s.getPort();
					//System.out.println("a client connect:"+s.getPort()+","+s.getInetAddress());
					BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
					String str = br.readLine();
					System.out.println(name+"--"+str);
					PrintWriter out = new PrintWriter(s.getOutputStream(),true);
					out.println("Receive:"+str);
				} finally {
					if(s!=null) s.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				//結束以後要關閉socket
				if(ss!=null) ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

三、建立客戶端

public static void main(String[] args) {
		Socket s = null;
		try {
			/**
			 * 客戶端經過Socket鏈接服務器端
			 */
			s = new Socket("127.0.0.1",5858);
			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			out.println("你好");
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str = br.readLine();
			System.out.println(str);	
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(s!=null) s.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

四、在服務器端接收客戶端的鏈接

//此處就接收了一個客戶端的請求
					s = ss.accept();
					String name = s.getInetAddress().getHostAddress()+":"+s.getPort();
					//System.out.println("a client connect:"+s.getPort()+","+s.getInetAddress());

五、兩端進行通訊

服務器端和客戶端創建了鏈接以後能夠獲取這個Socket的InputStream和OutputStream,

經過這兩個流就能夠完成相應的操做。

客戶端

try {
			/**
			 * 客戶端經過Socket鏈接服務器端
			 */
			s = new Socket("127.0.0.1",5858);
			//若是要輸出字符數據,都是用PrintWriter
			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			out.println("你好");

服務器的接收端

try {
			ss = new ServerSocket(5858);
			//由於服務器端通常都是不中止工做的,因此須要使用死循環
			while(true) {
				try{
					//此處就接收了一個客戶端的請求
					s = ss.accept();
					String name = s.getInetAddress().getHostAddress()+":"+s.getPort();
					//System.out.println("a client connect:"+s.getPort()+","+s.getInetAddress());
					//只要操做的是字符數據,統一用BufferedReader
					BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
					String str = br.readLine();
					System.out.println(name+"--"+str);

6.二、基於TCP的編程操做

服務端和客戶端鏈接完成以後,經過socket能夠完成兩段的通訊,由於使用socket能夠獲取相應

的輸入流和輸出流。

一、建議最佳操做

經過socket獲取的輸入流或者輸出流都是基於字節數據的,因此須要經過基於字節數據的流

完成。

建議在寫數據時使用PrintWriter,在讀數據時使用BufferedReader。

/**
			 * 客戶端經過Socket鏈接服務器端
			 */
			s = new Socket("127.0.0.1",5858);
			//若是要輸出字符數據,都是用PrintWriter
			//寫數據使用PrintWriter
			PrintWriter out = new PrintWriter(s.getOutputStream(),true);
			out.println("你好");



			//讀數據使用BufferedReader,經過轉換流進行轉換
			BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String str = br.readLine();
			System.out.println(str);

二、服務器端的編寫

//服務器端就是建立相應的ServerSocket
		ServerSocket ss = null;
		Socket s = null;
		try {
			ss = new ServerSocket(5858);
			//由於服務器端通常都是不中止工做的,因此須要使用死循環
			while(true) {
				try{
					//此處就接收了一個客戶端的請求
					s = ss.accept();
					String name = s.getInetAddress().getHostAddress()+":"+s.getPort();
					//System.out.println("a client connect:"+s.getPort()+","+s.getInetAddress());
					//只要操做的是字符數據,統一用BufferedReader
					BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
					String str = br.readLine();
					System.out.println(name+"--"+str);
					PrintWriter out = new PrintWriter(s.getOutputStream(),true);
					out.println("Receive:"+str);
				} finally {
					if(s!=null) s.close();
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				//結束以後要關閉socket
				if(ss!=null) ss.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

6.三、基於UDP的編程操做

UDP一般是經過接收端和發送端完成通訊的。

接收端的編寫

DatagramSocket ds = null;
		try {
			//UDP接收端鏈接
			ds = new DatagramSocket(9999);
			//定義將UDP的數據包接收到什麼地方
			byte[] buf = new byte[1024];
			//定義UDP的數據接收包
			DatagramPacket dp = new DatagramPacket(buf, buf.length);
			while (true) {
				//接收數據包
				ds.receive(dp);
				String str = new String(dp.getData(),0,dp.getLength());
				System.out.println(str);
			}

發送端的編寫

DatagramSocket ds = null;
		try {
			//定義一個UDP的Socket來發送數據
			ds = new DatagramSocket();
			//假設發送的數據是個字符串
			String hello = "hello world";
			//定義一個UDP的數據發送包來發送數據,InetSocketAddress表示要接收的地址
			DatagramPacket dp = new DatagramPacket(hello.getBytes(), 
					hello.getBytes().length, new InetSocketAddress("127.0.0.1",9999));
			for(int i=0;i<10;i++) {
				ds.send(dp);
				Thread.sleep(1000);
			}

七、正則表達式

正則表達式是用來處理字符串的。

1、用來進行字符串的匹配。

2、用來進行替換操做。

3、用來提取信息。

7.一、基礎表達式

1、基本匹配

.:全部字符

\d:全部數字

\D:全部非數字

\s:空白字符

\S:非空白字符

\w:[a-zA-Z_0-9]

\W:非\w

//.表示任意字符
		System.out.println("a".matches("."));
		System.out.println("aa".matches(".a"));
		System.out.println("\\d");
		//\\d表示是不是數字
		System.out.println("123".matches("\\d\\d\\d"));
		System.out.println("1a23c4".matches("\\d\\D\\d\\d\\D\\d"));
		//\\s表示是不是空白字符
		System.out.println("1  2		d".matches("\\d\\s\\s\\d\\s\\sd"));
		//\\w表示經常使用輸入字符:a-z,A-Z,0-9,_
		System.out.println("aa b1 22".matches("\\w\\w\\s\\w\\w\\s\\w\\w"));
		//[abcd]表示是不是abcd這四個字符中的某一個
		System.out.println("a".matches("[abcd]"));
		//[a-z]表示是不是a-z之間的字符
		System.out.println("D".matches("[a-zA-Z]"));
		//[^a-z]表示不在a-z之間
		System.out.println("h".matches("[^a-z]"));
		//也支持&&和||
		System.out.println("e".matches("[a-z&&[def]]"));
		System.out.println("H".matches("[a-z]||[A-D]"));

7.二、?*+

2、.、*、+

X?  X,once or not at all

X*  X,zero or more times

X+  X,one or more times

3、範圍匹配

X{n}  X,exactly n times

X{n,}  X,at least n times

X{n,m}  X,at least n but not more than m times

[abc]  a,b or c (simple class)

//*表示任意多個字符(0個或多個)
		System.out.println("aaaa".matches("a*"));
		//輸出結果爲false,由於*表示的多個
		System.out.println("abcd".matches("a*"));
		System.out.println("abcd".matches("a.*"));
		System.out.println("abcd".matches("a[a-z]*"));
		System.out.println("".matches("a*"));
		//+表示一個或者多個
		System.out.println("aa".matches("a+"));
		System.out.println("a".matches("a+"));
		System.out.println("".matches("a+"));
		//?表示0個或者1個
		System.out.println("a".matches("a?"));
		System.out.println("aa".matches("a?"));
		System.out.println("".matches("a?"));
		//{n,m}表示至少出現n次,最多出現m次
		System.out.println("2016-7-20".matches("\\d{4}-\\d{1,2}-\\d{1,2}"));
		//第一個:檢測一個字符串是不是數字
		System.out.println("3423.43".matches("\\d+\\.?\\d+"));
		//第二個:檢測一個字符串是不是一個電話號碼 010-8898989-01
		System.out.println("0101-2345678-03".matches("\\d{3,4}-\\d{7}-\\d{2}"));
		System.out.println("0101-2345678".matches("\\d{3,4}-\\d{7}-*\\d*"));
		//第三個:匹配一個IP地址:192.168.1.123
		System.out.println("192.168.1.123".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
		//第四個:匹配一個身份證號
		System.out.println("12345678998765432X".matches("\\d{15}||\\d{18}||\\d{17}[X]"));
		//匹配一個電子郵件
		System.out.println("qw@al.com.cn".matches("[\\w-\\.]*\\w+@[\\w\\.-]*\\w+\\.\\w{2,6}"));

7.三、邊界處理

//^不在[]中就表示以xx爲開頭,特別注意:[^abc]表示除了abc以外的字符
		System.out.println("helloworld".matches("^h\\w+"));
		System.out.println("h".matches("^h\\w+"));
		System.out.println("1you".matches("\\d\\w+"));
		//$表示以XX結尾
		System.out.println("1you1d".matches("\\w*\\d$"));

7.四、Pattern和Matcher

//能夠先將一個正則表達式編譯成爲一個Pattern對象,能夠提升效率
		Pattern p = Pattern.compile("\\d{4}");
		//經過Pattern能夠獲取一個Matcher對象,經過Matcher對象能夠獲取大量的有用信息
		Matcher m = p.matcher("23458888-6789-1234");
		//判斷是否匹配
		System.out.println(m.matches());
		//將查找的指針重置
		m.reset();
		//如下會報錯,必須在find以後才能執行group
		//System.out.println(m.group());
		/*//find指的是順序匹配相應的字符串
		System.out.println(m.find());
		//每進行一次find,就能夠將字符串經過group獲取,必定要執行了find以後才能執行group
		System.out.println(m.group());
		System.out.println(m.find());
		System.out.println(m.group());
		System.out.println(m.find());
		System.out.println(m.group());*/
		while(m.find()) {
			//m.start和m.end能夠獲取匹配字符串的開始位置和結束位置
			System.out.println(m.group()+"["+m.start()+","+m.end()+"]");
		}

7.五、替換

String str = "23456asdfg2343sdfds343";
		//第一個參數是正則表達式,第二個參數是要替換的值
		System.out.println(str.replaceAll("\\d", "*"));
		System.out.println(str.replaceAll("\\d+", "*"));
		//替換後4位
		System.out.println("12345678909".replaceAll("\\d{4}$", "****"));

7.六、分組和查找

分組

String str = "222333199812030001,222333199902030002,222333198804050003";
		//使用括號進行分組
		//此處分紅了三個組,每個左括號就是一個組
		Pattern p = Pattern.compile("((\\d{6})(\\d{8}))\\d{4}");
		Matcher m = p.matcher(str);
		while(m.find()) {
			System.out.println(m.group());
			//根據group(xx)來輸出某個組的內容
			System.out.println("出生地:"+m.group(2)+"出生日期:"+m.group(3));
		}

貪婪模式

String h = "<table><td>你好</td><td>我好</td><td>你們好</td></table>";
		//貪婪模式,指的是.*會匹配全部的信息,此處會找整個信息
		p = Pattern.compile("<td>(.*)</td>");
		m = p.matcher(h);
		while(m.find()) {
			//找到的結果:你好</td><td>我好</td><td>你們好
			System.out.println(m.group(1));
			System.out.println(m.start()+","+m.end());
		}

非貪婪模式

//非貪婪模式,僅僅只是匹配第一個結尾,特別注意:?接在*+以後就表示使用了非貪婪模式
		p = Pattern.compile("<td>(.*?)</td>");
		m = p.matcher(h);
		while(m.find()) {
			System.out.println(m.group(1));
			System.out.println(m.start()+","+m.end());
		}

 

(完)

相關文章
相關標籤/搜索