Java学习笔记备份

day1
1class Demo
{
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}
三点:main为程序入口,被虚拟机所调用,有main函数,一个类就可以独立运行。
2、类文件在各个路径下都可以找到
使用classpath环境变量  
set classpath=c:\my class
set classpath=c:\my class;
存在加分号和不加分号的区别,加上分号如果在指定目录下找不到会在当前目录下进行查找,一般不要加
set classpath=.;c:\my class;
设置当前路径和设置路径,要显式地设置出来
3class类名前添加public关键字强制保证类名和文件名相同,否则编译不通过。





day2
1、java中特有的注释
/**
文档注释
*/
该种注释,可以使用jdk中的javadoc.exe程序来提取源码和说明。
2、大括号即作用域
public static void main(String[] args){
	{
		int z = 9;
		System.out.println(z);
	}
	System.out.println(z);
}
上述代码段编译时会报错,因为z的作用域的原因。
3、运算两端同类型才能运算,不同数值型可以运算,但会有类型提升。
public class Test {
	public static void main(String[] args){
	    byte b = 4;
	    byte b1 = 3;
	    byte b2 = 7;
	    b = b1 + b2;   //type mismatch:cannot convert from int to byte
	    
	    int x;
	    x = b1 + b2;
	}
}
4、自动类型转换(隐式)和强制类型转换(显式)
5、任何数值和字符串(用双引号)单引号为字符,计算时取ASCII值)做加法都是相连接。
System.out.println(3 + "2");   //输出结果为32
System.out.println(3 +2);   //输出结果为53 
6short s = 3;
   s += 4;                     //自动进行转换
   s = (short)(s + 4)//强制进行转换
   
   
   
   
   
