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());
		}

 

(完)

相关文章
相关标签/搜索