day3
1、异或 ^两边如果相同,则结果为false2、按位操作符 &  |
3、逻辑操作符(短路) && ||  
4、取反和反码不一样
a. 原码、反码、补码:
(1)在Java中,所有数据的表示方式都是以补码形式来表示
(2)正数:原码、反码、补码相同
(3)负数:符号位为1,其余各位是对原码取反,然后整个数加1
(4)~按位取反(反码加1称为补码。)步骤就是先求出这个数(因为java存的数是补码)的原码,
然后对原码取反得到X,这个X就是我们要求的那个数的补码
b. 取反(~)运算
(1)n=37 ,二进制数就是 100101
因为在Java中,所有数据的表示方式都是以补码形式来表示,如果没有特别的说明,Java 中的数据类型默认为intint数据类型的长度为8位,就是32字节,32bit的意思,
因此,n=100101的原码=补码(因为是正数,所以原==反)运算过程就是:
原码:00000000 00000000 00000000 0010010137
~n(对n的原码) 取反运算得:  11111111 11111111 11111111 11011010        很明显,最高位是1,意思是原码为负数,负数的补码是其绝对值的原码取反,末尾再加1,
因此,我们可将这个二进制数的补码进行还原:
首先,末尾减1得反码:11111111 11111111 11111111 11011001
其次,将各位取反得原码:00000000 00000000 00000000 00100110 这个就是~n的绝对值形式,|~n|=38,
所以,~n= -38,这个就是Java虚拟机的运算结果
(2)n= - 4, 取反 (~-4-4补码:10000000 00000000 00000000 00000100
-4反码:10000000 00000000 00000000 00000011
-4原码:11111111 11111111 11111111 11111100
对原码取反:00000000 00000000 00000000 00000011  
因为是正数,所以补码等于原码等于反码= 3,所以~-4 = 3
5、左移、右移(高位是什么,移位后高位补什么)、无符号右移 << >> >>>
6、对两个数值变量进行互换(不使用第三个变量)
public class Test {
	public static void main(String[] args){
		int a = 3int b = 4;
	    
		a = a + b;
        b = a - b;
        a = a - b;		//这种方式如果两个整数值过大,会发生强制转换
		
		a = a ^ b;
		b = a ^ b;
        a = a ^ b;      //一个数异或同一个值两次,变为原来的值 		
	}
}
7、局部代码块与变量作用域
使用局部代码块可以节省内存(虚拟机内存不大),性能优化
public class Test {
	public static void main(String[] args){
		int a = 3int b = 4;
	    
		{//局部代码块
			int m = 89;
			System.out.println("Hello" + m);
		}	//该代码块结束后,变量m被释放
		System.out.println("Hello" + m);  //报错
	}
}
8if...else if...效率比 if...if...要高。 
9ifswitch的应用
if:1、对具体的值进行判断
   2、对区间进行判断
   3、对运算结果是boolean类型的表达式进行判断
switch:1、对具体值进行判断 2、值的个数通常是固定的  





day4
1、九九乘法表 
public class Test {
	public static void main(String[] args){
		for(int x = 1; x <= 9; x++){
			for(int y = 1; y <= x; y++){
				//\to为制表符,保证右对齐
				System.out.print(y+"*"+x+"="+y*x+"\t");
			}
			System.out.println();
		}
	}
}
2、转义字符
\n : 回车
\t : 制表符
\b : 退格
\r : 按下回车键
Windows系统中回车符其实是由两个符号组成的\r\n. linux中回车符是\n. 
3breakcontinue
break:跳出当前循环 选择结构和循环结构
continue: 结束本次循环,继续下次循环 循环结构中使用
break想要跳出指定循环,需要用到标号;continue想要继续指定循环也可以用标号
a、
public class Test {
	public static void main(String[] args){
	    for(int x = 0; x < 3; x++){
	    	for(int y = 0; y < 4; y++){
	    		System.out.println("x="+x);
			    break;
	    	}
	    }
	}
} 	
output:
x=0
x=1
x=2
b、
public class Test {
	public static void main(String[] args){
	    for(int x = 0; x < 3; x++){
	    	for(int y = 0; y < 4; y++){
	    		System.out.println("x="+x);
	    	}
	    	break;
	    }
	}
} 	  
output:
x=0
x=0
x=0
x=0	  
c、  
package cn.itcast.io;
public class Test {
	public static void main(String[] args){
	    firstloc:for(int x = 0; x < 3; x++){
	    	secondloc:for(int y = 0; y < 4; y++){
	    		System.out.println("x="+x);
		    	break firstloc;
	    	}
	    }
	}
}  output:x=0
continue打印10以内的奇数(continue: 结束本次循环,继续下次循环 循环结构中使用)
package cn.itcast.io;
public class Test {
	public static void main(String[] args){
	    for(int x = 0; x < 11; x++){
			if(x%2 == 0)
				continue;
			System.out.print("x="+x+" ");
		}
	}
} 	output:x=1 x=3 x=5 x=7 x=9   
4、函数
函数的定义、特点、应用和重载
5、内存加载过程(栈)
//javac启动java编译器,生成字节码文件
/>javac FunctionDemo.java --> FunctionDemo.class 
//java启动虚拟机,找main函数程序执行入口
/>java FunctionDemo 
6、重载(overload)
重载的概念:在同一个类中,允许一个以上的同名函数,只要他们的参数个数或参数类型不同即可。
重载的特点:与返回值类型无关,只看参数列表。
重载的好处:方便阅读,优化程序设计。
重载的示例:
//两个整数的和
public static int add(int a, int b) {return a+b;}
//三个整数的和
public static int add(int a, int b, int c) {return a+b+c;}
//两个小数的和
public static double add(double a, double b) {return a+b;}
//该函数加入,编译时会直接报错(函数的重载和返回值类型无关)
//java是严谨性语言,如果函数出现调用的不确定性,会编译失败
public static double add(int a, int b) {return a+b;}
7、乘法表(体现函数的重载和复用)
package cn.itcast.io;
public class Test {
	public static void main(String[] args){
		printCFB(6);
		printCFB();
	}
	
	public static void printCFB(int num){
		for(int x = 1; x <= num; x++){
			for(int y = 1; y <= x; y++){
				//\to为制表符,保证右对齐
				System.out.print(y+"*"+x+"="+y*x+"\t");
			}
			System.out.println();
		}
	}
	
	public static void printCFB(){
		printCFB(9);
	}
}
8、数组
格式1、元素类型[] 数组名 = new 元素类型[元素个数或数组长度]
       示例:int[] arr = new int[5];
格式2、元素类型[] 数组名 = new 元素类型[] {元素, 元素, ......};
       示例:int[] arr = new int[]{3, 5, 1, 7};
	         int[] arr = {3, 5, 1, 7};
/*java  java中一般用int[] a; c++一般用int a[];
 一维数组:
1.int[] a; //声明没有初始化
2.int[] a = new int[5];  //初始化为默认值,int型为0
3.int[] a = {1, 2, 3, 4, 5}; //初始化为给定值,静态初始化方式
4.//错误 ,Connot define dimension expressions when an array initializer is provided
  int[] a = new int[5]{1, 2, 3, 4, 5};
  //错误,Arrays constants can only be used in initializers
  int[] array = new int[5];  array = {23, 5, 34, 12, 78, 43, 15};
  int[] array;  array = {23, 5, 34, 12, 78, 43, 15};
5.int[] a; a = new int[5];  //同2
6.//The local variable array may not have been initialized
  int[] array;  array[0] = 1;
*/
9、内存的划分
寄存器、本地方法区、方法区、栈内存、堆内存
栈内存:存储的都是局部变量,而且变量所属的作用域一旦结束,该变量就自动释放
堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都在堆中





day5
1、选择排序、冒泡排序
2、有序的数组可以使用二分查找,无序的只能顺序查找
java提供了二分查找法,如果存在返回的具体的角标位置,不存在返回的是(-插入点-13、进制转换(查表法)





day6
1、二维数组
格式1int[][] arr = new int[3][2];
       定义一个名称为arr的二维数组,有三个一维数组,每一个一维数组中有两个元素
格式2int[][] arr = new int[3][];
       arr[0] = new int[3];
	   arr[1] = new int[1];
	   arr[2] = new int[2];定义一个名称为arr的二维数组,有三个一维数组,每一个一维数组默认初始化值为null,分别进行初始化
2、面向对象 封装、继承、多态
3、用java语言对现实生活中的事物进行描述,通过类的形式来体现。
4、对事物的描述通常只关注两个方面,一个是属性,一个是行为。
5、默认初始化 int num; 显示初始化 int num = 4;
public class Car {
    int num;
    String color;
    
    void run(){
    	System.out.println(num+"..."+color);
    }
    
    public static void main(String[] args){
    	Car c = new Car();
    	c.num = 4;
    	
    	c.run();
    }
}  output:4...null
6、成员变量和局部变量的区别
a、成员变量定义在类中,整个类都可以访问;局部变量定义在局部代码块,只在所属区域有效。
b、成员变量存在于堆内存的对象中;局部变量存在于栈内存的方法中。
c、成员变量随着对象的创建而存在,随着对象的消失而消失;
   局部变量随着所属区域的存在而存在,随着所属区域的结束而释放。
d、成员变量都有默认初始化值,局部变量没有默认初始化值。
7、类类型参数 public static void show(Car c)
8、匿名对象 其实就是定义对象的简写格式
   Car c = new Car(); c.run();        new Car().run()
   a、当对象对方法仅进行一次调用的时候,就可以简化成匿名对象。
   b、匿名对象可以作为实际参数进行传递。
9、基本数据类型参数传递和引用数据类型参数传递
public class Car {
	public static void main(String[] args){
		int x = 3;
		show(x);
		System.out.println("x = "+x);
	}
	
	public static void show(int x){
		x = 4;
	}
}   //output:x = 3
public class Car {
    int x = 3;
	public static void main(String[] args){
		Car c = new Car();
		c.x = 9;
		show(c);
		System.out.println("x = "+c.x);
	}
	
	public static void show(Car c){
		c.x = 4;
	}
}   //output:x = 4
10、封装:隐藏对象的属性和内部实现细节,仅对外提供公共访问方式。





day7
1、构造函数
特点:函数名和类名相同 不用定义返回值类型,没有具体的返回值
作用:给对象进行初始化
2、默认构造函数的特点 无参
3、多个构造函数是以重载的形式存在的(第34是不同的)
public class Person {
    private String name;
    private int age;
    
    //定义一个Person类的构造函数
    Person()//构造函数,而且是空参数的
    {
    	name = "baby";
    	age = 1;
    	System.out.print("person run   ");
    }
    
    //有名字的构造函数
    Person(String n)
    {
    	name = n;
    }
    
    //有名字和年龄的构造函数
    Person(String n, int a)
    {
    	name = n;
    	age = a;
    }
    
    //有年龄和名字的构造函数
    Person(int a, String n)
    {
    	name = n;
    	age = a;
    }
    
    //speak函数
    public void speak(){
    	System.out.print(name+":"+age+"  ");
    }
    
    //主函数
    public static void main(String[] args){
    	Person p1 = new Person();
    	p1.speak();
    	Person p2 = new Person("tom");
    	p2.speak();
    	Person p3 = new Person("jack", 12);
    	p3.speak();
    	Person p4 = new Person(10, "lily");
    	p4.speak();
    }
}  //output:  person run   baby:1  tom:0  jack:12  lily:10  
4、构造函数有return语句
5this关键字
this代表其所在函数所属对象的引用,this代表本类对象的引用,当在函数内
需要调用到函数的对象时,就用thisthis也可以在构造函数中调用其他的构造函数。只能定义在构造函数的第一行。 
public class Person {
    private String name;
    private int age;
    
    //定义一个Person类的构造函数
    Person()//构造函数,而且是空参数的
    {
    	name = "baby";
    	age = 1;
    	System.out.print("person run   ");
    }
    
    //有名字的构造函数
    Person(String name)
    {
    	this.name = name;
    }
    
    //有名字和年龄的构造函数
    Person(String name, int age)
    {
    	this(name);    //利用带name参数的构造函数进行初始化
    	this.age = age;
    }
    
    //speak函数
    public void speak(){
    	System.out.print(name+":"+age+"  ");
    }
} 
6static关键字
   用于修饰成员:成员变量和成员函数
   特点:随着类的加载而加载 优先于对象存在 被所有对象所共享 可以直接被类名调用
   注意:静态方法只能访问静态成员 静态方法中不能有thissuper关键字 主函数是静态的
7、成员变量和静态变量区别
   a、生命周期不同:成员变量随着对象的创建而存在,随着对象的被回收而释放,
   静态变量随着类的加载而存在,随着类的消失而消失。
   b、调用方式:成员变量只能被对象调用,静态变量可以被对象调用,还可以被类名调用。
   c、别名不同:成员变量也称为实例变量,静态变量称为类变量。
   d、数据存储位置:成员变量存储在堆内存的对象中,静态变量数据存储在方法区。
8、内存图解
9、静态变量和静态函数
10、静态代码块(随着类的加载而执行,而且只执行一次)
   作用:用于给类进行初始化(构造函数用于给对象进行初始化)
   原因:有的类不需要创建对象,比如类中的方法都是静态的方法。
class StaticCode {
	static 
	{
		System.out.print("this is static code! ");
	}
	
	void show(){
		System.out.println("show run!");
	}
}

public class StaticCodeDemo{
	public static void main(String[] args){
		new StaticCode().show();
		//StaticCode.show();
	}
}  //output:this is static code! show run!

class StaticCode {
	static 
	{
		System.out.print("this is static code! ");
	}
	
	static void show(){
		System.out.println("show run!");
	}
}

public class StaticCodeDemo{
	public static void main(String[] args){
		//new StaticCode().show();
		StaticCode.show();
	}
}  //output:this is static code! show run!
11、构造代码块对所有对象进行初始化,构造函数对对应对象进行针对性的初始化。





day8
1、继承
   提高代码复用性,让类和类之间产生了关系,为多态创造前提
2、java中支持单继承,不直接支持多继承,但对c++中的多继承机制进行改良。
   单继承:一个子类只有一个直接父类。
   多继承:一个子类可以有多个直接父类(java中不允许,进行改良)
           不直接支持,因为多个父类中有相同成员,会产生调用不确定性。
    如下:
class A{
	void show(){
		System.out.println("a");
	}
}
class B{
	void show(){
		System.out.println("b");
	}
}
class C extends A,B{
	
}
当调用new C().show()时,会产生调用的不确定性。
3、java支持多层(多重)继承。 c继承b,b继承a
   当要使用一个继承体系时,查看该体系中的顶层类,了解该体系基本功能,
   查看最子类队象,完成功能使用。
4、本类中的成员和局部变量同名用this区分,子父类中的成员变量同名用super区分交换。
   thissuper的用法很相似,this代表本类对象的一个引用,super代表一个父类空间。
class Fu{
	int num = 4;
}

public class ZiLei extends Fu{
    int num = 5;
    
    void show(){
    	System.out.println(this.num + "......" + super.num);
    }
    
    public static void main(String[] args){
    	ZiLei z = new ZiLei();
    	z.show();
    }
}  //output:5......4
5、子类不能直接访问父类中的私有成员变量,通过public修饰的接口间接访问。
6、当子父类中出现成员函数一模一样的情况,会运行子类的函数,称为覆盖(重写)。
   重写注意事项:
   a、子类方法覆盖父类方法时,子类权限必须要大于等于父类的权限。
   b、静态只能覆盖静态,或被静态覆盖。
7、何时使用重写?升级,要添加新功能,但不更改原来的类中的内容,提高程序的扩展性。
8、强制一个类不能创建对象,可以将该类的构造函数私有化。
   class ArrayTool{ private ArrayTool(){} }
9、D:\Program Files(x86)\Java\jdk1.8.0_131\bin\javadoc.exe 提取文档注释
10、设计模式 
   单例模式(Singleton Pattern):Ensure a class has only one instance,and provided a 
   global point of access to it.
   单例设计模式,解决的问题:可以保证一个类在内存中的对象唯一性。 
   如何保证唯一性:
     a、不允许其他程序用new创建该类对象。
     b、在该类创建一个本类实例。
     c、对外提供一个方法让其他程序可以获取该对象。
//饿汉式:	 
public class Emperor{
	//b、在该类创建一个本类实例。
	private static final Emperor emperor = new Emperor();
	//a、不允许其他程序用new创建该类对象。
	private Emperor(){
		
	}
	//c、对外提供一个方法让其他程序可以获取该对象。
	public static Emperor getInstance(){
		return emperor;
	}
	public static void say(){
		System.out.println("我是...");
	}
}  //该代码摘自《设计模式之禅》p58
//懒汉式
public class Emperor{
	//b、在该类创建一个本类实例。
	private static Emperor emperor = null;
	//a、不允许其他程序用new创建该类对象。
	private Emperor(){
		
	}
	//c、对外提供一个方法让其他程序可以获取该对象。
	public static Emperor getInstance(){
		if(emperor == null)
		{
			emperor = new Emperor();
		}
		return emperor;
	}
	public static void say(){
		System.out.println("我是...");
	}
}   //多线程,高并发情况下可能无法保证只实例化一个对象,使用synchronized。





day9
1、子父类中的构造函数
在子类构造对象时,发现,访问子类构造函数时,父类也运行了。原因是在子类的构造
函数中第一行有一个默认的隐式语句:super();,调用的就是父类中的空参数的构造函数。
子类的实例化过程,子类中所有的构造函数默认都会访问父类中的空参数的构造函数(但可以
自行指定带参构造函数)。
2、为什么子类实例化的时候要访问父类中的构造函数?
子类会使用父类的属性等,父类的构造函数中可能对某些属性进行了一些操作。
3、子类构造函数中如果使用this调用了本类构造函数时,那么super就没有了,因为superthis都只能定义在第一行。
4class Fu
{
	Fu()
	{
		super();
		show();
		return;
	}
	void show()
	{
		System.out.println("fu show");
	}
}
class Zi extends Fu
{
	int num = 8;
	Zi()
	{
		super();
		//-->通过super初始化父类内容时,子类的成员变量并未显示初始化。等super()父类初始化完毕后,
		//才进行子类的成员变量显示初始化。
		System.out.println("zi cons run...."+num);
		return;
	}
	void show()
	{
		System.out.println("zi show..."+num);
	}
}
class ExtendsDemo5 
{
	public static void main(String[] args) 
	{
		Zi z = new Zi();   //先查找子类中的show方法
		z.show();
	}
}
/*
一个对象实例化过程:
Person p = new Person();
1,JVM会读取指定的路径下的Person.class文件,并加载进内存,
	并会先加载Person的父类(如果有直接的父类的情况下).
2,在堆内存中的开辟空间,分配地址。
3,并在对象空间中,对对象中的属性进行默认初始化。
4,调用对应的构造函数进行初始化。
5,在构造函数中,第一行会先到调用父类中构造函数进行初始化。
6,父类初始化完毕后,在对子类的属性进行显示初始化。
7,在进行子类构造函数的特定初始化。
8,初始化完毕后,将地址值赋值给引用变量.
*/
5final关键字
final可以修饰类(不可被继承);方法(不可被覆盖);变量(是一个常量,只能被赋值一次)
6、内部类只能访问被final修饰的局部变量(内部类在局部位置上只能访问局部中被final修饰的局部变量。)
7、抽象类特点:  
a、含abstract修饰符的class即为抽象类,abstract类不能创建实例。 
b、含有abstract方法的类必须定义为abstract class。 
c、abstract 类中定义的抽象方法必须在具体子类中实现,所以不能有抽象构造方法或抽象静态方法(可以有静态方法)。 
d、abstract 类中的方法不是必须是抽象的。 
e、子类没有实现抽象父类中的所有抽象方法,那么子类也必须定义为abstract类型。 
8、抽象类中有构造函数,用于给子类对象进行初始化
9、抽象类中可以不定义抽象方法,但很少见,目的是不让该类创建对象。
awt的适配器对象就是这种类。通常这个类中的方法有方法体,但没有内容。
10、抽象关键字不可以和privatestaticfinal共存
11、接口定义:interface()
a、接口中的所有方法都必须是抽象的。 
b、接口中的方法定义默认为public abstract类型。 
c、接口中的变量默认为public static final
12、接口实现:implements  class DemoImpl implements Demo
13、java中的类不支持多继承,所以java将多继承进行改良,在java中变成多实现。一个类可以实现多个接口。
如下:
interface A{
	public void show();
}
interface B{
	public void show();
}
class C implements A,B{    //多实现
	public void show()
	{
		//不会存在调用的不确定性
	}
}
14、一个类在继承另一个类的同时,还可以实现多个接口
interface A{
	public void show();
}
interface B{
	public void show();
}
class Q{
	public void method(){
		
	}
}

 class C extends Q implements A,BAD_CONTEXT{
	 
 }
所以,接口的出现,避免了单继承的局限性。
15、接口与接口之间是继承关系,接口可以多继承。
interface A{
	public void show();
}
interface B{
	public void method();
}
interface QQ extends A,B{
	public void function();
}
class WW implements QQ{
	//覆盖了三个方法
	public void show(){};
	public void method(){};
	public void function(){};
}





day10
1、接口示例
/*
笔记本电脑使用。
为了扩展笔记本的功能,但日后出现什么功能设备不知道。

定义一个规则,只要日后出现的设备都符合这个规则就可以了。
规则在java中就是接口。
*/
interface USB// 暴露的规则。
{
	public void open();
	public void close();
}
class BookPC
{
	public static void main(String[] args)
	{
		useUSB(new UPan());//功能扩展了。
		useUSB(new UsbMouse());
	}
	//使用规则。
	public static void useUSB(USB u)//接口类型的引用,用于接收(指向)接口的子类对象。//USB u= new UPan();
	{
		if(u!=null)
		{
			u.open();
			u.close();
		}
	}
}
//一年后。------------------------------
//实现规则。
//这些设备和电脑的耦合性降低了。
class UPan implements USB
{
	public void open()
	{
		System.out.println("upan open");
	}
	public void close()
	{
		System.out.println("upan close");
	}

}
class UsbMouse implements USB
{
	public void open()
	{
		System.out.println("UsbMouse open");
	}
	public void close()
	{
		System.out.println("UsbMouse close");
	}

}
2、多态 某一事物的多种存在形态,在代码中的体现是父类或者接口的引用指向子类的对象。
3、多态提高了代码的扩展性,前期定义的代码可以使用后期的内容,但不能使用后期子类的特有内容。
4、转型,向上转型和向下转型
abstract class Animal
{
	abstract void eat();
}
class Cat extends Animal
{
	void eat()
	{
		System.out.println("吃鱼");
	}
	void catchMouse()
	{
		System.out.println("抓老鼠");
	}
}
class DuoTaiDemo 
{
	public static void main(String[] args) 
	{
		Animal a = new Cat(); //自动类型提升,猫对象提升了动物类型。但是特有功能无法访问。
							  //作用就是限制对特有功能的访问。
							  //专业讲:向上转型。将子类型隐藏。就不能使用子类的特有方法。
		a.eat();
		//如果还想用具体动物猫的特有功能。 
		//你可以将该对象进行向下转型。
		Cat c = (Cat)a;//向下转型的目的是为了使用子类中的特有方法。
		c.eat();
		c.catchMouse();

		//注意:对于转型,自始自终都是子类对象在做着类型的变化。
		Animal a1 = new Dog();
		Cat c1 = (Cat)a1;      //ClassCastException,编译可以通过,运行不能通过
	}
}
5、类型(类或接口)判断 instanceof
//判断ArrayList中的元素的类型也有用到过
public class ListTest {
	 public static void main(String[] args) {  
        List<String> arr = new ArrayList<String>();  
        arr.add("a");  
        arr.add("b");  
        arr.add("a");  
        arr.add("d");  
        arr.add("d");  
        arr.add("e");  
        for (int i = 0; i < arr.size(); i++) {  
        	boolean result = arr.get(i) instanceof String;
        	System.out.print(result+" ");
        } 
        System.out.print("删除前:"+arr.toString()+" ");  
        for (int i = 0; i < arr.size() - 1; i++) {  
            for (int j = arr.size() - 1; j > i; j--) {  
                if(arr.get(j).toString().equals(arr.get(i).toString())){  
                    arr.remove(j);  
                }  
            }  
        }  
        System.out.println("删除后:"+arr.toString());  
    }  
}   //output:true true true true true true 删除前:[a, b, a, d, d, e] 删除后:[a, b, d, e]
6、在向下转型时,先使用instanceof来判断类型
public static void method(Animal a)//Animal a = new Dog();
	{
		a.eat();
		//通常在向下转型前用于健壮性的判断。
		if(a instanceof Cat)//instanceof:用于判断对象的具体类型。只能用于引用数据类型判断
		{
			Cat c = (Cat)a;
			c.catchMouse();
		}
	}
7、多态时,成员的特点:
a、成员变量
	编译时:参考引用型变量所属的类中的是否有调用的成员变量,有,编译通过,没有,编译失败。
	运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
	简单说:编译和运行都参考等号的左边。
b、成员函数(非静态)
	编译时:参考引用型变量所属的类中的是否有调用的函数。有,编译通过,没有,编译失败。
	运行时:参考的是对象所属的类中是否有调用的函数。
	简单说:编译看左边,运行看右边。因为成员函数存在覆盖特性。
c、静态函数
	编译时:参考引用型变量所属的类中的是否有调用的静态方法。
	运行时:参考引用型变量所属的类中的是否有调用的静态方法。
	简单说,编译和运行都看左边。其实对于静态方法,是不需要对象的(所以和非静态不同,不会覆盖)。
8、内部类
将一个类定义在另一个类的里面,里面那个类就称为内部类。
访问特点:内部类可以直接访问外部类中的成员,包括私有成员。而外部类要访问内部类中的成员必须要建立内部类的对象。
9、内部类可以使用访问权限修饰符 
//直接访问外部类中的内部类中的成员
class Outer
{
	private static int num = 31;
	class Inner// 内部类。
	{
		void show()
		{
			System.out.println("show run..."+num);
		}
		/*static void function()//如果内部类中定义了静态成员,该内部类也必须是静态的。
		{
			System.out.println("function run ...."+num);
		}
		*/
	}
	public void method()
	{
		Inner in = new Inner();
		in.show();
	}
}
class InnerClassDemo
{
	public static void main(String[] args) 
	{
		//直接访问外部类中的内部类中的成员。
		Outer.Inner in = new Outer().new Inner();
		in.show();

		//如果内部类是静态的。 相当于一个外部类
//		Outer.Inner in = new Outer.Inner();
//		in.show();

		//如果内部类是静态的,成员是静态的。
//		Outer.Inner.function();
		
	}
}
10、为什么内部类可以直接访问外部类的成员? 因为内部类持有了外部类的引用,外部类.this
class Outer
{
	int num = 3;
	class Inner
	{
		int num = 4;
		void show()
		{
			int num = 5;
			System.out.println(num);             //5
			System.out.println(this.num);        //4
			System.out.println(Inner.this.num);  //4
			System.out.println(Outer.this.num);  //3
		}
	}
	void method()
	{
		new Inner().show();
	}
}
class InnerClassDemo2 
{
	public static void main(String[] args) 
	{
		new Outer().method();
	}
}
11、局部内部类(内部类可以放在局部位置上)(day9 6)
内部类在局部位置上只能访问局部中被final修饰的局部变量。
class Outer
{
	int num = 3;
	Object method()
	{
		final int x = 9;

		class Inner
		{
			public String toString()
			{
				return "show ..."+x;
			}
		}
		Object in = new Inner();
		return in;//0x0045
//		in.show();
	}
}
class InnerClassDemo3 
{
	public static void main(String[] args) 
	{
		Outer out = new Outer();
		Object obj = out.method();  //方法调用完出栈,但对象还存在,所以需要将x定义为final
		System.out.println(obj);
	}
}
12、匿名内部类。就是内部类的简写格式,前提:内部类必须继承或者实现一个外部类或者接口。
匿名内部类其实就是一个匿名子类对象,格式:new 父类or接口() {子类内容}
13、当函数参数是接口类型时,而且接口中的方法不超过3个,可以用匿名内部类作为实际参数进行传递。
14、静态方法中不允许有this





day11
1、Object-equals方法
class Per extends Object
{
	private int age;
	Per(int age){
		this.age = age;
	}
}
public class ObjectTest {
    public static void main(String[] args)
    {
    	Per p1 = new Per(20);
    	Per p2 = new Per(20);
    	Per p3 = p1;
    	
    	System.out.print((p1 == p2) + " ");
    	System.out.print((p1 == p3) + " ");
    	System.out.print((p1.equals(p2)) + " ");
    	System.out.println(p1.equals(p3));
    }
}    //output false true false true
2、Object-equals方法覆盖
class Per extends Object
{
	private int age;
	Per(int age){
		this.age = age;
	}
	
	//和父类中的重载
	public boolean equals(Person obj){
		
	}
	
	//覆写(一般都会覆盖此方法,根据对象的特有内容,建立判断对象是否相同的依据)
    public boolean equals(Object obj)//Object obj = p2;
	{
		if(!(obj instanceof Person))
		{
			//return false;
			throw new ClassCastException("类型错误");
		}
		Person p = (Person)obj;
		return this.age == p.age;
	}
}
3、Object-hashCode方法
当重写equals方法时,一般重写该方法,以维护hashCode的常规协定
4、Object-getClass方法  返回Object的运行时类
5、Object-toString方法  返回该对象的字符串表现形式getClass.getName()+"@"+Integer.toHexString(hashCode())
6、异常
描述不正常情况的类称为异常类,以前将正常流程代码和问题处理代码相结合,
现在将正常流程代码和问题代码分离,提高阅读性。
7、异常分为两大类Throwable a、一般不可处理的。Error  b、可以处理的 Exception 
Throwable:无论是error,还是异常,问题发生就应该可以抛出,让调用者知道并处理。
8、可抛性通过两个关键字来体现:throwsthrow
凡是可以被这两个关键字所操作的类和对象都具备可抛性。
9、java虚拟机将传送过来的异常打印到控制台(真实开发时打印到日志)
10、异常信息可以自定义
class Demo
{
	public int method(int[] arr,int index)
	{		
		if(arr==null)
			throw new NullPointerException("数组的引用不能为空!");

		if(index>=arr.length)
		{
			throw new ArrayIndexOutOfBoundsException("数组的角标越界:"+index);
		}
		if(index<0)
		{
			throw new ArrayIndexOutOfBoundsException("数组的角标不能为负:"+index);
		}
		return arr[index];
	}
}
10、异常可以自定义,定义异常类需要继承异常体系,只有成为异常体系的子类才能具有可抛性。
11、异常的分类
a、编译时被检测异常:只要是Exception和其子类都是,除了特殊子类RuntimeException体系。
//这种问题一旦出现,希望在编译时就进行检测,让这种问题有对应的处理方式。
//这样的问题都可以针对性的处理。
b、编译时不检测异常(运行时异常):就是Exception中的RuntimeException和其子类。
//这种问题的发生,无法让功能继续,运算无法进行,更多是因为调用者的原因导致的而或者引
//发了内部状态的改变导致的。
//那么这种问题一般不处理,直接编译通过,在运行时,让调用者调用时的程序强制停
//止,让调用者对代码进行修正。
所以,当自定义的异常继承自Exception时,函数不throws出异常,编译时会报错;若
继承自RuntimeException,则编译时不会报错。
12throwthrows的区别
throws使用在函数上,throw使用在函数内;throws抛出的是异常类,可以抛出多个,throw抛出的
是异常对象。
13try(){需要被检测异常的代码} catch(异常类 变量){处理异常的代码} finally{一定会被执行的代码}
14finally代码块作用:try{} finally{} 也比较常见,异常无法直接catch处理,但资源需要关闭
例如连接数据库、查询、关闭连接。查询时出异常了,则需要靠finally代码块执行关闭动作、释放资源
15、异常转换
16、异常的注意事项
a、子类在覆盖父类方法时,父类的方法如果抛出了异常,那么子类的方法只能抛出父类的异常或者该异常的子类。
b、如果父类抛出多个异常,那么子类只能抛出父类异常的子集。





day12
1、包 对类文件进行分类管理,给类提供多层命名空间,写在程序文件的第一行
类名的全称是包名.类名 包也是一种封装形式
2、包在文件系统中的体现是文件夹。
3、包与包之间的类进行访问,被访问的包中的类必须是public的,被访问的包中的类的方法也必须是public的。
4protected不同包中只有子类可以
5public    protected    default   private
同一类中      √         √            √         √ 
同一包中      √         √            √
子类中        √         √
不同包中      √
6import关键字可以导入其他包中的类,这样可以在使用其他包中的类时,不再需要添加包名。
7、多线程的两种线程创建方式
a、以定义Thread类子类的方式创建线程  b、以创建Runnable接口实例的方式创建线程
8、调用thread.run不能开启线程,需要用thread.start才开启线程。
9、Thread.currentThread().getName()  
线程在创建时即确定了编号从Thread-0开始,也可以自行定义,通过重写带参构造函数
class Demo extends Thread
{
	private String name;
	Demo(String name)
	{
		super(name);
		//this.name = name;
	}
	public void run()
	{
		for(int x=0; x<10; x++)
		{
			System.out.println(name+"....x="+x+".....name="+Thread.currentThread().getName());
		}
	}
}
class ThreadDemo2 
{
	public static void main(String[] args) 
	{
		Demo d1 = new Demo("旺财");
		Demo d2 = new Demo("xiaoqiang");
		d1.start();//开启线程,调用run方法。
		
		d2.start();
		System.out.println("over...."+Thread.currentThread().getName());
	}
}





day13
1、线程的四种状态
            start()         ------------------------->
被创建---------------->运行    sleep()    wait()       冻结
   |                    |   <-------------------------  |
   |              run() |      sleep()    notify()      |
   |              stop()|                               |
   |      stop()        |                               |
   ------------------> 消亡 <----------------------------
sleep方法需要指定睡眠时间,单位是毫秒。
一个特殊的状态:就绪。 具备了执行资格,但是还没有获取资源。
2、CPU的执行资格:可以被CPU处理,在处理队列中排队
   CPU的执行权:正在被CPU处理的
   运行:具备执行资格和执行权  冻结:释放执行权的同时释放执行资格
   临时阻塞状态:具备执行资格,但不具备执行权,在等待其他线程释放执行权。
3、创建线程方式一:继承Thread类。
步骤:
a、定义一个类继承Thread类。
b、覆盖Thread类中的run方法。
c、直接创建Thread的子类对象创建线程。
d、调用start方法开启线程并调用线程的任务run方法执行。
4、创建线程的第二种方式:实现Runnable接口。
a、定义类实现Runnable接口
b、覆盖接口中的run方法,将线程的任务代码封装到run方法中。
c、通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递。
	为什么?因为线程的任务都封装在Runnable接口子类对象的run方法中。
	所以要在线程对象创建时就必须明确要运行的任务。
d、调用线程对象的start方法开启线程。
5、实现Runnable接口的好处:
a、将线程的任务从线程的子类中分离,进行单独封装。按照面向对象的思想将任务的封装成对象。
b、避免了java单继承的局限性。
所以,创建线程的第二种方式较为常用。
6、多次启动一个线程是非法的。
7、卖票实例 使用第二种创建线程的方法,可以只创建一个线程(有安全性问题),与static效果相同。
8、线程的安全性问题产生原因
a、多个线程在操作共享的数据 
b、操作共享数据的线程代码有多条
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会出现问题。
9、同步代码块
线程的安全性问题解决思路;
就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程时不可以参与运算的。
必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。 
在java中,用同步代码块就可以解决这个问题。
同步代码块的格式:
synchronized(对象)
{
	需要被同步的代码 ;
}
class Ticket implements Runnable//extends Thread
{
	private  int num = 100;
	Object obj = new Object();
	public void run()
	{
		while(true)
		{
			synchronized(obj)
			{
				if(num>0)
				{
					try{Thread.sleep(10);}catch (InterruptedException e){}		
					System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
				}
			}
		}
	}
}
class  TicketDemo
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();//创建一个线程任务对象。
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		Thread t3 = new Thread(t);
		Thread t4 = new Thread(t);
		t1.start();
		t2.start();
		t3.start();
		t4.start();	
	}
}
10、同步的好处:解决了线程的安全问题。
同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。
同步的前提:同步中必须有多个线程并使用同一个锁。
11、同步函数
class Bank
{
	private int sum;
	public synchronized void add(int num)//同步函数
	{
			sum = sum + num;
			try{Thread.sleep(10);}catch(InterruptedException e){}
			System.out.println("sum="+sum);
	}
}
class Cus implements Runnable
{
	private Bank b = new Bank();
	public void run()
	{
		for(int x=0; x<3; x++)
		{
			b.add(100);
		}
	}
}
12、同步函数用的锁是线程对象实例(this)的锁
同步函数和同步代码块的区别:
同步函数的锁是固定的this。同步代码块的锁是任意的对象。建议使用同步代码块。
class Ticket implements Runnable
{
	private  int num = 100;
	boolean flag = true;
	public void run()
	{
		if(flag)
			while(true)
			{
				synchronized(this)
				{
					if(num>0)
					{
						try{Thread.sleep(10);}catch (InterruptedException e){}						
						System.out.println(Thread.currentThread().getName()+".....obj...."+num--);
					}
				}
			}
		else
			while(true)
				this.show();
	}
	public synchronized void show()
	{
		if(num>0)
		{
			try{Thread.sleep(10);}catch (InterruptedException e){}
			
			System.out.println(Thread.currentThread().getName()+".....function...."+num--);
		}
	}
}
class SynFunctionLockDemo 
{
	public static void main(String[] args) 
	{
		Ticket t = new Ticket();
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);

		t1.start();
		try{Thread.sleep(10);}catch(InterruptedException e){}
		t.flag = false;
		t2.start();
	}
}
13、静态同步函数的锁是该函数所属字节码文件对象,可以用getClass方法或当前类名.class表示。
14、懒汉式单例模式的同步和效率问题
class Single
{
	private static Single s = null;
	private Single(){}
	public static Single getInstance()
	{
		if(s==null)
		{
			synchronized(Single.class)	//不能用getClass方法,因为该方法不是静态的	
			{
				if(s==null)
		//				-->0 -->1
					s = new Single();
			}
		}
		return s;
	}
}
class  SingleDemo
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
}





day14
1、线程间通讯
多个线程在处理同一资源,但任务却不同。
2、下面程序解决多线程访问同一资源的问题,但存在长时间执行一个线程,切换慢的问题
class Resource
{
	String name;
	String sex;
}
//输入
class Input implements Runnable
{
	Resource r ;
	Input(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			synchronized(r)
			{
				if(x==0)
				{
					r.name = "mike";
					r.sex = "nan";
				}
				else
				{
					r.name = "丽丽";
					r.sex = "女女女女女女";
				}
			}
			x = (x+1)%2;
		}
	}
}
//输出
class Output implements Runnable
{
	Resource r;
	Output(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			synchronized(r)
			{
				System.out.println(r.name+"....."+r.sex);
			}
		}
	}
}
class  ResourceDemo
{
	public static void main(String[] args) 
	{
		//创建资源。
		Resource r = new Resource();
		//创建任务。
		Input in = new Input(r);
		Output out = new Output(r);
		//创建线程,执行路径。
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//开启线程
		t1.start();
		t2.start();
	}
}
3、等待、唤醒机制
a、wait() 让线程处于冻结状态,被wait的线程会被存储到线程池中。
b、notify() 唤醒线程池中的一个线程(任意)。
c、notifyAll() 唤醒线程池中的所有线程。
这些方法都必须用于同步中,因为这些方法都是用于操作线程状态的方法,
必须要明确操作的哪个锁上的线程。
class Resource
{
	String name;
	String sex;
	boolean flag = false;
}
//输入
class Input implements Runnable
{
	Resource r ;
//	Object obj = new Object();
	Input(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			synchronized(r)
			{
				if(r.flag)
					try{r.wait();}catch(InterruptedException e){}
				if(x==0)
				{
					r.name = "mike";
					r.sex = "nan";
				}
				else
				{
					r.name = "丽丽";
					r.sex = "女女女女女女";
				}
				r.flag = true;
				r.notify();
			}
			x = (x+1)%2;
		}
	}
}
//输出
class Output implements Runnable
{
	Resource r;
//	Object obj = new Object();
	Output(Resource r)
	{
		this.r = r;
	}

	public void run()
	{
		while(true)
		{
			synchronized(r)
			{
				if(!r.flag)
					try{r.wait();}catch(InterruptedException e){}
				System.out.println(r.name+"....."+r.sex);
				r.flag = false;
				r.notify();
			}
		}
	}
}
class  ResourceDemo2
{
	public static void main(String[] args) 
	{
		//创建资源。
		Resource r = new Resource();
		//创建任务。
		Input in = new Input(r);
		Output out = new Output(r);
		//创建线程,执行路径。
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//开启线程
		t1.start();
		t2.start();
	}
}
4、为什么操作线程的方法wait、notify、notifyAll定义在了Object类中? 
因为这些方法是监视器的方法。监视器其实就是锁。
锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
5、将同步放在资源类中,进行优化
class Resource
{
	private String name;
	private String sex;
	private boolean flag = false;
	public synchronized void set(String name,String sex)
	{
		if(flag)
			try{this.wait();}catch(InterruptedException e){}
		this.name = name;
		this.sex = sex;
		flag = true;
		this.notify();
	}
	public synchronized void out()
	{
		if(!flag)
			try{this.wait();}catch(InterruptedException e){}
		System.out.println(name+"...+...."+sex);
		flag = false;
		notify();
	}
}
//输入
class Input implements Runnable
{
	Resource r ;
//	Object obj = new Object();
	Input(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			if(x==0)
			{
				r.set("mike","nan");
			}
			else
			{
				r.set("丽丽","女女女女女女");
			}
			x = (x+1)%2;
		}
	}
}
//输出
class Output implements Runnable
{
	Resource r;
//	Object obj = new Object();
	Output(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}
class  ResourceDemo3
{
	public static void main(String[] args) 
	{
		//创建资源。
		Resource r = new Resource();
		//创建任务。
		Input in = new Input(r);
		Output out = new Output(r);
		//创建线程,执行路径。
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//开启线程
		t1.start();
		t2.start();
	}
}
6、生产者和消费者
多生产者和多消费者(while(flag)\notifyAll)
if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行!
notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll解决了本方线程一定会唤醒对方线程的问题。
class Resource
{
	private String name;
	private int count = 1;
	private boolean flag = false;
	public synchronized void set(String name)//  
	{
		while(flag)
			try{this.wait();}catch(InterruptedException e){}//   t1    t0
		
		this.name = name + count;//烤鸭1  烤鸭2  烤鸭3
		count++;//2 3 4
		System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
		flag = true;
		notifyAll();
	}
	public synchronized void out()//  t3
	{
		while(!flag)
			try{this.wait();}catch(InterruptedException e){}	//t2  t3
		System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);//消费烤鸭1
		flag = false;
		notifyAll();
	}
}
class Producer implements Runnable
{
	private Resource r;
	Producer(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.set("烤鸭");
		}
	}
}
class Consumer implements Runnable
{
	private Resource r;
	Consumer(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}
class  ProducerConsumerDemo
{
	public static void main(String[] args) 
	{
		Resource r = new Resource();
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);

		Thread t0 = new Thread(pro);
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t3 = new Thread(con);
		t0.start();
		t1.start();
		t2.start();
		t3.start();
	}
}
7、jdk1.5新特性lock(锁)和condition(监视器)
一把锁获取两组监视器,一组监视生产者,一组监视消费者
/*
jdk1.5以后将同步和锁封装成了对象。 
并将操作锁的隐式方式定义到了该对象中,
将隐式动作变成了显示动作。

Lock接口: 出现替代了同步代码块或者同步函数。将同步的隐式锁操作变成现实锁操作。
同时更为灵活。可以一个锁上加上多组监视器。
lock():获取锁。
unlock():释放锁,通常需要定义finally代码块中。

Condition接口:出现替代了Object中的wait notify notifyAll方法。
			将这些监视器方法单独进行了封装,变成Condition监视器对象。
			可以任意锁进行组合。
await();
signal();
signalAll();
*/
import java.util.concurrent.locks.*;
class Resource
{
	private String name;
	private int count = 1;
	private boolean flag = false;
//	创建一个锁对象。
	Lock lock = new ReentrantLock();
	//通过已有的锁获取该锁上的监视器对象。
//	Condition con = lock.newCondition();
	//通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者。
	Condition producer_con = lock.newCondition();
	Condition consumer_con = lock.newCondition();
	public  void set(String name)//  t0 t1
	{
		lock.lock();
		try
		{
			while(flag)
//			try{lock.wait();}catch(InterruptedException e){}//   t1    t0
			try{producer_con.await();}catch(InterruptedException e){}//   t1    t0
		
			this.name = name + count;//烤鸭1  烤鸭2  烤鸭3
			count++;//2 3 4
			System.out.println(Thread.currentThread().getName()+"...生产者5.0..."+this.name);//生产烤鸭1 生产烤鸭2 生产烤鸭3
			flag = true;
//			notifyAll();
//			con.signalAll();
			consumer_con.signal();
		}
		finally
		{
			lock.unlock();
		}
		
	}
	public  void out()// t2 t3
	{
		lock.lock();
		try
		{
			while(!flag)
//			try{this.wait();}catch(InterruptedException e){}	//t2  t3
			try{cousumer_con.await();}catch(InterruptedException e){}	//t2  t3
			System.out.println(Thread.currentThread().getName()+"...消费者.5.0......."+this.name);//消费烤鸭1
			flag = false;
//			notifyAll();
//			con.signalAll();
			producer_con.signal();
		}
		finally
		{
			lock.unlock();
		}
		
	}
}
class Producer implements Runnable
{
	private Resource r;
	Producer(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.set("烤鸭");
		}
	}
}
class Consumer implements Runnable
{
	private Resource r;
	Consumer(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}
class  ProducerConsumerDemo2
{
	public static void main(String[] args) 
	{
		Resource r = new Resource();
		Producer pro = new Producer(r);
		Consumer con = new Consumer(r);

		Thread t0 = new Thread(pro);
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		Thread t3 = new Thread(con);
		t0.start();
		t1.start();
		t2.start();
		t3.start();

	}
}
8、a、wait可以指定时间也可以不指定。
   sleep必须指定时间。
   b、在同步中时,对cpu的执行权和锁的处理不同。
   wait:释放执行权,释放锁。
   sleep:释放执行权,不释放锁。
9、停止线程方式 定义标记和interrupt(将线程从冻结态强制转换到运行态,会抛出异常)
10、setDaemon将线程标记为守护(后台)线程或用户线程。当运行的线程都是守护线程时,Java虚拟机退出。 
11、join等待该线程运行完成。setPriority设置优先级。





day15
1、字符串对象一旦被创建就不会再改变,存储在字符串常量区中。
2、String类中的equals覆写了Object中的equals,建立了string类的判断字符串是否相同的依据。
public class StringDemo {
	public static void main(String[] args) {
        stringDemo1();
		stringDemo2();
	}
	//output 
	/*true
    false
    false
    true
    s=abc
    s1=abc*/
	public static void stringDemo2() {
		// TODO Auto-generated method stub
		
		String s = "abc";//创建一个字符串对象在常量池中。		
		String s1 = new String("abc");//创建两个对象一个new一个字符串对象在堆内存中。
		
		System.out.println(s==s1);//false
		System.out.println(s.equals(s1));
		//string类中的equals复写Object中的equals建立了string类自己的判断字符串对象是否相同的依据。
		//其实就是比较字符串内容。
		System.out.println("s="+s);
		System.out.println("s1="+s1);	
	}
	/**
	 * 演示字符串定义的第一种方式,并明确字符串常量池的特点.
	 * 池中没有就建立,池中有,直接用。
	 */
	private static void stringDemo1() {
		String s = "abc";//"abc"存储在字符串常量池中。
		String s1 = "abc";		
		System.out.println(s==s1);//true
		s = "nba";
		System.out.println(s==s1);
	}
}
4、String的构造函数
public class StringConstructorDemo {
	public static void main(String[] args) {
		//将字节数组或者字符数组转成字符串可以通过String类的构造函数完成。
        stringConstructorDemo();
		stringConstructorDemo2();
	} 
	//output
	//s1=aBCD
    //s=apq
	private static void stringConstructorDemo2() {
		char[] arr = {'w','a','p','q','x'};
		String s = new String(arr,1,3);
		System.out.println("s="+s);
	}
	public static void stringConstructorDemo() {
		String s = new String();//等效于String s = "";  不等效String s = null;
		byte[] arr = {97,66,67,68};
		String s1 = new String(arr);
		System.out.println("s1="+s1);	
	}
}
3、字符串的相关操作
  按照面向对象的思想对字符串进行功能分类。
  a、获取
    1.1 获取字符串中字符的个数(长度).
    	int length();
    1.2 根据位置获取字符。
    	char charAt(int index);
    1.3 根据字符获取在字符串中的第一次出现的位置.
    	int indexOf(int ch)
    	int indexOf(int ch,int fromIndex):从指定位置进行ch的查找第一次出现位置 
    	int indexOf(String str);
    	int indexOf(String str,int fromIndex);
    	 根据字符串获取在字符串中的第一次出现的位置.
    	int lastIndexOf(int ch)
    	int lastIndexOf(int ch,int fromIndex):从指定位置进行ch的查找第一次出现位置 
    	int lastIndexOf(String str);
    	int lastIndexOf(String str,int fromIndex);
    1.4 获取字符串中一部分字符串。也叫子串.
    	String substring(int beginIndex, int endIndex)//包含begin 不包含end 。
    	String substring(int beginIndex);
  b、转换
  	2.1 将字符串变成字符串数组(字符串的切割)
  		String[]  split(String regex):涉及到正则表达式.
  	2.2 将字符串变成字符数组。
  		char[] toCharArray();
  	2.3 将字符串变成字节数组。
  		byte[] getBytes();
  	2.4 将字符串中的字母转成大小写。
  		String toUpperCase():大写
  		String toLowerCase():小写
 	2.5  将字符串中的内容进行替换
 		String replace(char oldch,char newch);
  		String replace(String s1,String s2);
  	2.6 将字符串两端的空格去除。
  		String trim();
  	2.7 将字符串进行连接 。
  		String concat(string);
  c、判断
  	3.1 两个字符串内容是否相同啊?
  		boolean equals(Object obj);
  		boolean equalsIgnoreCase(string str);忽略大写比较字符串内容。
  	3.2 字符串中是否包含指定字符串?
  		boolean contains(string str);
  	3.3 字符串是否以指定字符串开头。是否以指定字符串结尾。
  		boolean startsWith(string);
  		boolean endsWith(string);
  d、比较 compareTo();
5intern():对字符串池进行操作的
6、StringBuffer
 StringBuffer:就是字符串缓冲区。用于存储数据的容器。
 特点:
 a、长度的可变的。 
 b、可以存储不同类型数据。
 c、最终要转成字符串进行使用。
 d、可以对字符串进行修改。
7、既然是一个容器对象。应该具备功能
 a、添加:
 	StringBuffer append(data);
 	StringBuffer insert(index,data);
 b、删除:
 	StringBuffer delete(start,end):包含头,不包含尾。
 	StringBuffer deleteCharAt(int index):删除指定位置的元素 
 c、查找:
 	char charAt(index);
 	int indexOf(string);
 	int lastIndexOf(string);
 d、修改:
 	StringBuffer replace(start,end,string);
 	void setCharAt(index,char);
8、jdk1.5以后出现了功能和StringBuffer一模一样的对象。就是StringBuilder
不同的是:
StringBuffer是线程同步的。通常用于多线程。
StringBuilder是线程不同步的。通常用于单线程。 它的出现提高效率。
jdk升级:简化书写。提高效率。增加安全性。





day16
1、基本数据类型对象包装类
好处:可以在对象中定义更多的功能方法操作该数据。
2、基本数据类型对应的封装类
byte        Byte
short       Short
int         Integer
long        Long
float       Float
double      Double
char        Character
boolean     Boolean
3、该包装对象主要用于基本类型和字符串之间的转换
 基本类型--->字符串
 	a,基本类型数值+""
 	b,用String类中的静态方法valueOf(基本类型数值);
 	c,用Integer的静态方法valueOf(基本类型数值);
 字符串--->基本类型
 	a,使用包装类中的静态方法   xxx parseXxx("xxx类型的字符串");*****
 	int parseInt("intstring");
 	long parseLong("longstring");
 	boolean parseBoolean("booleanstring");
 	只有Character没有parse方法 
 	b,如果字符串被Integer进行对象的封装。
 	可使用另一个非静态的方法,intValue();
 	将一个Integer对象转成基本数据类型值。
4、进制转换
整数具备不同的进制体现
 十进制-->其他进制
 	toBinaryString
 	toOctalString
 	toHexString
	System.out.println(Integer.toBinaryString(60));
	System.out.println(Integer.toOctalString(60));
	System.out.println(Integer.toHexString(60));
 其他进制-->十进制
 	parseInt("string",radix)
	System.out.println(Integer.parseInt("3c",16)); 
5、自动装箱 Integer i = new Integer(4);  Integer i = 4;(jdk1.5之后新特性,自动装箱)
    Integer a = new Integer(128);
    Integer b = new Integer(128);
    System.out.print((a == b) + " ");
    System.out.print(a.equals(b) + " ");
    Integer a1 = new Integer(129);
    Integer b1 = new Integer(129);
    System.out.print((a1 == b1) + " ");
    System.out.print(a1.equals(b1) + " ");
    Integer x = 127;
    Integer y = 127; //jdk1.5以后,装箱的如果是一个字节,那么数据会被共享不会重新开辟空间
    System.out.print((x == y) + " ");
    System.out.print(x.equals(y) + " ");
    Integer x1 = 128;
    Integer y1 = 128;
    System.out.print((x1 == y1) + " ");
    System.out.print(x1.equals(y1) + " ");
    //output:false true false true true true false true 
6、集合框架
为什么会出现集合类?
用于存放对象的容器。数组是固定长度,集合长度可变。集合中不可以存储基本数据类型值。
7、体系与共性功能
集合容器因为内部的数据结构不同,有多种具体容器。不断向上抽取,就形成了集合框架。
框架的顶层就是Collection接口,其常见方法如下:
a、添加:
   boolean add(E e);
   boolean addAll(Collection<?> coll);
b、删除:
   boolean remove(object obj);
   boolean removeAll(Collection<?> coll);
   void clear();
c、判断:
   boolean contains(object obj);
   boolean containsAll(Collection coll);
   boolean isEmpty();  //判断集合中是否有元素
d、获取:
   int size();
   Iterator<E> iterator(); //取出集合元素的方式
e、其他:
   boolean retainAll(Collection coll); //取交集
   Object[] toArray();  //将集合转换成数组
8、迭代器的使用
public class IteratorDemo {
	public static void main(String[] args) {
		Collection coll = new ArrayList();
		coll.add("abc1");
		coll.add("abc2");
		coll.add("abc3");
		coll.add("abc4");
		//使用了Collection中的iterator()方法。 调用集合中的迭代器方法,是为了获取集合中的迭代器对象。
//		Iterator it = coll.iterator();		
//		while(it.hasNext()){
//			System.out.println(it.next());
//		}
		for(Iterator it = coll.iterator(); it.hasNext(); ){
			System.out.println(it.next());
		}
	}
}
9、List和Set的区别
List:有序(存入和取出的顺序一致),元素都有索引,可以重复。
Set: 元素不能重复,无序。
10、List的常用方法:共性特点是可以操作角标。
a、增加:
   void add(index, element);
   void add(index,collection);
b、删除:
   Object remove(index);
c、修改:
   Object set(index,element);
d、获取:
   Object get(index);
   int indexOf(object);
   int lastIndexOf(object);
   List subList(from, to);
11、ListIterator接口 迭代过程中修改集合  
public class ListDemo2 {
	public static void main(String[] args) {
		List list = new ArrayList();
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		System.out.println("list:"+list);
		ListIterator it = list.listIterator();//获取列表迭代器对象
		//它可以实现在迭代过程中完成对元素的增删改查。
		//注意:只有list集合具备该迭代功能.
		while(it.hasNext()){	
			Object obj = it.next();
			if(obj.equals("abc2")){
				it.set("abc9");
			}
		}
//		System.out.println("hasNext:"+it.hasNext());
//		System.out.println("hasPrevious:"+it.hasPrevious());
		while(it.hasPrevious()){
			System.out.println("previous:"+it.previous());
		}
		System.out.println("list:"+list);
		/*Iterator it = list.iterator();
		while(it.hasNext()){
			Object obj = it.next();//java.util.ConcurrentModificationException
			//在迭代器过程中,不要使用集合操作元素,容易出现异常。
			//可以使用Iterator接口的子接口ListIterator来完成在迭代中对元素进行更多的操作
			if(obj.equals("abc2")){
				list.add("abc9");
			}
			else
				System.out.println("next:"+obj);
		}
		System.out.println(list);
		*/
	}
	public static void show(List list) {
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		list.add("abc4");
		Iterator it = list.iterator();
		while(it.hasNext()){
			System.out.println("next:"+it.next());
		}
		//list特有的取出元素的方式之一。
		for(int x=0; x<list.size(); x++){
			System.out.println("get:"+list.get(x));
		}
	}
}
12、List子类
Vector:内部是数组数据结构,是同步的,线程安全。
ArrayList:内部是数组数据结构,是不同步的。替代Vector。查询速度快。
LinkedList:内部是链表数据结构,是不同步的。增删元素的速度很快。  
   
   
   
   
   
day17
1、LinkedList
   addFist(E e);  addLast(E e);  
   offerFirst();  offerLast();  jdk1.6 
   getFirst();  getLast();  
   peekFirst(); peekLast(); jdk1.6 当链表为空时,不抛出异常,返回空
   removeFirst();  removeLast();
   pollFirst();    pollLast(); jdk1.6 当链表为空时,不抛出异常,返回空
2、用LinkedList模拟一个堆栈或者数据结构
import java.util.LinkedList;
public class DuiLie {
	private LinkedList link;
	public DuiLie() {
		link = new LinkedList();
	}
	public void myAdd(Object obj) {
		link.addLast(obj);
	}
	public Object myGet() {
		return link.removeFirst();
	}
	public boolean isNull() {
		return link.isEmpty();
	}
}
3、ArrayList存储自定义对象
import java.util.ArrayList;
import java.util.Iterator;
import cn.itcast.p.bean.Person;
public class ArrayListTest {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Person p1 = new Person("lisi1",21);
		
		ArrayList al = new ArrayList();
		al.add(p1);
		al.add(new Person("lisi2",22));
		al.add(new Person("lisi3",23));
		al.add(new Person("lisi4",24));
		
		Iterator it = al.iterator();
		while(it.hasNext()){
//			System.out.println(((Person) it.next()).getName()+"::"+((Person) it.next()).getAge());
			Person p = (Person) it.next();
			System.out.println(p.getName()+"--"+p.getAge());
		}
//		al.add(5);//al.add(new Integer(5));
	}
}
4、HashSet元素不能重复,无序。Set中的方法和Collection中一样。
5、HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。
不保证迭代顺序,也不保证该顺序恒久不变,此类允许使用null元素。
6、哈希表确定元素是否相同 
a、判断两个元素的哈希值是否相同,如果相同,判断两个对象内容是否相同。
b、判断哈希值是否相同,其实判断的是hashCode的方法。判断内容用的equals方法。
7、HashSet存储自定义对象
public class Person /*extends Object*/ implements Comparable {
	private String name;
	private int age;
	public Person() {
		super();
		
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int hashCode() {
		return name.hashCode()+age*27;
	}
	@Override
	public boolean equals(Object obj) {
		
		if(this == obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException("类型错误");
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String toString(){
		return name+":"+age;
	}
	@Override
	public int compareTo(Object o) {
		
		Person p = (Person)o;
		
		int  temp = this.age-p.age;
		return temp==0?this.name.compareTo(p.name):temp;
	}
}

public class HashSetTest {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		HashSet hs = new HashSet();
		/*
		 * HashSet集合数据结构是哈希表,所以存储元素的时候,
		 * 使用的元素的hashCode方法来确定位置,如果位置相同,在通过元素的equals来确定是否相同。
		 * 
		 */
		hs.add(new Person("lisi4",24));
		hs.add(new Person("lisi7",27));
		hs.add(new Person("lisi1",21));
		hs.add(new Person("lisi9",29));
		hs.add(new Person("lisi7",27));
		
		Iterator it = hs.iterator();
		while(it.hasNext()){
			Person p = (Person)it.next();
			System.out.println(p);
		}
	}
}
8、LinkedHashSet具有可预知迭代顺序的Set接口的哈希表和链接列表实现。
9、TreeSet 使用元素的自然顺序对数据进行排序,是不同步的。
   判断元素唯一性的方式:就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。
   TreeSet排序自定义的对象,需要重写compareTo方法。
10、Treeset如果不要按照对象中具备的自然排序进行排序,或不具备自然排序,使用第二种方法:
   让集合自身具备比较功能,利用创建集合时的构造函数
   Treeset(Comparator<? super E> comparator) 构造一个新的空TreeSet,它根据指定比较器进行排序。
package cn.itcast.p5.comparator;
import java.util.Comparator;
import cn.itcast.p.bean.Person;
/**
 * 创建了一个根据Person类的name进行排序的比较器。
 */
public class ComparatorByName implements Comparator {
	@Override
	public int compare(Object o1, Object o2) {

		Person p1 = (Person)o1;
		Person p2 = (Person)o2;
		
		int temp = p1.getName().compareTo(p2.getName());
		
		return temp==0?p1.getAge()-p2.getAge(): temp;
	}
}
package cn.itcast.p5.treeset.demo;
import java.util.Iterator;
import java.util.TreeSet;
import cn.itcast.p.bean.Person;
import cn.itcast.p5.comparator.ComparatorByName;
public class TreeSetDemo {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TreeSet ts = new TreeSet(new ComparatorByName());
		//以Person对象年龄进行从小到大的排序。
		ts.add(new Person("zhangsan",28));
		ts.add(new Person("lisi",21));
		ts.add(new Person("zhouqi",29));
		ts.add(new Person("zhaoliu",25));
		ts.add(new Person("wangu",24));
		Iterator it = ts.iterator();
		while(it.hasNext()){
			Person p = (Person)it.next();
			System.out.println(p.getName()+":"+p.getAge());
		}
	
	}
}
11、TreeSet集合--二叉树  怎么存怎么取,实现让比较器返回1




day18
1、Map接口:一次添加一对元素,也称为双列集合。map集合必须保证键的唯一性。
2、常用方法:
a、添加
   V put(K key, V value);//返回前一个和key关联的值,没有返回空 
b、删除
   void clear();      //清空map集合
   V remove(K key);   //根据指定的key返回键值对
c、判断
   boolean containsKey(K key);
   boolean containsValue(V value);
   boolean isEmpty();
d、获取
   V get(K key);      //通过键获取值,如果没有返回null
   int size();        //获取键值对个数    
3、keySet方法
   Set<E> keySet();   //返回此映射中所包含的键的Set集合 
4、entrySet方法
   public Set<Map,Entry<K, V>> entrySet(); //返回此映射所包含的映射关系的Set视图
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapDemo {
	public static void main(String[] args) {
		Map<Integer,String> map = new HashMap<Integer,String>();
		method_2(map);
	}
	public static void method_2(Map<Integer,String> map){
		map.put(8,"zhaoliu");
		map.put(2,"zhaoliu");
		map.put(7,"xiaoqiang");
		map.put(6,"wangcai");
		Collection<String> values = map.values();
		Iterator<String> it2 = values.iterator();
		while(it2.hasNext()){
			System.out.println(it2.next());
		}
		/*
		 * 通过Map转成set就可以迭代。
		 * 找到了另一个方法。entrySet。
		 * 该方法将键和值的映射关系作为对象存储到了Set集合中,而这个映射关系的类型
		 就是Map.Entry类型(结婚证)
		 */
		Set<Map.Entry<Integer, String>> entrySet = map.entrySet();
		Iterator<Map.Entry<Integer, String>> it = entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Integer, String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key+"::::"+value);
		}
		//取出map中的所有元素。
		//原理,通过keySet方法获取map中所有的键所在的Set集合,在通过Set的迭代器获取到每一个键,
		//在对每一个键通过map集合的get方法获取其对应的值即可。
		/*
		Set<Integer> keySet = map.keySet();
		Iterator<Integer> it = keySet.iterator();
		
		while(it.hasNext()){
			Integer key = it.next();
			String value = map.get(key);
			System.out.println(key+":"+value);
		}
		*/	
	}
}
5、Collection<V> values();   //此映射中包含的值的Collection视图
6、Map常用子类:
   Hashtable:内部结构是哈希表,是同步的。不允许null作为键和值。
       Properties:表示一个持久的属性集,可以保存在流中或从中加载。属性列表中每个
	   键及对应值都是一个字符串。
   HashMap:内部结构是哈希表,不是同步的。允许null作为键和值。
   TreeMap:内部结构是二叉树,不是同步的。可以对Map集合中的键值进行排序。
7、泛型(JDK1.5以后出现的机制)ArrayList<String> a1 = new ArrayList<String>();
   泛型出现的原因:提高集合的安全性。
   反省出现的好处:将运行时期的问题暴露在编译时期。避免了强制转换的麻烦。
   泛型的书写格式:<>就是一个用于接收具体引用数据类型的参数范围。在程序中,只要用到
       了带有<>的类或者接口,就要明确传入的具体引用数据类型。
   自定义泛型类:
   public class Tool<QQ>{
		private QQ q;
		public QQ getObject() {
			return q;
		}
		public void setObject(QQ object) {
			this.q = object;
		}
   }
8、擦除与补偿
   泛型技术是给编译器使用的技术,用于编译时期,确保类型安全。
   运行时,会将泛型去掉,生成的class文件中是不带泛型的,这个称为泛型的擦除,
   目的为了兼容运行的类加载器。
   在运行时,通过获取元素的类型进行转换动作,不用使用者进行强制转换,称为泛型的补偿。
9、泛型方法(泛型定义在类型的前面,修饰符的后面)
public class Tool<QQ>{
	private QQ q;
	public QQ getObject() {
		return q;
	}

	public void setObject(QQ object) {
		this.q = object;
	}
	
	/**
	 * 将泛型定义在方法上。
	 * @param str
	 */
	public <W> void show(W str){
		System.out.println("show : "+str.toString());
	}
	public void print(QQ str){
		System.out.println("print : "+str);
	}
	
	/**
	 * 当方法静态时,不能访问类上定义的泛型。如果静态方法使用泛型,
	 * 只能将泛型定义在方法上。 
	 * @param obj
	 */
	public static <Y> void method(Y obj){
		System.out.println("method:"+obj);
	}
}
10、泛型接口
public class GenericDefineDemo5 {
	public static void main(String[] args) {
		InterImpl in = new InterImpl();
		in.show("abc");
		
		InterImpl2<Integer> in2 = new InterImpl2<Integer>();
		in2.show(5);
	}
}
//泛型接口,将泛型定义在接口上。 
interface Inter<T>{
	public void show(T t);
}
class InterImpl2<Q> implements Inter<Q>{
	public void show(Q q){
		System.out.println("show :"+q);
	}
}
class InterImpl implements Inter<String>{
	public void show(String str){
		System.out.println("show :"+str);
	}
}
11、泛型的限定  
? extends E:接收E类型或者E的子类型对象,上限
? super E:接收E类型或者E的父类型,下限
public class GenericAdvanceDemo2 {
	public static void main(String[] args) {
		ArrayList<Person> al = new ArrayList<Person>();
		al.add(new Person("abc",30));
		al.add(new Person("abc4",34));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		al2.add(new Student("stu1",11));
		al2.add(new Student("stu2",22));
		
		ArrayList<String> al3 = new ArrayList<String>();
		al3.add("stu3331");
		al3.add("stu33332");
		
		printCollection(al2);
		printCollection(al);
	}
	/*public static void printCollection(Collection<? extends Person> al) {
		Iterator<? extends Person> it = al.iterator();
		while(it.hasNext()){
			Person p = it.next();
			System.out.println(p.getName()+":"+p.getAge());
		}
	}*/
	public static void printCollection(Collection<? super Student> al){
		Iterator<? super Student> it = al.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
12、上限应用
//一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的。不会出现类型安全隐患。 
	public static void main(String[] args) {
		ArrayList<Person> al1 = new ArrayList<Person>();
		al1.add(new Person("abc",30));
		al1.add(new Person("abc4",34));
		
		ArrayList<Student> al2 = new ArrayList<Student>();
		al2.add(new Student("stu1",11));
		al2.add(new Student("stu2",22));
		
		ArrayList<Worker> al3 = new ArrayList<Worker>();
		al3.add(new Worker("stu1",11));
		al3.add(new Worker("stu2",22));
		
		ArrayList<String> al4 = new ArrayList<String>();
		al4.add("abcdeef");
//		al1.addAll(al4);//错误,类型不匹配。
		al1.addAll(al2);
		al1.addAll(al3);
		System.out.println(al1.size());
	}
}
class MyCollection<E>{
	public void add(E e){
	}
	public void addAll(MyCollection<? extends E> e){
	}
}
13、通常对集合中的元素进行取出操作时,可以是用下限。比较器
14、通配符的体现
public class GenericAdvanceDemo{
	public static void main(String[] args) {
		ArrayList<Person> al1 = new ArrayList<Person>();
		al1.add(new Person("abc",30));
		al1.add(new Person("abc4",34));
		
		ArrayList<Person> al2 = new ArrayList<Person>();
		al2.add(new Person("abc22222",30));
		al2.add(new Person("abc42222222",34));
		
		ArrayList<String> al4 = new ArrayList<String>();
		al4.add("abcdeef");
		al4.add("abc");
		al1.containsAll(al4);
	}
	public static void printCollection(Collection<?> al){
		Iterator<?> it = al.iterator();
		while(it.hasNext()){
			System.out.println(it.next().toString());
		}
	}
}
class MyCollection2<E>{
	public boolean containsAll(Collection<?> coll){
		return true;
	}
}
15、集合使用技巧
是否需要唯一
  需要:set
      是否需要指定顺序:
	  需要:TreeSet
	  不需要:HashSet
	  但是想要一个和存储一致的顺序:LinkedHashSet
  不需要:list
      是否需要频繁增删:
	  需要:LinkedList
	  不需要:ArrayList
后缀名就是该集合所属的体系,前缀名就是该集合的数据结构。
看到array:数组,查询快,有角标。
看到link:链表,增删快,add\get\remove+first\last方法。
看到hash:哈希表,想到唯一性,元素需要覆盖hashcode方法和equals方法。
看到tree:二叉树,排序,两个接口Comparable和Comparator。





day19
1、集合框架工具类Collections(s和Collection接口分开)
2、排序、折半查找、最值、逆序、替换、随机 https://docs.oracle.com/javase/8/docs/api/
3、将非同步集合转换为同步集合的方法
4、集合框架工具类Arrays
//toString的经典实现。
public static String myToString(int[] a){
	int iMax = a.length - 1;
	if (iMax == -1)
            return "[]";
       StringBuilder b = new StringBuilder();
       b.append('[');
       for (int i = 0;  ; i++) {//中间省略条件判断,提高了效率。
           b.append(a[i]);
           if (i == iMax)
    	        return b.append(']').toString();
           b.append(", ");
    }
}
5、将数组转换为List集合 Arrays类  public static <T> List<T> asList(T... a)  
    好处:可以使用集合的方法操作数组中的元素
    注意:
    数组的长度是固定的,所以对于集合的增删方法是不可以使用的,否则会报异常。
    如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
    如果数组中的元素是基本类型数值,那么会将该数组作为集合中的元素进行存储。
6、将List集合转换为数组 Collection类 Object[] toArray()
    作用:对集合中的元素操作的方法进行限定,不允许对其进行增删。
    toArray方法需要传入一个指定类型的数组。
    如果长度小于集合的size,那么该方法会创建一个同类型并和集合相同size的数组。
    如果长度大于集合的size,那么该方法就会使用指定的数组,存储集合中的元素,其他位置默认为null。
    所以建议,最后长度就指定为,集合的size。
	String[] arr = list.toArray(new String[list.size()]);
7、jdk1.5新特性:ForEach 只用于遍历,不操作,简化书写
public class ForEachDemo {
	public static void main(String[] args) {
		/*
		 * foreach语句:
		 * 格式:
		 * for(类型  变量   :Collection集合|数组)
		 * {
		 * 		
		 * }
		 * 传统for和高级for的区别?
		 * 传统for可以完成对语句执行很多次,因为可以定义控制循环的增量和条件。
		 * 
		 * 高级for是一种简化形式。
		 * 它必须有被遍历的目标。该目标要是数组,要么是Collection单列集合。
		 * 
		 * 对数数组的遍历如果仅仅是获取数组中的元素,可以使用高级for。
		 * 如果要对数组的角标进行操作建议使用传统for。 
		 */
		List<String> list =new ArrayList<String>();
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		for(String s : list){	//简化书写。		
			System.out.println(s);			
		}
		int[] arr = {3,1,5,7,4};
		for(int i : arr){
			System.out.println(i);
		}
		//可以使用高级for遍历map集合吗?不能直接用,但是可以将map转成单列的set,就可以用了。
		Map<Integer,String> map = new HashMap<Integer,String>();
		map.put(3,"zhagsan");
		map.put(1,"wangyi");
		map.put(7,"wagnwu");
		map.put(4,"zhagsansan");
		for(Integer key : map.keySet()){
			String value = map.get(key);
			System.out.println(key+"::"+value);
		}
		for(Map.Entry<Integer,String> me : map.entrySet()){
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key+":"+value);
		}
	}
}
8、jdk1.5新特性:函数可变参数
public class ParamterDemo {
	public static void main(String[] args) {
		int sum = newAdd(5,1,4,7,3);
		System.out.println("sum="+sum);
		int sum1 = newAdd(5,1,2,7,3,9,8,7,6);
		System.out.println("sum1="+sum1);
	}
	/*
	 * 函数的可变参数。
	 * 其实就是一个数组,但是接收的是数组的元素。
	 * 自动将这些元素封装成数组。简化了调用者的书写。
	 * 注意:可变参数类型,必须定义在参数列表的结尾。
	 */
	public static int newAdd(int a,int...  arr){
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum+=arr[i];
		}
		return sum;
	}
	public static int add(int[] arr){
		int sum = 0;
		for (int i = 0; i < arr.length; i++) {
			sum+=arr[i];
		}
		return sum;
	}
}
9、jdk1.5新特性:静态导入
import java.util.Collections;
import java.util.List;
import static java.util.Collections.*;//静态导入,其实到入的是类中的静态成员。
//import static java.util.Collections.max;//静态导入,其实到入的是类中的静态成员。
import static java.lang.System.*;
public class StaticImportDemo {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("abc3");
		list.add("abc7");
		list.add("abc1");
		out.println(list);
		sort(list);
		System.out.println(list);
		String max = max(list);
		System.out.println("max="+max);
	}
}





day20
1、System类
public class SystemDemo {
	private static final String LINE_SEPARATOR = System.getProperty("line.separator");
	public static void main(String[] args) {
	//System:类中的方法和属性都是静态的。
	//常见方法:
	//long currentTimeMillis();获取当前时间的毫秒值。 
		System.out.println("hello-"+LINE_SEPARATOR+" world");
		demo_1();
		//给系统设置一些属性信息。这些信息是全局,其他程序都可以使用。 
		System.setProperty("myclasspath", "c:\myclass");
	}
	
	public static void demo_1(){
		//获取系统的属性信息,并存储到了Properties集合中。 
		//properties集合中存储都是String类型的键和值。
		//最好使用它自己的存储和取出的方法来完成元素的操作。
		Properties prop = System.getProperties();
		Set<String> nameSet = prop.stringPropertyNames();
		for(String name : nameSet){
			String value = prop.getProperty(name);
			System.out.println(name+"::"+value);
		}
	}
}
2、Runtime类
public class RuntimeDemo {
	public static void main(String[] args) throws IOException, InterruptedException {
		/*
		 * Runtime:没有构造方法摘要,说明该类不可以创建对象。
		 * 又发现还有非静态的方法。说明该类应该提供静态的返回该类对象的方法。
		 * 而且只有一个,说明Runtime类使用了单例设计模式。
		 */
		Runtime r = Runtime.getRuntime();
		Process p = r.exec("notepad.exe");
		Thread.sleep(5000);
		p.destroy();
	}
}
3、Math类      其中的方法全部都是静态的。
4、Date类
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateDemo {
	public static void main(String[] args) throws ParseException {
		methodDemo_1();
		methodDemo_2();
		methodDemo_3();
	}
	/**
	 * 将日期格式的字符串-->日期对象。
	 * 	使用的是DateFormat类中的parse()方法。  
	 */
	public  static void methodDemo_3() throws ParseException {
		String str_date = "2012年4月19日";
		str_date = "2011---8---17";
			
		DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
		dateFormat = new SimpleDateFormat("yyyy---MM---dd");
		Date date = dateFormat.parse(str_date);
		System.out.println(date);
	}
	/**
	 * 对日期对象进行格式化。
	 * 将日期对象-->日期格式的字符串。
	 * 使用的是DateFormat类中的format方法。
	 */
	public static void methodDemo_2() {
		Date date = new Date();
		//获取日期格式对象。具体着默认的风格。 FULL LONG等可以指定风格。
		DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.LONG);
		dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
		//System.out.println(dateFormat);
		
		//如果风格是自定义的如何解决呢?
		dateFormat = new SimpleDateFormat("yyyy--MM--dd");
		String str_date = dateFormat.format(date);
		System.out.println(str_date);
	}
	/**
	 * 日期对象和毫秒值之间的转换。
	 * 
	 * 毫秒值-->日期对象 : 
	 * 	1,通过Date对象的构造方法  new Date(timeMillis);
	 *  2,还可以通过setTime设置。 
	 *  因为可以通过Date对象的方法对该日期中的各个字段(年月日等)进行操作。
	 *  
	 * 日期对象-->毫秒值:
	 * 	2,getTime方法。
	 * 因为可以通过具体的数值进行运算。 
	 */
	public static void methodDemo_1() {
		long time = System.currentTimeMillis();
		//System.out.println(time);//1335671230671
		
		Date date = new Date();//将当前日期和时间封装成Date对象。
		System.out.println(date);//Sun Apr 29 11:48:02 CST 2012

		Date date2 = new Date(1335664696656l);//将指定毫秒值封装成Date对象。
		System.out.println(date2);
	}
}
//output:
//Mon Jan 29 17:48:56 CST 2018
//Sun Apr 29 09:58:16 CST 2012
//2018--01--29
//Wed Aug 17 00:00:00 CST 2011
5、Calendar类  
因为Date的接口不易于实现国际化,从jdk1.1开始,使用Calendar类来
实现日期和时间字段之间的转换,使用DateFormat类来格式化和解析日期字符串。
import java.util.Calendar;
public class CalendarDemo {
	public static void main(String[] args) {
		Calendar c = Calendar.getInstance();
		int year = 2012;
		showDays(year);
	}
	public static void showDays(int year) {
		Calendar c = Calendar.getInstance();
		c.set(year, 2, 1);
		c.add(Calendar.DAY_OF_MONTH, -1);
		showDate(c);
	}
	public static void showDate(Calendar c) {
		int year = c.get(Calendar.YEAR);
		int month = c.get(Calendar.MONTH)+1;
		int day = c.get(Calendar.DAY_OF_MONTH);
		int week = c.get(Calendar.DAY_OF_WEEK);
		System.out.println(year+"年"+month+"月"+day+"日"+getWeek(week));
	}
	public static String getWeek(int i) {
		String[] weeks = {"","星期日","星期一","星期二","星期三","星期四","星期五","星期六"};
		return weeks[i];
	}
} //output:2012年2月29日星期三
6、IO流
IO流用来处理设备之间的数据输出
Java对数据的操作是通过流的方式,用于操作流的对象都在IO包中
流按操作数据分为两种:字节流与字符流
7、字符流的由来:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,
获取对应的文字,然后对文字进行操作。简单说:字节流+编码表
8、字节流的抽象基类 InputStream、OutputStream
   字符流的抽象基类 Reader、Writer
   字符流和字节流的子类以基类作为名称后半部分,前半部分就是该类的功能
9、要操作文字数据,优先考虑字符流。要将数据从内存写到硬盘上,要使用字符流中的输出流。
   FileWriter
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
	private static final String LINE_SEPARATOR = System.getProperty("line.separator");
	public static void main(String[] args) throws IOException{
		//如果文件不存在,则会自动创建。如果文件存在,则会被覆盖。
        //如果构造函数中加入true,可以实现对文件进行续写!
    	FileWriter fw = new FileWriter("demo.txt", true);
	    fw.write("test filewriter"+LINE_SEPARATOR+"test change line");
	    //fw.flush();  //进行刷新,将数据直接写到目的地中。
		fw.close();  //在关闭前会先调用flush将缓冲区数据存入到目的地
		//fw.write("Write after closed");// java.io.IOException: Stream closed
	}
}
10、流对象在try的外面创建引用变量,在try的里面初始化
import java.io.FileWriter;
import java.io.IOException;
public class IOExceptionDemo {
	private static final String LINE_SEPARATOR = System.getProperty("line.separator");
	public static void main(String[] args) {
		FileWriter fw = null;
		try {
			fw = new FileWriter("k:\\demo.txt");
			fw.write("test filewriter"+LINE_SEPARATOR+"test change line");
		} catch (IOException e) {
			System.out.println(e.toString());
		} finally {
			if (fw != null)
				try {
					fw.close();
				} catch (IOException e) {
					// code....
					throw new RuntimeException("关闭失败");
				}
		}
	}
}
11、Reader FileReader  read和read(char[])
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("demo.txt");
		int ch = 0;
		while((ch=fr.read())!=-1){
			System.out.println((char)ch);
		}
		fr.close();
	}
}
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo2 {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("demo.txt");
		char[] buf = new char[1024];
		int len = 0;
		while((len=fr.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
		fr.close();
    }
}





day21
1、复制文件
	public static void main(String[] args) throws IOException {
		//1,读取一个已有的文本文件,使用字符读取流和文件相关联。
		FileReader fr = new FileReader("IO流_2.txt");
		//2,创建一个目的,用于存储读到数据。
		FileWriter fw = new FileWriter("copytext_1.txt");
		//3,频繁的读写操作。
		int ch = 0;
		while((ch=fr.read())!=-1){
			fw.write(ch);
		}
		//4,关闭流资源。 
		fw.close();
		fr.close();
	}
	
	public static void main(String[] args) {
		FileReader fr = null;
		FileWriter fw = null;
		try {
			fr = new FileReader("IO流_2.txt");
			fw = new FileWriter("copytest_2.txt");
			//创建一个临时容器,用于缓存读取到的字符。
			char[] buf = new char[BUFFER_SIZE];//这就是缓冲区。 
			//定义一个变量记录读取到的字符数,(其实就是往数组里装的字符个数 )
			int len = 0;
			while((len=fr.read(buf))!=-1){
				fw.write(buf, 0, len);
			}
		} catch (Exception e) {
			throw new RuntimeException("读写失败");
		}finally{
			if(fw!=null)
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			if(fr!=null)
				try {
					fr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}
2、字符流的缓冲区
   缓冲区的出现提高了对数据的读写效率。对应类BufferWriter、BufferReader
   缓冲区要结合流才可以使用,在流的基础上对流的功能进行了增强。
//BufferWriter   
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
	private static final String LINE_SEPARATOR = System.getProperty("line.separator");
	public static void main(String[] args) throws IOException {
		FileWriter fw = new FileWriter("buf.txt");
		//为了提高写入的效率。使用了字符流的缓冲区。
		//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
		BufferedWriter bufw = new BufferedWriter(fw);
		//使用缓冲区的写入方法将数据先写入到缓冲区中。
//		bufw.write("abcdefq"+LINE_SEPARATOR+"hahahha");
//		bufw.write("xixiixii");
//		bufw.newLine();
//		bufw.write("heheheheh");
		for(int x=1; x<=4; x++){
			bufw.write("abcdef"+x);
			bufw.newLine();
			bufw.flush();
		}
		//使用缓冲区的刷新方法将数据刷目的地中。
//		bufw.flush();
		//关闭缓冲区。其实关闭的就是被缓冲的流对象。
		bufw.close();
//		fw.close();
	}
}
//BufferReader
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("buf.txt");
		BufferedReader bufr = new BufferedReader(fr);
		String line = null;
		while((line=bufr.readLine())!=null){   //readline读一行,文本文件特有
			System.out.println(line);
		}
		bufr.close();	
	}
}
3、装饰设计模式:对一组对象的功能进行增强时,可以使用该模式。
public class PersonDemo {
	public static void main(String[] args) {
		Person p = new Person();
		p.chifan();
		NewPerson p1 = new NewPerson(p);
		p1.chifan();
		NewPerson2 p2 = new NewPerson2();
		p2.chifan();
	}
}
class Person{
	void chifan(){
		System.out.println("吃饭");
	}
}
//装饰,这个类的出现是为了增强Person而出现的。
class NewPerson{
	private Person p ;
	NewPerson(Person p){
		this.p = p;
	}
	public void chifan(){
		System.out.println("开胃酒");
		p.chifan();
		System.out.println("甜点");
	}
}
//继承的方式
class NewPerson2 extends Person{
	public void chifan(){
		System.out.println("开胃酒");
		super.chifan();
		System.out.println("甜点");
	}
}
4、装饰设计模式和继承(都进行功能的扩展)的区别
继承会导致继承体系越来越臃肿。装饰比继承更为灵活。
装饰类和被装饰类都必须属于同一个接口或者父类。装饰类也要继承,直接继承父类。
5、LineNumberReader  设置和读取行号
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderDemo {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("IO流_2.txt");
		LineNumberReader lnr = new LineNumberReader(fr);
		String line = null;
		lnr.setLineNumber(100);    //设置起始行号
		while((line=lnr.readLine())!=null){
			System.out.println(lnr.getLineNumber()+":"+line);
		}
		lnr.close();
	}
}
6、字节流
基本操作与字符流相同,但它不仅可以操作字符,还可以操作其他类型文件。
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamDemo {
	public static void main(String[] args) throws IOException {
		demo_read();
	}
	public static void demo_read() throws IOException {
		//1,创建一个读取流对象。和指定文件关联。
		FileInputStream fis = new FileInputStream("bytedemo.txt");
		
		//available()慎用,如果关联了大文件,new的数组非常大
		System.out.println(fis.available());
		byte[] buf = new byte[fis.available()];		
		fis.read(buf);
		System.out.println(new String(buf));
		
		//使用这种读取数据的方式
		byte[] buf = new byte[1024];		
		int len = 0;
		while((len=fis.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
//		int ch = 0;
//		while((ch=fis.read())!=-1){
//			System.out.println((char)ch);
//		}
		//一次读取一个字节。
//		int ch = fis.read();		
//		System.out.println(ch);
		
		fis.close();
	}
	public static void demo_write() throws IOException {
		//1,创建字节输出流对象。用于操作文件.
		FileOutputStream fos = new FileOutputStream("bytedemo.txt");
		//2,写数据。直接写入到了目的地中。 
		fos.write("abcdefg".getBytes());
//		fos.flush();
		fos.close();//关闭资源动作要完成。 
	}
}
7、copy一个MP3文件
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMp3Test {
	public static void main(String[] args) throws IOException {
		copy_4();
	}
//	千万不要用,效率没有!
	public static void copy_4() throws IOException {
		FileInputStream fis = new FileInputStream("c:\\0.mp3");		
		FileOutputStream fos = new FileOutputStream("c:\\4.mp3");
		int ch = 0;
		while((ch =fis.read())!=-1){
			fos.write(ch);
		}
		fos.close();
		fis.close();
	}
	//不建议。 
	public static void copy_3() throws IOException {
		FileInputStream fis = new FileInputStream("c:\\0.mp3");		
		FileOutputStream fos = new FileOutputStream("c:\\3.mp3");
		byte[] buf = new byte[fis.available()];
		fis.read(buf);
		fos.write(buf);
		fos.close();
		fis.close();
	}
	public static void copy_2() throws IOException {
		FileInputStream fis = new FileInputStream("c:\\0.mp3");	
		BufferedInputStream bufis = new BufferedInputStream(fis);
		FileOutputStream fos = new FileOutputStream("c:\\2.mp3");
		BufferedOutputStream bufos = new BufferedOutputStream(fos);
		int ch = 0;
		while((ch=bufis.read())!=-1){
			bufos.write(ch);
		}
		bufos.close();
		bufis.close();
	}
	public static void copy_1() throws IOException {
		FileInputStream fis = new FileInputStream("c:\\0.mp3");		
		FileOutputStream fos = new FileOutputStream("c:\\1.mp3");
		byte[] buf = new byte[1024];
		int len = 0;
		while((len=fis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
		fis.close();
	}
}





day22
1、读取键盘输入
public static void readKey2() throws IOException {
	/*
	 * 获取用户键盘录入的数据,
	 * 并将数据变成大写显示在控制台上,
	 * 如果用户输入的是over,结束键盘录入。
	 * 
	 * 思路:
	 * 1,因为键盘录入只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串。
	 * 2,那就需要一个容器。StringBuilder.
	 * 3,在用户回车之前将录入的数据变成字符串判断即可。 
	 */
	//1,创建容器。
	StringBuilder sb = new StringBuilder();
	//2,获取键盘读取流。		
	InputStream in = System.in;
	//3,定义变量记录读取到的字节,并循环获取。 		
	int ch = 0;
	while((ch=in.read())!=-1){
		//在存储之前需要判断是否是换行标记 ,因为换行标记不存储。 
		if(ch=='\r')
			continue;
		if(ch=='\n'){
			String temp = sb.toString();
			if("over".equals(temp))
				break;
			System.out.println(temp.toUpperCase());
			sb.delete(0, sb.length());
		}
		else
		//将读取到的字节存储到StringBuilder中。
		sb.append((char)ch);
	}
}
2、转换流
InputStreamReader  字节流通向字符流的桥梁,将字节解码成字符
public static void readKey3() throws IOException {
	//1、创建容器
	StringBuffer sb = new StringBuffer();
	//2、获取键盘读取流
	InputStream in = System.in;
	//将字节流转换为字符流
	InputStreamReader isr = new InputStreamReader(in);
	
	BufferedReader bufr = new BufferedReader(isr);
	String line = null;
	while((line = bufr.readLine()) != null){
		if("over".equals(line))
			break;
			System.out.println(line.toUpperCase());
	}
}
OutputStreamWriter 字符流通向字节流的桥梁,将写入流中的字符编码成字节
public static void readKey3() throws IOException {
	//1、创建容器
	StringBuffer sb = new StringBuffer();
	//2、获取键盘读取流
	InputStream in = System.in;
	//3、将字节流转换为字符流
	InputStreamReader isr = new InputStreamReader(in);
	BufferedReader bufr = new BufferedReader(isr);

	OutputStream out = System.out;
	OutputStreamWriter osw = new OutputStreamWriter(out);
	BufferedWriter  bufw = new BufferedWriter(osw);
	
	String line = null;
	while((line = bufr.readLine()) != null){
		if("over".equals(line))
			break;
			//System.out.println(line.toUpperCase());
		bufw.write(line.toUpperCase());
		bufw.newLine();
		bufw.flush();
	}
}
简化,一旦有键盘录入
	public static void main(String[] args) throws IOException {
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		String line = null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
	}
}
a,需求:将键盘录入的数据写入到一个文件中。 
b,需求:将一个文本文件内容显示在控制台上。
c,需求:将一个文件文件中的内容复制到的另一个文件中。  
该三种需求只需要修改简化代码中的源和目的
3、流的操作规律
转换流:
InputStreamReader:字节流通向字符流的桥梁,将字节解码成字符
OutputStreamWriter:字符流通向字节流的桥梁,将写入流中的字符编码成字节
a、明确源和目的
   源:InputStream Reader
   目的:OutputStream Writer 
b、明确数据是否是纯文本数据
   源是否纯文本 是:Reader  否:InputStream
   目的是否纯文本 是:Writer  否:OutputStream
c、明确具体设备
   源设备:硬盘:File   键盘:System.in   内存:数组   网路:Socket流
   目的设备:硬盘:File   控制台:System.out   内存:数组   网路:Socket流
d、是否需要其他额外功能:
   是否需要高效(缓冲区)是,就加buffer
4、将一个中文字符串数据按照指定的编码表写入到一个文本文件中.
a、目的。OutputStream,Writer b、是纯文本,Writer。c、设备:硬盘File 
FileWriter fw = new FileWriter("a.txt");
fw.write("你好"); 
注意:既然需求中已经明确了指定编码表的动作。
那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表。 只能使用其父类。OutputStreamWriter.
OutputStreamWriter接收一个字节输出流对象,既然是操作文件,那么该对象应该是FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName);
需要高效吗?
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName));
5、什么时候使用转换流?
a、源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁。 提高对文本操作的便捷。 
b、一旦操作文本涉及到具体的指定编码表时,必须使用转换流 。
6、File类
用来将文件或者文件夹封装成对象,方便对文件及文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数。 
public class FileDemo {
	public static void main(String[] args) {

		constructorDemo();	
	}
	public static void constructorDemo() {
		//可以将一个已存在的,或者不存在的文件或者目录封装成file对象。
		File f1 = new File("c:\\a.txt");
		File f2 = new File("c:\\","a.txt");
		File f = new File("c:\\");
		File f3 = new File(f,"a.txt");
		File f4 = new File("c:"+File.separator+"abc"+File.separator+"a.txt");
		System.out.println(f4);
	}
}
7、常用方法
a、获取:名称、路径、大小、修改时间
String getName()
String getAbsolutePath();//绝对路径
Stirng getPath()
long length()
long lastModified()
b、创建与删除
boolean createNewFile()		
boolean delete()
boolean mkdir()
boolean mkdirs()  //创建多级目录
c、判断
boolean exists()  //判断是否存在	
boolean isFile())
boolean isDirectory()
d、重命名
boolean renameTo(File dest)
e、系统根目录和容量获取
long getFreeSpace()
long getTotalSpace()
long getUsableSpace()  //字节数
static File[] listRoots()
f、获取目录内容
String[] list() //当目录不存在或无访问权限时抛出异常
8、过滤器 String[] list(FilenameFilter filter) 
import java.io.File;
import java.io.FilenameFilter;
public class SuffixFilter implements FilenameFilter {
	private String suffix ;
	public SuffixFilter(String suffix) {
		super();
		this.suffix = suffix;
	}
	@Override
	public boolean accept(File dir, String name) {
		return name.endsWith(suffix);
	}
}
class FileDemo
public static void listDemo_2() {
	File dir = new File("c:\\");
	String[] names = dir.list(new SuffixFilter(".txt"));
	for(String name : names){
		System.out.println(name);
	}
}





day23
1、深度遍历文件夹
import java.io.File;
public class FileTest {
	public static void main(String[] args) {
		File dir = new File("e:\\demodir");
		listAll(dir,0);
	}
	public static void listAll(File dir,int level) {
		System.out.println(getSpace(level)+dir.getName());
		//获取指定目录下当前的所有文件夹或者文件对象
		level++;
		File[] files = dir.listFiles();
		for(int x=0; x<files.length; x++){
			
			if(files[x].isDirectory()){
				listAll(files[x],level);
			}
			else
				System.out.println(getSpace(level)+files[x].getName());
		}	
	}
	private static String getSpace(int level) {
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		for(int x=0; x<level; x++){
			sb.insert(0,"|  ");
		}
		return sb.toString();
	}
}
2、删除文件先删除最里面文件
import java.io.File;
/*
 * 删除一个带内容的目录。 
 * 原理:必须从最里面往外删。需要进行深度遍历。
 */
public class RemoveDirTest {
	public static void main(String[] args) {
		File dir  = new File("e:\\demodir");
		//dir.delete();
		removeDir(dir);
	}
	public static void removeDir(File dir) {
		File[] files = dir.listFiles();
		for(File file : files){
			if(file.isDirectory()){
				removeDir(file);
			}else{
				System.out.println(file+":"+file.delete());
			}
		}
		System.out.println(dir+":"+dir.delete());
	}
}
3、Properties
表示一个持久的属性集,Properties可保存在流中或从流中加载。
属性列表的每个键及其对应值都是一个字符串。
通常该集合用于操作以键值对形式存在的配置文件。
4、Properties集合的存和取
public static void propertiesDemo(){
	//创建一个Properties集合。
	Properties prop  = new Properties();
	
	//存储元素。 
	prop.setProperty("zhangsan","30");
	prop.setProperty("lisi","31");
	prop.setProperty("wangwu","36");
	//修改元素。 
	prop.setProperty("wangwu","26");
	//取出所有元素。
	Set<String> names = prop.stringPropertyNames();
	for(String name : names){
		String value = prop.getProperty(name);
		System.out.println(name+":"+value);
	}
}
5、Properties类的list方法,将属性列表输出到指定的输出流
public static void methodDemo_2(){
	Properties prop  = new Properties();
	//存储元素。 
	prop.setProperty("zhangsan","30");
	prop.setProperty("lisi","31");
	prop = System.getProperties();
	prop.list(System.out);
}
6、Properties类的store方法
将Properties表中的属性列表(键和元素对)写入输出流。
public static void methodDemo_3() throws IOException {
	Properties prop  = new Properties();
	//存储元素。 
	prop.setProperty("zhangsan","30");
	prop.setProperty("lisi","31");
	//想要将这些集合中的字符串键值信息持久化存储到文件中。
	//需要关联输出流。
	FileOutputStream fos = new FileOutputStream("info.txt");
	//将集合中数据存储到文件中,使用store方法。
	prop.store(fos, "info");
	fos.close();
}
7、Properties类的load方法
从输入流中读取属性列表(键和元素对)。
public static void methodDemo_4() throws IOException {	
	Properties prop  = new Properties();
	//集合中的数据来自于一个文件。 
	//注意;必须要保证该文件中的数据是键值对。需要使用到读取流。 
	FileInputStream fis = new FileInputStream("info.txt");
	//使用load方法。 
	prop.load(fis);
	prop.list(System.out);
} 
//模拟一下load方法。
public static void myLoad() throws IOException{
	Properties prop  = new Properties();
	BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
	String line = null;
	while((line=bufr.readLine())!=null){
		if(line.startsWith("#"))
			continue;
		String[] arr = line.split("=");	
		//System.out.println(arr[0]+"::"+arr[1]);
		prop.setProperty(arr[0], arr[1]);
	}
	prop.list(System.out);
	bufr.close();
}
8、对已有的配置文件中的信息进行修改。 
   注意:FileReader和FileWriter实例化的位置
/*
 * 读取这个文件。
 * 并将这个文件中的键值数据存储到集合中。
 * 在通过集合对数据进行修改。
 * 在通过流将修改后的数据存储到文件中。 
 */
public static void test() throws IOException{
	File file = new File("info.txt");
	if(!file.exists()){
		file.createNewFile();
	}
	FileReader fr = new FileReader(file);
	//创建集合存储配置信息。
	Properties prop = new Properties();
	//将流中信息存储到集合中。
	prop.load(fr);
	prop.setProperty("wangwu", "16");
	FileWriter fw = new FileWriter(file);
	prop.store(fw,"");
	fw.close();
	fr.close();
}
9、打印流
public class PrintStreamDemo {
public static void main(String[] args) throws IOException {
//PrintStream:
//1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。 
//2,它不抛IOException.
//构造函数,接收三种类型的值:1,字符串路径。2,File对象。3,字节输出流。
	PrintStream out = new PrintStream("print.txt");
//	int by = read();
//	write(by);
//	out.write(610);//只写最低8位,
//	out.print(97);//将97先变成字符保持原样将数据打印到目的地。 
	out.close();
}
pubic class PrintWriterDemo {
public static void main(String[] args) throws IOException {
//PrintWriter:字符打印流。
//构造函数参数:1,字符串路径。2,File对象。3,字节输出流。4,字符输出流。
	BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
	//PrintWriter(OutputStream out, boolean autoFlush) 
	//在调用 println、printf 或 format 的其中一个方法时将刷新输出缓冲区,不用调用flush
	PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);
	String line =  null;
	while((line=bufr.readLine())!=null){
		if("over".equals(line))
			break;
		out.println(line.toUpperCase());
		//out.flush(); 
	}
	out.close();
	bufr.close();
}
10、序列流
SequenceInputStream表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个
输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的
最后一个输入流的文件末尾为止。 
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
public class SequenceInputStreamDemo {
	public static void main(String[] args) throws IOException {
		/*
		 * 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。
		 */
		//Vector<FileInputStream> v = new Vector<FileInputStream>();		
		//v.add(new FileInputStream("1.txt"));
		//v.add(new FileInputStream("2.txt"));
		//v.add(new FileInputStream("3.txt"));
		//Enumeration<FileInputStream> en = v.elements();
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int x=1; x<=3; x++){
			al.add(new FileInputStream(x+".txt"));
		}
		Enumeration<FileInputStream> en = Collections.enumeration(al);
		/*
		final Iterator<FileInputStream> it = al.iterator();
		Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
			@Override
			public boolean hasMoreElements() {
				
				return it.hasNext();
			}
			@Override
			public FileInputStream nextElement() {
				
				return it.next();
			}
		};*/
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream("1234.txt");
		byte[] buf = new byte[1024];
		int len = 0;
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
}





day24
1、文件切割
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class SplitFileDemo {
	private static final int SIZE = 1024 * 1024;
	public static void main(String[] args) throws Exception {
		File file = new File("c:\\aa.mp3");
		splitFile_2(file);
	}
	private static void splitFile_2(File file) throws IOException {
		// 用读取流关联源文件。
		FileInputStream fis = new FileInputStream(file);
		// 定义一个1M的缓冲区。
		byte[] buf = new byte[SIZE];
		// 创建目的。
		FileOutputStream fos = null;
		int len = 0;
		int count = 1;
		/*
		 * 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并。
		 * 这个信息为了进行描述,使用键值对的方式。用到了properties对象
		 */
		Properties prop  = new Properties();
		File dir = new File("c:\\partfiles");
		if (!dir.exists())
			dir.mkdirs();
		while ((len = fis.read(buf)) != -1) {

			fos = new FileOutputStream(new File(dir, (count++) + ".part"));
			fos.write(buf, 0, len);
			fos.close();
		}
		//将被切割文件的信息保存到prop集合中。
		prop.setProperty("partcount", count+"");
		prop.setProperty("filename", file.getName());
		fos = new FileOutputStream(new File(dir,count+".properties"));
		//将prop集合中的数据存储到文件中。 
		prop.store(fos, "save file info");
		fos.close();
		fis.close();
	}
	public static void splitFile(File file) throws IOException {
		// 用读取流关联源文件。
		FileInputStream fis = new FileInputStream(file);
		// 定义一个1M的缓冲区。
		byte[] buf = new byte[SIZE];
		// 创建目的。
		FileOutputStream fos = null;
		int len = 0;
		int count = 1;
		File dir = new File("c:\\partfiles");
		if (!dir.exists())
			dir.mkdirs();
		while ((len = fis.read(buf)) != -1) {
			fos = new FileOutputStream(new File(dir, (count++) + ".part"));
			fos.write(buf, 0, len);
		}
		fos.close();
		fis.close();
	}
}
2、文件合并
import java.io.File;
import java.io.FilenameFilter;
public class SuffixFilter implements FilenameFilter {
	private String suffix;
	public SuffixFilter(String suffix) {
		super();
		this.suffix = suffix;
	}
	@Override
	public boolean accept(File dir, String name) {
		return name.endsWith(suffix);
	}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
public class MergeFile {
	public static void main(String[] args) throws IOException {
		File dir = new File("c:\\partfiles");
		mergeFile_2(dir);
	}
	public static void mergeFile_2(File dir) throws IOException {
		File[] files = dir.listFiles(new SuffixFilter(".properties"));
		if(files.length!=1)
			throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");
		//记录配置文件对象。
		File confile = files[0];
		//获取该文件中的信息================================================。
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream(confile);
		prop.load(fis);
		String filename = prop.getProperty("filename");		
		int count = Integer.parseInt(prop.getProperty("partcount"));
		//获取该目录下的所有碎片文件。 ==============================================
		File[] partFiles = dir.listFiles(new SuffixFilter(".part"));
		if(partFiles.length!=(count-1)){
			throw new RuntimeException(" 碎片文件不符合要求,个数不对!应该"+count+"个");
		}
		//将碎片文件和流对象关联 并存储到集合中。 
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int x=0; x<partFiles.length; x++){
			
			al.add(new FileInputStream(partFiles[x]));
		}
		//将多个流合并成一个序列流。 
		Enumeration<FileInputStream> en = Collections.enumeration(al);
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream(new File(dir,filename));
		byte[] buf = new byte[1024];
		int len = 0;
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
	public static void mergeFile(File dir) throws IOException{
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int x=1; x<=3 ;x++){
			al.add(new FileInputStream(new File(dir,x+".part")));
		}
		Enumeration<FileInputStream> en = Collections.enumeration(al);
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream(new File(dir,"1.bmp"));
		byte[] buf = new byte[1024];
		int len = 0;
		while((len=sis.read(buf))!=-1){
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
}
3、操作对象ObjectInputStream和ObjectOutputStream,序列化和反序列化
被操作的对象需要实现Serializable接口(标记接口)
import java.io.Serializable;
/*
 * Serializable:用于给被序列化的类加入ID号。
 * 用于判断类和对象是否是同一个版本。 
 */
public class Person implements Serializable/*标记接口*/ {
	/**
	 * transient:非静态数据不想被序列化可以使用这个关键字修饰。 
	 *静态数据不能被持久化,因为静态变量不在堆内存区
	 */
	private static final long serialVersionUID = 9527l;
	private transient String name;
	private static int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import cn.itcast.io.p2.bean.Person;
public class ObjectStreamDemo {
	public static void main(String[] args) throws IOException, ClassNotFoundException {		
		writeObj();
		readObj();
	}
	public static void readObj() throws IOException, ClassNotFoundException {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
		//对象的反序列化。 
		Person p = (Person)ois.readObject();
		System.out.println(p.getName()+":"+p.getAge());
		ois.close();
	}
	public static void writeObj() throws IOException, IOException {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
		//对象序列化。  被序列化的对象必须实现Serializable接口。 
		oos.writeObject(new Person("小强",30));
		oos.close();
	}
}
4、Serializable接口(标记接口)
序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和
接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致InvalidClassException。
可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、
最终 (final)long 型字段)显式声明其自己的 serialVersionUID。
5、RandomAccessFile
随机访问文件,自身具备读写的方法,通过skipBytes(int x),seek(int x)来达到随机访问。
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
	public static void main(String[] args) throws IOException {

		/*
		 * RandomAccessFile 不是io体系中的子类。
		 * 特点:
		 * 1,该对象即能读,又能写。
		 * 2,该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素,
		 * 3,可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置。
		 * 4,其实该对象就是将字节输入流和输出流进行了封装。 
		 * 5,该对象的源或者目的只能是文件。通过构造函数就可以看出。 
		 */
		writeFile();
		readFile();
		randomWrite();
	}
	public static void randomWrite() throws IOException{
		RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw");
		//往指定位置写入数据。
		raf.seek(3*8);
		raf.write("哈哈".getBytes());
		raf.writeInt(108);
		raf.close();
	}
	public static void readFile() throws IOException {
		RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "r");
		//通过seek设置指针的位置。
		raf.seek(1*8);//随机的读取。只要指定指针的位置即可。 
		byte[] buf = new byte[4];
		raf.read(buf);
		String name = new String(buf);
		int age = raf.readInt();
		System.out.println("name="+name);
		System.out.println("age="+age);
		System.out.println("pos:"+raf.getFilePointer());
		raf.close();
	}
	//使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄。
	public static void writeFile() throws IOException{
		/*
		 * 如果文件不存在,则创建,如果文件存在,不创建
		 */
		RandomAccessFile raf = new RandomAccessFile("ranacc.txt","rw");
		raf.write("张三".getBytes());
		raf.writeInt(97);
		raf.write("小强".getBytes());
		raf.writeInt(99);
		raf.close();
	}
}
6、管道流PipedStream
输入输出可以直接进行连接,通过结合线程使用。
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedStream {
	public static void main(String[] args) throws IOException {
		PipedInputStream input = new PipedInputStream();
		PipedOutputStream output = new PipedOutputStream();
		input.connect(output);
		new Thread(new Input(input)).start();
		new Thread(new Output(output)).start();
	}
}
class Input implements Runnable{
	private PipedInputStream in;
	Input(PipedInputStream in){
		this.in = in;
	}
	public void run(){
		try {
			byte[] buf = new byte[1024];
			int len = in.read(buf);
			String s = new String(buf,0,len);
			System.out.println("s="+s);
			in.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}
class Output implements Runnable{
	private PipedOutputStream out;
	Output(PipedOutputStream out){
		this.out = out;
	}
	public void run(){
		try {
			Thread.sleep(5000);
			out.write("hi,管道来了!".getBytes());
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}
7、DataInputStream、DataOutputStream  操作基本数据类型
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataSteamDemo {
	public static void main(String[] args) throws IOException {
		writeData();
		readData();
	}
	public static void readData() throws IOException {
		DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
		String str = dis.readUTF();
		System.out.println(str);
	}
	public static void writeData() throws IOException {
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
		dos.writeUTF("你好");
		dos.close();	
	}
}
8、ByteArrayInputStream、ByteArrayOutputStream 操作字节数组
关闭此流无效,其没有调用底层资源。此类方法在关闭流后仍可调用,不会抛出异常。
9、CharArrayReader与CharArrayWriter   操作字符数组
10、StringReader与StringWriter   操作字符串
11、编码表
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class EncodeDemo {
	public static void main(String[] args) throws IOException {
		/*
		 * 字符串 --> 字节数组:编码。
		 * 字节数组 --> 字符串:解码。
		 * 你好:GBK:  -60 -29 -70 -61
		 * 你好: utf-8: -28 -67 -96 -27 -91 -67 
		 * 如果你编错了,解不出来。
		 * 如果编对了,解错了,有可能有救。
		 */
		String str = "谢谢";
		byte[] buf = str.getBytes("gbk");
		String s1 = new String(buf,"UTF-8");
		System.out.println("s1="+s1);
		byte[] buf2 = s1.getBytes("UTF-8");//获取源字节.
		printBytes(buf2);//-17 -65 -67 -17 -65 -67 -17 -65 -67 
					//-17 -65 -67 -17 -65 -67 -17 -65 -67 -17 -65 -67
					//-48 -69 -48 -69 
		String s2 = new String(buf2,"GBK");
		System.out.println("s2="+s2);	
		//encodeDemo(str);
	}
	public static void encodeDemo(String str)
			throws UnsupportedEncodingException {
		//编码;
		byte[] buf = str.getBytes("UTF-8");
		//解码:
		String s1 = new String(buf,"UTF-8");
		System.out.println("s1="+s1);
	}
	private static void printBytes(byte[] buf) {
		for(byte b : buf){
			System.out.print(b +" ");
		}
	}
}
12、截取字符串
public class Test {
	public static void main(String[] args) throws IOException {
		String str = "ab你好cd谢谢";
//		str = "ab琲琲cd琲琲";
//		int len = str.getBytes("gbk").length;		
//		for(int x=0; x<len; x++){
//			System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByByte(str, x+1));
//		}
		int len = str.getBytes("utf-8").length;		
		for(int x=0; x<len; x++){
			System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByU8Byte(str, x+1));
		}
//		String str = "琲";
//		byte[] buf = str.getBytes("gbk");
//		for(byte b : buf){
//			System.out.println(b);//-84  105 
//		}	
	}
	public static String cutStringByU8Byte(String str, int len) throws IOException {
		byte[] buf = str.getBytes("utf-8");
		int count = 0;
		for(int x=len-1; x>=0; x--){
			if(buf[x]<0)
				count++;
			else
				break;
		}
		if(count%3==0)
			return new String(buf,0,len,"utf-8");
		else if(count%3==1)
			return new String(buf,0,len-1,"utf-8");
		else 
			return new String(buf,0,len-2,"utf-8");
	}
	public static String cutStringByByte(String str,int len) throws IOException{
		byte[] buf = str.getBytes("gbk");
		int count = 0;
		for(int x=len-1; x>=0; x--){
			if(buf[x]<0)
				count++;
			else
				break;
		}
		if(count%2==0)
			return new String(buf,0,len,"gbk");
		else
			return new String(buf,0,len-1,"gbk");
	}
}





day25
1、GUI 图形用户接口
java为GUI提供的对象都存在java.awt和java.swing中
Awt Abstract Windows ToolKit,调用本地系统方法实现功能,属于重量级控件
swing 在Awt基础上用java实现,受系统影响小,属轻量级控件
2、CLI 命令行用户接口
3、Container:为容器,是一个特殊的组件,该组件可以通过add方法添加其他组件进来。
4、布局管理器
5、事件监听机制 
事件源(组件,承载事件的载体) 事件(Event) 监听器(Listener) 事件处理(引发事件后处理方式)
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class FrameDemo {
	public static void main(String[] args) {
		Frame f = new Frame("my frame");
		f.setBounds(400, 200, 500, 400);		
		f.setLayout(new FlowLayout());//设置流式布局
		Button but  = new Button("一个按钮");
		f.add(but);//将按钮添加到窗体中。 
		f.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {		
				//System.out.println("closing......."+e);
				System.exit(0);
			}	
		});
		//在按钮上加上一个监听。
		but.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				//System.out.println("button run .....");
				System.exit(0);
			}
		});
		f.setVisible(true);
		System.out.println("over");
	}
}
6、鼠标事件和键盘事件
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MouseAndKeyDemo {
	private Frame f;
	private TextField tf;
	private Button but;
	
	public MouseAndKeyDemo() {
		init();
	}
	private void init() {
		f = new Frame("演示鼠标和键盘监听");
		f.setBounds(400,200,500,400);
		f.setLayout(new FlowLayout());
		tf = new TextField(35);
		but = new Button("一个按钮");
		f.add(tf);
		f.add(but);
		myEvent();
		f.setVisible(true);
	}
	private void myEvent() {
		//给文本框添加键盘监听。
		tf.addKeyListener(new KeyAdapter() {
			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println("KeyEvent.getKeyText(e.getKeyCode())+":"+e.getKeyCode());
				int code = e.getKeyCode();
				if(!(code>=KeyEvent.VK_0 && code<=KeyEvent.VK_9)){
					System.out.println("必须是数字");
					e.consume();  //取消
				}
				if(e.isControlDown() && e.getKeyCode()==KeyEvent.VK_ENTER){
					System.out.println("enter run ...");
				}
			}
		});
		
		f.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {	
				System.exit(0);
			}
		});
		
		//按钮上添加一个动作监听事件,会在鼠标点击后运行
		but.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.out.println("action run.....");
			}
		});
		//在按钮上添加一个鼠标监听
		but.addMouseListener(new MouseAdapter() {
			private int count = 1;
			@Override
			public void mouseEntered(MouseEvent e) {
				//tf.setText("mouse enter..."+count++);
			}
			@Override
			public void mouseClicked(MouseEvent e) {
				if(e.getClickCount()==2)
				tf.setText("mouse double click..."+count++);
			}	
		});
	}
	public static void main(String[] args) {
		new MouseAndKeyDemo();
	}
}
7、Swing与装插件
 
 
 
 
 
day26
1、网络模型:
osi tcp/ip
2、网络通信要素 IP 端口号 通信协议
3、物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
4、UDP 将数据及源和目的封装成数据包,不需要建立连接,每个数据包限制在64K,不可靠但速度快
5、TCP 建立连接,形成数据传输的通道,进行大数据量传输,三次握手建立连接,可靠,效率低
6、java网络相关java.net包
7、InetAddress类  Inet4Address Inet6Address
import java.net.InetAddress;
import java.net.UnknownHostException;
public class IPDemo {
public class IPDemo {
	public static void main(String[] args) throws UnknownHostException{
		InetAddress ip = InetAddress.getLocalHost();
		System.out.print(ip.getHostAddress()+"  ");
		System.out.print(ip.getHostName()+"  ");
		ip = InetAddress.getByName("192.168.1.102");
		System.out.print(ip.getHostAddress()+"  ");
		System.out.print(ip.getHostName());
	}
}   //output:192.168.56.1  DESKTOP-D4462PN  192.168.1.102  21OQ5ANS6ISUPVL
8、有的主机对应多个IP地址
static InetAddress[] getAllByName(String host) 
在给定主机名的情况下,根据系统上配置的名称服务返回其IP地址所组成的数组。 
9、域名解析  无IP无访问
先查找system32目录下的hosts文件,再查找DNS服务器。
10、Socket就是为网络服务提供的一种机制,数据在两个Socket之间通过IO传输。
11、DatagramSocket 用来发送和接收数据包的套接字。
12、UDP发送、接收
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class UDPSendDemo {
	public static void main(String[] args) throws IOException {
		System.out.println("发送端启动......");
		/*
		 * 创建UDP传输的发送端。
		 * 1,建立udp的socket服务。
		 * 2,将要发送的数据封装到数据包中。 
		 * 3,通过udp的socket服务将数据包发送出去。
		 * 4,关闭socket服务。
		 */
		//1,udpsocket服务。使用DatagramSocket对象。
		DatagramSocket ds = new DatagramSocket(8888);
		//2,将要发送的数据封装到数据包中。
		String str = "udp传输演示:哥们来了!";
		//使用DatagramPacket将数据封装到的该对象包中。
		byte[] buf = str.getBytes();
		DatagramPacket dp = 
				new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.100"),10000);
		//3,通过udp的socket服务将数据包发送出去。使用send方法。
		ds.send(dp);
		//4,关闭资源。
		ds.close();
	}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class UDPReceDemo {
	public static void main(String[] args) throws IOException {
		System.out.println("接收端启动......");
		/*
		 * 1,建立udp socket服务,因为是要接收数据,必须要明确一个端口号。
		 * 2,创建数据包,用于存储接收到的数据。方便用数据包对象的方法解析这些数据.
		 * 3,使用socket服务的receive方法将接收的数据存储到数据包中。
		 * 4,通过数据包的方法解析数据包中的数据。
		 * 5,关闭资源 
		 */
		//1,建立udp socket服务。
		DatagramSocket ds = new DatagramSocket(10000);
		//2,创建数据包。
		byte[] buf = new byte[1024];
		DatagramPacket dp = new DatagramPacket(buf,buf.length);
		//3,使用接收方法将数据存储到数据包中。
		ds.receive(dp);//阻塞式的。
		//4,通过数据包对象的方法,解析其中的数据,比如,地址,端口,数据内容。
		String ip = dp.getAddress().getHostAddress();
		int port = dp.getPort();
		String text = new String(dp.getData(),0,dp.getLength());
		System.out.println(ip+":"+port+":"+text);
		//5,关闭资源。
		ds.close();	
	}
}
13、TCP Socket客户端套接字  ServerSocket服务器套接字
14、TCP发送、接收
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
	public static void main(String[] args) throws IOException {
		//服务端接收客户端发送过来的数据,并打印在控制台上。 
		/*
		 * 建立tcp服务端的思路:
		 * 1,创建服务端socket服务。通过ServerSocket对象。
		 * 2,服务端必须对外提供一个端口,否则客户端无法连接。
		 * 3,获取连接过来的客户端对象。
		 * 4,通过客户端对象获取socket流读取客户端发来的数据并打印在控制台上。
		 * 5,关闭资源。关客户端,关服务端。 
		 */
		//1创建服务端对象。
		ServerSocket ss = new ServerSocket(10002);
		//2,获取连接过来的客户端对象。
		Socket s = ss.accept();//阻塞式.
		String ip = s.getInetAddress().getHostAddress();
		//3,通过socket对象获取输入流,要读取客户端发来的数据
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		String text = new String(buf,0,len);
		System.out.println(ip+":"+text);		
		s.close();
		ss.close();	
	}
}
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//客户端发数据到服务端
		/*
		 * Tcp传输,客户端建立的过程。
		 * 1,创建tcp客户端socket服务。使用的是Socket对象。
		 * 		建议该对象一创建就明确目的地。要连接的主机。 
		 * 2,如果连接建立成功,说明数据传输通道已建立。
		 * 		该通道就是socket流 ,是底层建立好的。 既然是流,说明这里既有输入,又有输出。
		 * 		想要输入或者输出流对象,可以找Socket来获取。 
		 * 		可以通过getOutputStream(),和getInputStream()来获取两个字节流。
		 * 3,使用输出流,将数据写出。 
		 * 4,关闭资源。 
		 */
		//创建客户端socket服务。
		Socket socket = new Socket("192.168.1.100",10002);
		//获取socket流中的输出流。 
		OutputStream out = socket.getOutputStream();
		//使用输出流将指定的数据写出去。
		out.write("tcp演示:哥们又来了!".getBytes());
		//关闭资源。
		socket.close();
	}
}
15、常见问题 缺少结束标记、阻塞式方法 shutdownOutput();





day27
1、服务端多线程
2、常用客户端(IE浏览器)和服务端(Tomcat)
3、客户端和服务端原理
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class MyBrowser {
	public static void main(String[] args) throws UnknownHostException, IOException {
		Socket s = new Socket("192.168.1.100",8080);

		//模拟浏览器,给tomcat服务端发送符合http协议的请求消息。
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		out.println("GET /myweb/1.html HTTP/1.1");
		out.println("Accept: */*");
		out.println("Host: 192.168.1.100:8080");
		out.println("Connection: close");
		out.println();
		
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		String str =new String(buf,0,len);
		System.out.println(str);
		s.close();
		//http://192.168.1.100:8080/myweb/1.html
	}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class MyTomcat {
	public static void main(String[] args) throws IOException {
		ServerSocket ss = new ServerSocket(9090);
		Socket s = ss.accept();
		System.out.println(s.getInetAddress().getHostAddress()+".....connected");
		InputStream in = s.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		String text = new String(buf,0,len);
		System.out.println(text);
		
		//给客户端一个反馈信息。
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		out.println("<font color='red' size='7'>欢迎光临</font>");
		s.close();
		ss.close();
	}
}
3、URL统一资源定位符 URI统一资源标识符
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class URLDemo {
	public static void main(String[] args) throws IOException {
		String str_url = "http://192.168.1.100:8080/myweb/1.html";
		URL url = new URL(str_url);
		
		//System.out.println("getProtocol:"+url.getProtocol());
		//System.out.println("getHost:"+url.getHost());
		//System.out.println("getPort:"+url.getPort());
		//System.out.println("getFile:"+url.getFile());
		//System.out.println("getPath:"+url.getPath());
		//System.out.println("getQuery:"+url.getQuery());
		
//InputStream in = url.openStream();(url.openConnection()和conn.getInputStream()组合)
		
		//获取url对象的Url连接器对象。
		//将连接封装成了对象:java中内置的可以解析的具体协议的对象+socket.
		URLConnection conn = url.openConnection();
		//String value = conn.getHeaderField("Content-Type");
		//System.out.println(value);
//output:text/htmml
		//System.out.println(conn);
//output:sun.net.www.protocol.http.HttpURLConnection:http://192.168.1.100:8080/myweb/1.html
		InputStream in = conn.getInputStream();
		byte[] buf = new byte[1024];
		int len = in.read(buf);
		String text = new String(buf,0,len);
		System.out.println(text);
		in.close();	
	}
}





day28
1、正则表达式:正则表达式用于操作字符串数据
正则表达式用于操作字符串数据,通过一些特定符号来体现。
2、匹配
使用String类中的matches方法
长度5~15. 只能是数字, 0不能开头  String regex = "[1-9][0-9]{4,14}";//正则表达式。
public static void functionDemo_1(){
	//匹配手机号码是否正确。 
	String tel = "15800001111";
	String regex = "1[358]\\d{9}";  
    String regex = "1[358][0-9]{9}"; 	
	boolean b = tel.matches(regex);
	System.out.println(tel+":"+b);
}
3、切割
使用String类中的split方法
组:((A)(B(C))) 
public static void functionDemo_2(){
	String str = "zhangsanttttxiaoqiangmmmmmmzhaoliu";
	String[] names = str.split("(.)\\1+");//str.split("\\.");
	for(String name : names){
		System.out.println(name);
	}	
}
4、替换
使用String类中的replaceAll方法
public static void functionDemo_3() {
	String str = "zhangsanttttxiaoqiangmmmmmmzhaoliu";
	str = str.replaceAll("(.)\\1+", "$1");
	System.out.println(str);	
	String tel = "15800001111";//158****1111;	
	tel = tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");	
	System.out.println(tel);
}
5、获取 
public  static void functionDemo_4() {
	String str = "da jia hao,ming tian bu fang jia!";
	String regex = "\\b[a-z]{3}\\b";
	//1,将正则封装成对象。
	Pattern p = Pattern.compile(regex);
	//2, 通过正则对象获取匹配器对象。 
	Matcher m = p.matcher(str);
	//使用Matcher对象的方法对字符串进行操作。
	//既然要获取三个字母组成的单词 
	//查找。 find();
	System.out.println(str);
	while(m.find()){
		System.out.println(m.group());//获取匹配的子序列
		System.out.println(m.start()+":"+m.end());
	}
}
6、反射
JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方
法的功能称为java语言的反射机制。 
动态获取类中信息,就是java反射 。可以理解为对类的解剖。
要想要对字节码文件进行解剖,必须要有字节码文件对象。
7、Tomcat提供了处理请求和应答的方式,因为具体的处理动作不同,所以对外提供了接口,
由开发者来具体实现请求和应答处理。
interface Servlet,例如下
web.xml
<servlet>
  <servlet-name>RegServlet</servlet-name>
  <servlet-class>cn.itcast.servlet.RegServlet</servlet-class>
</servlet>
AllUserServlet.xml
public class AllUserServlet extends HttpServlet{}
8、获取字节码对象的三种方式
a、Object类中的getClass()方法 必须明确具体的类和创建对象
b、类名.class 任何数据类型都具备一个静态的属性,class来获取其对应的class对象
c、class.forname(包名.类名) 只需知道类的字符串名称,更为扩展
9new和forname创建对象
public static void createNewObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException{	
	//早期:new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,
	//并创建该字节码文件对象,并接着创建该字节文件的对应的Person对象.
	cn.itcast.bean.Person p = new cn.itcast.bean.Person();
	//现在:
	String name = "cn.itcast.bean.Person";
	//找寻该名称类文件,并加载进内存,并产生Class对象。
	Class clazz = Class.forName(name);
	//如何产生该类的对象呢?
	Object obj  = clazz.newInstance();
}
public static void createNewObject_2() throws Exception {
	cn.itcast.bean.Person p = new cn.itcast.bean.Person("小强",39);
	/*
	 * 当获取指定名称对应类中的所体现的对象时,
	 * 而该对象初始化不使用空参数构造该怎么办呢?
	 * 既然是通过指定的构造 函数进行对象的初始化,
	 * 所以应该先获取到该构造函数。 通过字节码文件对象即可完成。
	 * 该方法是:getConstructor(paramterTypes);
	 */
	String name = "cn.itcast.bean.Person";
	//找寻该名称类文件,并加载进内存,并产生Class对象。
	Class clazz = Class.forName(name);
	//获取到了指定的构造函数对  象。
	Constructor constructor = clazz.getConstructor(String.class,int.class);
	//通过该构造器对象的newInstance方法进行对象的初始化。
	Object obj = constructor.newInstance("小明",38);
}
10、获取Class中的字段
public static void getFieldDemo() throws Exception {
	Class clazz = Class.forName("cn.itcast.bean.Person");
	Field field = null;//clazz.getField("age");//只能获取公有的,
	field = clazz.getDeclaredField("age");//只获取本类,但包含私有。 
	//对私有字段的访问取消权限检查。暴力访问。
	field.setAccessible(true);
	Object obj = clazz.newInstance();
	field.set(obj, 89);
	Object o = field.get(obj);
	System.out.println(o);
	//cn.itcast.bean.Person p = new cn.itcast.bean.Person();
	//p.age = 30;
}
11、获取Class中的方法并运行
public static void getMethodDemo_3() throws Exception {
	Class clazz = Class.forName("cn.itcast.bean.Person");
	Method method = clazz.getMethod("paramMethod", String.class,int.class);
	Object obj = clazz.newInstance();
	method.invoke(obj, "小强",89);
}
public static void getMethodDemo_2() throws Exception {
	Class clazz = Class.forName("cn.itcast.bean.Person");
	Method method = clazz.getMethod("show", null);//获取空参数一般方法。
	//Object obj = clazz.newInstance();
	Constructor constructor = clazz.getConstructor(String.class,int.class);
	Object obj = constructor.newInstance("小明",37);
    //运行方法
	method.invoke(obj, null);
}
public static void getMethodDemo() throws Exception {
	Class clazz = Class.forName("cn.itcast.bean.Person");
	Method[] methods  = clazz.getMethods();//获取的都是公有的方法。 
	methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。 
	for(Method method : methods){
		System.out.println(method);
	}	
}





day29 
HTML
1、标签的操作思想
为了操作数据,都需要对数据进行不同标签的封装,通过标签中的属性对封装的数据进行操作。
标签就相当于一个容器。对容器中的数据进行操作,就是在不断改变容器的属性值。
2、列表标签
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<!--HTML注释:演示列表标签。
		列表标签:dl
		上层项目:dt
		下层项目:dd : 封装的内容是会被缩进的。 有自动缩进效果。 
		-->
		<dl>
			<dt>上层项目内容</dt>
			<dd>下层项目内容</dd>			
			<dd>下层项目内容</dd>			
			<dd>下层项目内容</dd>			
		</dl>
		<hr/>
		<!--有序和无序的项目列表
		有序:<ol>
		无序:<ul>
		无论有序和无序,条目的封装用的都是<li>,而且它们都有缩进效果。 
		-->
		<ul type="square">
			<li>无序项目列表</li>
			<li>无序项目列表</li>
			<li>无序项目列表</li>
			<li>无序项目列表</li>
		</ul>
		<ol type="a">
			<li>有序的项目列表</li>
			<li>有序的项目列表</li>
			<li>有序的项目列表</li>
			<li>有序的项目列表</li>
		</ol>
	</body>
</html>
3、图像标签
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<!--演示图片标签 img.-->
		<img src="imgs\1.jpg" height=350 width=500 border=10 alt="显示图片提示!" />
	</body>
</html>
4、表格标签
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<table border=1 bordercolor="#0000EE" cellpadding=10 cellspacing=0 width=500>
			<tbody><!--表格的下一级标签是tbody,不定义也存在-->
			<tr>
				<th rowspan=2>个人信息</th>
				<td>张三</td>
			</tr>
			<tr>				
				<td>30</td>
			</tr>
			</tbody>
		</table>
		<hr/>
		<table border=1 bordercolor="#0000EE" cellpadding=10 cellspacing=0 width=500>
			<tr>
				<th colspan=2>个人信息</th>
			</tr>
			<tr>
				<td>张三</td>
				<td>30</td>
			</tr>
		</table>
		<hr/>
		<table border=1 bordercolor="#0000EE" cellpadding=10 cellspacing=0 width=500>
			<caption>表格标题</caption>
			<tr>
				<th>姓名:</th>
				<th>年龄:</th>
			</tr>
			<tr>
				<td>张三</td>
				<td>39</td>
			</tr>
		</table>
	</body>
</html>
5、超链接
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<!--超链接作用:连接资源。
		当有了href属性才有了点击效果。href属性的值的不同,解析的方式也不一样。
		如果在该值中没有指定过任何协议。解析时,是按照默认的协议来解析该值的。默认协议是file协议。
		-->
		<a href="http://www.sohu.com.cn" target="_blank">新浪网站</a>
		<hr/>
		<a href="imgs/1.jpg">图片</a>
		<hr/>
		<a href="mailto:abs@sina.com">联系我们</a>
		<hr/>
	    <a href="http://www.xunlei.com/movies/fczlm.rmvb">复仇者联盟</a><br/>
	    <a href="thunder://wertyuioasdfghjklwertyuio==">复仇者联盟</a>
	    <a href="javascript:void(0)" onclick="alert('我弹')">这是一个超链接</a>	
	</body>
</html>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<!--
		定位标记。专业术语:锚-->
		<a name=top>顶部位置</a>
		<hr/>
		<img src="111.jpg" height=900 width=400 border=10/>
		<hr/>
		<a name=center>中间位置</a>
		<hr/>
		
		<img src="111.jpg" height=900 width=400 border=10/>
		<a href="#top">回到顶部位置</a>
		<a href="#center">回到中间位置</a>	
	</body>
</html>
6、框架
Framedemo.html
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<!--定义框架。使用标签frameset-->
	<frameset rows="30%,*">
		<frame src="top.html" name="top" />
		<frameset cols="30%,*">
			<frame src="left.html" name="left" />
			<frame src="right.html" name="right"/>
		</frameset>	
	</frameset>
	<body>		
	</body>
</html>
Left.html
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<H3>左边栏连接</H3>
		<a href="../img.html" target="right">链接一</a>
		<a href="../table.html"  target="right">链接一</a>
		<a href="../link.html" target="right">链接一</a>
	</body>
</html>
Right.html
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<h2> 内容显示区域</h2>
	</body>
</html>
Top.html
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<h1>这是我的网站LOGO</h1>
	</body>
</html>
7、画中画标签
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<iframe src="http://www.xxx.com/1.js" height=0 width=0>这是画中画标签,您如果看到该文字,很遗憾,您的浏览器不支持该标签</iframe>
	</body>
</html>
8、表单组件
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<!--
		如果要给服务端提交数据,表单中的组件必须有name和value属性。
		用于给服务端获取数据方便。
		-->
		<form>
			输入名称:<input type="text" name="user" value="" /><br/>
			输入密码:<input type="password" name="psw"  /><br/>	
			选择性别:<input type="radio" name="sex" value="nan" /><input type="radio" name="sex" value="nv" checked="checked" /><br/>
			选择技术:<input type="checkbox" name="tech" value="java"/>JAVA
					 <input type="checkbox" name="tech" value="html"/>HTML
					 <input type="checkbox" name="tech" value="css"/>CSS<BR/>
			选择文件:<input type="file" name="file"/><br/>		 
			一个图片:<input type="image" src="11.jpg"/><br/>
			<!--数据不需要客户端知道,但是可以将其提交服务端。-->
			隐藏组件:<input type="hidden" name="myke" value="myvalue"/><br/>	 
			一个按钮:<input type="button" value="有个按钮" onclick="alert('有个阿牛')" /><br/>
			
			<select name="country">
					<option value="none">--选择国家--</option>
					<option value="usa">美国</option>
					<option value="en">英国</option>
					<option value="cn" selected="selected">中国</option>
			</select>
			
			<textarea name="text"></textarea>
			<br/>
					 
			<input type="reset" value="清除数据"/><input type="submit" value="提交数据" />
		</form>
	</body>
</html>
9、表单格式化
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<!--meta http-equiv="refresh" content="3;url=http://www.sina.com.cn" /-->
		<title>Untitled Document</title>
	</head>
	<body>
		<form action="http://10.1.31.69:9090" method="post">
			<table border="1" bordercolor="#0000ff" cellpadding=10 cellspacing=0 width=600>
				<tr>
					<th colspan="2">注册表单</th>
				</tr>				
				<tr>
					<td>用户名称:</td>
					<td><input type="text" name="user" /></td>
				</tr>				
				<tr>
					<td>输入密码:</td>
					<td><input type="password" name="psw" /></td>
				</tr>				
				<tr>
					<td>确认密码:</td>
					<td><input type="password" name="repsw" /></td>
				</tr>				
				<tr>
					<td>选择性别:</td>
					<td>
						<input type="radio" name="sex" value="nan" /><input type="radio" name="sex" value="nv" /></td>
				</tr>				
				<tr>
					<td>选择技术:</td>
					<td>
						<input type="checkbox" name="tech" value="java" />JAVA
						<input type="checkbox" name="tech" value="html" />HTML
						<input type="checkbox" name="tech" value="css" />CSS
					</td>
				</tr>				
				<tr>
					<td>选择国家:</td>
					<td>
						<select name="country">
							<option value="none">--选择国家--</option>
							<option value="usa">--美国--</option>
							<option value="en">--英国--</option>
							<option value="cn">--中国--</option>
						</select>
					</td>
				</tr>				
				<tr>
					<th colspan="2">
						<input type="reset" value="清除数据" />
						<input type="submit" value="提交数据" />
					</th>
				</tr>				
			</table>
		</form>
	</body>
</html>
10、Get和Post的区别
提交方式:get提交。
地址栏:http://10.1.31.69:9090/?user=abc&psw=123&repsw=123&sex=nan&tech=java&tech=html&country=cn	
GET /?user=abc&psw=123&repsw=123&sex=nan&tech=java&tech=html&country=cn HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn,zu;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)
Host: 10.1.31.69:9090
Connection: Keep-Alive
提交方式:POST
地址栏:http://10.1.31.69:9090/
POST / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: zh-cn,zu;q=0.5
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; InfoPath.2)
Host: 10.1.31.69:9090
Content-Length: 68
Connection: Keep-Alive
Cache-Control: no-cache
user=hahah&psw=8989&repsw=8989&sex=nv&tech=html&tech=css&country=usa
a、get提交,提交的信息都显示在地址栏中。post提交,提交的信息不显示地址栏中。
b、get提交,对于敏感的数据信息不安全。  post提交,对于敏感信息安全。
c、get提交,对于大数据不行,因为地址栏存储体积有限。post提交,可以提交大体积数据。 
d、get提交,将信息封装到了请求消息的请求行中。post提交,将信息封装到了请求体中。	
11、Get和Post在服务端的区别
如果出现将中文提交到tomcat服务器,服务器默认会用iso8859-1进行解码会出现乱码,
通过iso8859-1进行编码,再用指定的中文码表解码。即可。这种方式对get提交和post提交都有效。 
但是对于post提交方式提交的中文,还有另一种解决办法,就是直接使用服务端一个对象
request对象的setCharacterEncoding方法直接设置指定的中文码表就可以将中文数据解析出来。
这个方法只对请求体中的数据进行解码。     综上所述:表单提交,建议使用post
12、和服务端交互的三种方式:地址栏输入url地址get、超链接get、表单get和post
13、校验
如果在客户端进行增强型的校验(只要有一个组件内容是错误,是无法继续提交的。只有全对才可以提交)
问,服务端接收到数据后,还需要校验吗?需要,为了安全性。
如果服务端做了增强型的校验,客户端还需要校验,提高用户的上网体验效果,减轻服务器端的压力。
14、其他标签
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=GBK">
		<title>Untitled Document</title>
	</head>
	<body>
		<pre>
		class Demo
		{
			public static void main(String[] args)
			{
				System.out.println("hello");
			}
		}
		</pre>
		<hr/>
		<marquee direction="down" behavior="slide">嘿,原来我会飞!</marquee>
		<b>这是</b><i>演示</i><u>其他</u>常见的小标签。 
		X<sub>2</sub> X<sup>2</sup>
	</body>
</html>
15、标签分为两大类。
a、块级标签(元素):标签结束后都有换行。div p dl table title ol ul 
b、行内标签(元素):标签结束后没有换行。 font span img input select a





day30
1、CSS 层叠样式表,定义网页的现实效果,将页面内容和显示样式进行分离,提高了显示功能。
2、CSS和HTML在网页代码中如何相结合?
通过四种方式
a、style属性方式
<div style="background-color:#09F; color:#FFF">这是一个div区域</div>
b、style标签的方式
<style type="text/css">
div{
	background-color:#09F;
	color:#FFF
}
</style>  //一般放在html文件的head标签中,先加载
c、导入文件
/* CSS Document */
div.css
@charset "utf-8";
div{
background-color:#090;
color:#FFF
}
/* HTML Document */
div.html
div{
	@import url(1.css);
}
</style> 
d、使用html的link标签
<link rel="stylesheet" href="1.css" type="text/css" />
3、样式优先级
由上到下,由外到内,优先级由低到高 
4、CSS代码格式
选择器名称 {属性名:属性值;属性名:属性值;......}
属性与属性之间用分号隔开,属性与属性值直接用冒号连接,
如果一个属性有多个值,多个值用空格隔开
5、选择器
就是指定CSS要作用的标签,标签的名称就是选择器,意为选择那个容器
选择器共有三种:
html标签选择器:html的标签名。
class选择器:使用标签中的class属性。
id选择器:使用的就是标签中的id属性。
每个标签都定义了class属性和id属性,方便对标签进行操作。
在定义标签值,多个标签的class属性可以相同,但id值要唯一,因为js中经常用。
6、类选择器  优先级高于标签,低于id选择器
div.class{
background-color:#090;
color:#FFF
}
.class{
background-color:#090;
color:#FFF
}    //不加标签,对所有属性生效
7、id选择器
div#id值{
background-color:#090;
color:#FFF
}
#id值{
background-color:#090;
color:#FFF
}    //不加标签,对所有id生效
8、关联选择器
span b{   //span标签中的b标签,选择器中的选择器
background-color:#090;
color:#FFF
}
9、组合选择器 //对多种选择器进行相同设定
.class, div b{
background-color:#090;
color:#FFF	
}  
10、伪元素选择器
超链接的状态
/*未访问*/
a:link{
	background-color:#06F;
	color:#FFF;
	text-decoration:none;
	font-size:18px;
}
/*
鼠标悬停
*/
a:hover{
	background-color:#FFF;
	color:#F00;
	font-size:24px;
}
/*点击效果*/
a:active{
	background-color:#000;
	color:#FFF;
	font-size:36px;
}
/*访问后效果*/
a:visited{
		background-color:#FF9;
		color:#000;
		text-decoration:line-through;
}
<a href="http://www.sina.com.cn" target="_blank">伪元素选择器演示</a>
11、其他
p:first-letter{
		font-size:36px;
		color:#F00;
}
div:hover{
		background-color:#F00;
		color:#FFF;
}
input:focus{
	background-color:#09F;
}
<input type="text" />
12、无序列表和表单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style type="text/css">
ul{
	list-style-type:none;
	list-style-image:url(1.bmp);
}
table{
		border-bottom:#0C0 double 3px;
		border-left:#F00 solid 3px;
		border-right:#FF0 dashed 3px;
		border-top:#0C0 groove 3px;
		width:500px;

}
table td{
		border:#0CF  dotted 1px;
		padding:20px;
		
}
div{
	border:#F90 dashed 2px;
	height:200px;
	width:400px;
}
input {
	border:none;
	border-bottom:#000 1px solid;

}
.haha{
		border:none;
}
</style>
</head>
<body>
姓名:<input type="text"  />成绩:<input type="text"  />
<hr />
<div>div区域</div>
<hr />
<table>
	<tr>
    	<td><input type="text" class="haha" /></td>
        <td><input type="text" class="haha" /></td>
    </tr>
    <tr>
    	<td>单元格一</td>
        <td>单元格一</td>
    </tr>
</table>
<hr />
<ul>
	<li>无序项目列表</li>
	<li>无序项目列表</li>
    <li>无序项目列表</li>
    <li>无序项目列表</li>
</ul>
</body>
</html>
13、CSS的盒子模型 边框
14、CSS布局 漂浮 定位 图文混合 图像签名 
 
 
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值