java基础知识点 java基础知识大全(重点)
代码只是思想的一种体现形式01-01图形化方式:鼠标键盘;命令行方式:dir:列出当前目录下的文件以及文件夹md:创建目录e:进入E盘rd:删除目录cd:进入目录cd..:退出目录cd/:返回根目录del:删除文件exit:退出DOS命令行echo haha>1.txtdel 1.txt 回车del opdel *.txt01-02SUN斯坦福大学网络公司95年推出的一门高级编程语言完全面向对象,安全可靠,与平台无关的编程语言J2EE企业版J2SE标准版J2ME小型版Java5.0之后就更名为JAVAEE JAVASE JAVAME了语言特点:跨平台型,在不同的系统平台上都可以运行。也称为Java具有良好的可移植性即可,由JVM来负责Java程序在该系统中的运行。01-03Java语言环境搭建JREJava虚拟机和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可JDK是提供给Java开发人员用的,其中包含了Java的开发工具,也包括了JRE。所以装了JDK就不用再继续装JRE了。其中的开发工具:编译工具打包工具01-04配置环境变量。java_home: C:……jdk1.6.0path: C:……jdk1.6.0binclasspath: C:……jdk1.6.0lib ; .01-05配置技巧:path即配置了以后的内容,而且也配置了系统环境变量。%%动态获取已有path值所以:可以把容易变化的提取出来,然后获取出来。比如:JAVA_HOME=D:jdk1.6.0 path=%%bin 就相当于path=D:jdk1.6.0bin01-06临时配置:set命令,查看或设置环境变量的值set path=C:……jdk1.6.0bin 就能用了。但是如果在DOS中用start打开,环境变量值仍然有效01-07创建hellowrldDemo.javaclass Demo{public static void main{Stytem.out.println;}}编译:javac Demo.java输出:java Demo如果加入public的话,类名与文件名必须一致01-08临时配置环境变量set classpath=I:重学javajava_codeday01对环境变量清空set classpath=虚拟机在启动时,先找的是环境变量classpath.例如,D盘里面有一个Demo.classE盘里面有一个Demo.class但是classpaht=E:则java Demo时运行出来的为hello world当写“;”时,在指定目录找,找不到转到当前目录,如果没有写“;”时,那么仅在指定目录找,并不找当前目录。所以,在正常情况下,不要加“;”如果配置多路径: set classpath=C:;D: 如果还要找当前目录找: set classpath=.;C:;D: classpath是先找配置环境变量,再找当前目录,如果没有加“;”那就不再继续找当前目录path与classpath相反。 path是现在当前目录下找,再去path环境变量去找注意:如果是java文件用classpath,如果是可执行文件用path01-09说一说hello world 小程序的特点class 专门用来定义类的关键字Demo 是类名用大括号定义区间,{}。一般格式为 {public static void main {System.out.println;}}类里是否写主函数,不是必须的。类里面能写一个主函数public static void main 01-10备注注释:①注解说明程序的②调试程序单行注释//多行注释/**/文档的注释/**@author*/关键:多行注释当中,不能有多行注释。最好一遍写注释,一边写代码一般情况下:类上面加的都是文档类的注释,函数上面加的是多行注释,一般代码中的某几句话,加的是单行注释/*需求:定义一个hello world小程序思路:1,2,3步骤:1通过class关键字定义一个类。将代码都编写到该类中。2为了保证该类的独立运行,在类中定义一个主函数,格式为publi static void main3保存一个扩展名为java的文件4到dos控制台中通过javac工具对java文件进行编译。5再通过java命令对生成的类文件进行执行。*/ 02-01关键字:就是被赋予特殊涵义的单词标识符:在程序中自定义的一些名称,比如:类名。规则:26个英文字母,0-9数字,_$组成1,数字不可以开头2,不可以使用关键字3,Java中严格区分大小写包名:必须全是小写;类名与接口名:多单词组成时,所有单词的首字母大写变量名与函数名:第一个单词字母小写,第二个单词开始每个单词首字母大写。常量命:所有字母均大写,多个单词用下划线隔开。建议定义包名:不要重复,可以使用url来完成定义。url是唯一的。02-07变量:就是将不确定的数据进行存储,也就是需要在内存中开辟一个空间。开辟空间:数据类型,变量名称,数据数据类型:①基本数据类型,整数类型byte,short,int,long;浮点类型float,double;字符型char;布尔型boolean;②引用数据类型类接口,数组定义变量格式:数据类型 变量名 = 初始化值例如:定义一个int类型的变量,取值为4int x = 4 ;x = 10;//将x变为10什么时候定义变量?当数据不确定时,需要对数据进行存储时,就定义一个变量,来完成存储的动作。02-08类型转换:byte b = 3;b = ;System.out.println; 5 System.out.println70); F02-09运算符取模%-1%5=-1自增++int a = 3 , b; b = a++; //先赋值,后+1int c = 3 , d; d = ++c; //先+1,后赋值字符串数据和任何数据使用+都是相连接,最终都会变成字符串。System.out.println; //5+5=55System.out.println);//5+5=1002-10转义字符:通过来转变后面字母或者符号的含义。n 换行b 退格r 按下回车键 t 制表符char ch = 'n'; //代表一个回车想打印一个有双引号的hello System.out.println; //这样就把"后面的双引号转义为双引号输出。02-11赋值运算符 = += -= *= /= %= x+=4 就是说相当于x=x+4 ,但是x+4=4 是一次运算,会进行一次自动转换。short x=4;x=x+4;x+=4区别:x=x+4编译失败,因为x会被提升为int类型,运算后的结果还是int类型,无法复制给short类型。x+=4编译成功,因为+=运算符在给x赋值时,自动完成了强制转换操作。比较运算符 ==相等于 !=不等于比较运算符的结果要么真true,要么假false。02-12逻辑运算符 逻辑运算符作用:用于连接boolean类型的表达式& 两边的booblean表达式有一个为false,那么结果都为false,只有两遍都为true,则结果为true| 两边的有一面为true,就为true。两面都为false则结果为false^ 两边相同时,结果为false,两边不同时,结果为true! 取反&& 比如,int a = 2; a>3 && a<6; 如果左侧为假,则不运算,直接为假。如果左侧为真,再继续运算右侧。|| 当左面为真时,右侧不运算;如果左面为假时,再运算右侧。02-13左移右移<<左移,>>右移,>>>无符号右移左移就是2的N次幂3<<2 --> 3*2的2次方 123<<3 --> 3*2的3次方 24右移就是除以2的N次幂的整数6>>2 --> 6/2的2次方 16>>1 --> 6/2的1次方 3>>优异,最高位补什么由原有数据的最高位而定>>>无符号右移,无论最高位是什么,右移后都用0补02-14与-或-异或& 6&3=2; | 6|5=7; ^ 6^5=3; ~ ~6=-7;一个数异或同一个数两次,结果还是那个数。02-15最有效率的方式算出2乘以8等于几?2<<3 =16class Demo15{public static void main {int n=3,m=8;System.out.println;//System.out.println;//int temp;//temp=n;//n=m;//m=temp;//System.out.println;//System.out.println;//n = n + m;//如果n+m的值非常大,容易超出int范围。//m = n - m;//n = n - m;//System.out.println;System.out.println;n = n ^ m;m = n ^ m;//^mn = n ^ m;System.out.println;}}02-16三元运算符格式?表达式1:表达式2;,02-17程序流程控制判断结构if语句int x = 3;if //满足条件时,则执行{}的内容{System.out.println;}当没有{}时候,就执行最近的语句。if else 结构 简写格式: 变量 = ?表达式1:表达式2;三元运算符的特点是:好处:可以简化if else代码弊端: 因为是一个运算符,所以运算完必须要有一个结果。if else else if else...02-18if 练习//需求1:根据用户定义的数值不同,打印对应的星期英文。//需求2:根据用于指定月份,打印该月份所属的季节。//3,4,5春季; 6,7,8夏季;9,10.11秋季;12,1,2冬季02-19选择结构switch语句格式 switch{case 取值1:执行语句;break;//跳出语句case 取值2:执行语句;break;...default://默认情况执行语句break;}特点:① 选择的类型只有四种byte short int char② case之间与default没有顺序,先执行第一个case,没有case匹配的值则执行default③ 结束switch语句的四种情况,遇到break,执行switch语句消失;④ 如果匹配的case或者default没有对应的break那么程序会继续乡下执行,直到遇到break或switch结尾结束02-20用switch判断季节注:if和switch语句很像,具体什么场景下应用哪个语句呢?如果判断的具体数值不多,而且符合byte short int char这四种类型建议使用switch语句,因为效率稍高其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广.3-01循环结构 while ; do while ; forwhile语句格式:、while{执行语句}do while语句格式do{执行语句}while//需求:打印1,2class WhileDemo{public static void main{int x = 1;while{System.out.println;x++;}}}3-02do while//需求:打印 1,2class WhileDemo{public static void main{int x = 1;do{System.out.println;x++;}while;}}//注意: do while特点是条件无论是否满足,循环体都要执行一次3-03for格式for{执行语句;}例如://执行顺序 1 258 47 for { 3 6System.out.println;}3-04for 与while不同1,变量有自己的作用域,对于for来讲;如果用于控制循环的增量定义在for语句中。那么该变量只在for语句内有效。for语句执行完毕。该变量在内存中被释放。2,for和while可以互换,如果需要定义循环增量。用for更为合适总结:对于要执行很多次的语句时,就用循环语句3-05无限循环的最简单表达形势for{}或者while{}3-06累加思想:通过变量记录住每次变化的结果。通过循环的格式。进行累加动作。计数器思想:通过一个变量记录数据的状态变化。也需要通过循环完成3-07语句嵌套形势,就是语句中含有语句//循环嵌套class ForForDemo {public static void main {for {for {System.out.print;}System.out.println;}}}//对于打印长方形:外循环控制的行数,内循环控制的是每一行的列数。也就是一行中的元素的个数。发现图形有很多行,每一行都有很多列原理:形象说法,大圈套小犬3-08尖朝上,改变条件,让条件随着外循环变化;尖朝下,改变初始化值,让初始化值随着外循环变化;3-10其他流程控制语句breakcontinuebreak语句:应用于选择结构和循环结构continue语句:只能作用于循环结构。特点:结束本次循环,继续下一次循环记住:break和continue作用的范围,break和continue单独存在时,下面不可以有单独语句3-11/**打印输出** ** * ** * * * * * * * * * * * * * *①,控制行号,②控制空格③控制星号与空格尖朝下,y随x变而变,尖朝上,条件随x变而变*/class ForForTest2{public static void main {//行号for {//空格for {System.out.print;}//星号+空格for {System.out.print;}System.out.println;}}}3-12函数:函数就是定义在类中的具有特定功能的一段独立小程序,函数也称为方法为了提高代码的服用行。对代码进行抽取,将这个部分定义成一个独立的功能。方便日后的使用,java中对功能的定义是通过函数的形式来体现的。1,先明确函数定义的格式修饰符 返回值类型 函数名{执行语句;return 返回值;}当函数运算后,没有具体的返回值时,这时返回值类型用一个特殊的关键字来表示关键字为:void,void代表的是没有具体返回值的情况当函数的返回值类型是void时,函数中的return语句可以省略不写注:返回值类型:函数运行后的结果的数据类型。参数类型:是形式参数的数据类型。形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。实际参数:传递给形式参数的具体值return:用于结束函数返回值:该值会返回给调用者函数的特点:①定义函数可以将功能进行封装,②提高了功能的复用性③函数只有被调用时,才会被执行④提高了代码的复用性⑤函数中只能调用函数,不可以在函数内定义函数3-13函数的基本应用如何定义一个函数呢?1,既然函数是一个独立的功能,那么该功能的运算结果先明确;****因为这是在明确函数的返回值类型****2,再明确在定义该功能的过程中,是否需要未知的内容参与运算。****因为这是在明确函数的参数列表//定义一个功能,完成3+4的运算,并将结果返回给调用者思路,明确功能的结果是一个整数和,再实现该功能的过程中,是否有未知内容参与运算,没有。1其实这两个功能就是在明确函数的定义2明确函数的参数列表以上的函数的功能是固定的,毫无扩展性而言。为了方便用户需求,由用户指定加数与被加数。这样功能才有意义。思路,结果是一个和,返回值类型是int,有未知内容参与运算。有两个。这两个位置参数类型都是int//判断两个数是否相同class PanDuan {public static void main {boolean x =getPan;System.out.println;}static boolean getPan{return x==y;}}再注意:1,如果函数返回值为void时候,主函数中无法进行输出2,函数中只进行定义就好,不要进行进行运算结果。因为那是调用者的事情3-14函数的重载概念:在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数或者参数类型不同即可。特点:什么时候用重载?当定义的功能相同,但参与运算的未知内容不同。那么,这时就定义一个函数名称以表示其功能,方便阅读,而通过参数列表的不同区分多个同名函数.3-15示例//返回两个数的和int add{return x+y;}//返回三个数的和int add{return x+y+z;}//返回两个小数的和double add{return x+y;}3-16注意:重载与返回值类型没关系。函数不可以跟给定函数同时存在在一个类当中eg:给定函数void show{}例子: a. void shor{}//重载与返回值类型没关系b. double show{}//函数不可以跟给定函数同时存在在一个类当中3-17数组概念:同一种类型数据的集合。其实数组就是一个容器好处:可以自动给数组中的元素从0开始编号,方便造作这些元素。//元素类型 数组名 = new 元素类型 ;//需求:想定义一个可以存储3个整数的容器.int x = new int;//不是元素,是元素的个数一旦定义数组之后,堆内存就肯定有值,有默认值int,默认为0;double 0.0; float 0.0f;boolean false;赋值:x = 59;//给0空间赋值为59x = null;//x不再指向数组,而为空 Java程序在运行时,一共划分了5个区域。①栈内存:用于存储局部变量,当数据使用完时,所占空间会自动释放。②堆内存:数组和对象,通过new简历的实例都存放在堆内存中。每一个实体都有内存地址值实体中的变量都有默认初始化值实体不再被使用、会在不确定的时间内被垃圾回收站回收。③方法区④本地方法区⑤寄存器举个例子说明引用数据类型:int x = new int;int y = x;y = 30;System.out.println;//输出结果为30,而不是0,原因是数组x与数组y同时引用一个内存地址。4-01数组的定义第一种格式:int arr = new int;//一般情况下,用这种格式int arr = new int;//两种格式都行哦。赋值的时候arr=3;arr=4;第二种格式:int arr = new int{3,1,4,5,2};//这种叫做静态初始化方式,是一种简化形势↑注意这里不要写长度int arr = {3,4,5,6,3};注意:ArrayIndexOutOfBoundsException:4:操作数组时,访问到了数组中不存在的角标NullPointerException:空指针异常,当引用没有任何指向值为空的情况该引用还在用于操作实体时。4-02常见操作-遍历数组的操作:获取数组中的元素。//数组中有一个属性可以直接获取数组元素个数使用方式:数组名称.lengthclass ArrayDemo3{public static void main {//int arr=new int;int arr={3,4};//数组中有一个属性可以直接获取数组元素个数lengthint sum=0;for{System.out.println;sum=sum+arr;}System.out.println;}}//定义功能,用于打印数组中的元素。元素间用逗号隔开class ArrayTest1 {public static void main {int arr={3,4,5,6,3,13,4};printarr;}public static void printarr{System.out.print;for//for是打印数组的{if//判断x不是倒数第一个数组元素{System.out.print;}elseSystem.out.println;}}}4-03/*给定一个数组{5,1,6,4,2,8,9}获取数组中的最大值,以及最小值思想:1,获取最值需要进行比较,每一次比较都会有一个较大的值,因为该值不确定通过一个变量进行临时存储。2,让数组中的每一个元素都和这个变量中的值进行比较。如果大于了变量中的值,就用该变量记录较大的值。3,当所有的元素都比较完成,那么该变量中存储的就是数组中的最大值步骤:1,定义变量。初始化为数组中的任意一个即可2,通过循环,对数组进行遍历3,在遍历过程中,定义判断条件,如果遍历到的元素比变量中的元素大,就赋值给该变量。需要定义一个变量,以便提高复用性。1,明确结果,数组中的最大元素 int.2,位置内容:一个数组。int*/class ArrayTest2{//求最大值的函数public static int getMax{int max = arr;for {if{max=arr;}}return max;}//求最小值的函数public static int getMin{int min= arr;for {ifmin=arr;}return min;}//主函数public static void main {int arr={3,4,5,7,88,6,44,5};int max = getMax;int min = getMin;System.out.println;}}//获取最大值的另一种方式。//可不可以将临时变量初始化为0呢?可以的,这种方式,初始化的是角标int max = 0;for{ifmax=x;}return max;//获取double4-04排序--选择排序package Test4;/*** 对给定的数组进行排序* {5,1,6,4,2,8,9}* 从小到大的方式打印*/class ArrayTest2 {//按照从小到大排序public static void selectSort1{//进行遍历每个数组元素的第一个角标for {//数组元素的下一个角标for{//如果第一个元素大于第一个元素if{//那么给元素进行调换位置int temp = arr;arr=arr;arr=temp;}}}}//定义一个打印函数public static void printarr{System.out.print;for//for是打印数组的{if//x不等于最后一个数组,则执行{System.out.print;}elseSystem.out.println;}}//主函数public static void main{int arr={5,1,6,4,2,8,9};//从小到大排序selectSort1;printarr;//从大到校排序selectSort2;printarr;}}4-05排序-冒泡排序。相邻的两个元素进行比较,如果符合条件换位。//冒泡排序,从小到大排序public static void bubbleSort1{//遍历,相邻两个元素,不能剩最后一个元素对比,所以arr.length-1for{//for{//做相邻比较if{int temp = arr;arr = arr;arr = temp;}}}}4-06排序-位置置换功能抽取public static void swap{int temp = arr;arr = arr;arr = temp;}//那么给元素进行调换位置/*int temp = arr;* arr=arr;* arr=temp;*/swap;4-07数组-折半查找可以提高效率,但是必须要保证该数组时有序的数组。原理 min = 0 ;max = arr.length-1;mid = /2;package test;/***折半查找*/public class ArrayTest4 {public static void main{int arr = {2,4,5,7,19,32,45};int index = halfSearch;System.out.println;int index2 = halfSearcp;System.out.println;int index3 = getIndex;System.out.println; }//折半查找方法一public static int halfSearch{int min,max,mid;min = 0;max = arr.length - 1;mid = /2;while{ifmin = mid +1;else ifmax = mid -1;ifreturn -1;mid = /2;}return mid;}//折半查找方法二public static int halfSearcp{int min = 0,max = arr.length -1,mid;while{mid = /2;if{max = mid-1;}else if{min = mid +1;}elsereturn mid;}return -1;}//正常查找public static int getIndex{for{if{return x;}}return -1;}}/*练习,在有序序列中插入一个数字*/原理,通过折半的方式,如果原序列当中有,就在原序列中插入,如果没有,就在最小角标的位置插入4-08数组,十进制-二进制package Demo;/** 十进制-->二进制*/class ArrayTest5 {public static void toBin{//新建一个存储字符串StringBuffer的对象sbStringBuffer sb = new StringBuffer;while{//将字符串存储在对象sb当中sb.append;num = num /2;}//reverse翻转功能System.out.print;}public static void main{toBin;}}4-09/*** * 十进制-->十六进制*/public static void toHex{//存储字符串容器sbStringBuffer sb = new StringBuffer;//因为32位就8组0000for{int temp = num & 15;if{sb.append);}elsesb.append;//无符号右移四位num = num>>>4;}System.out.print;}4-10/**查表法* 十进制-->十六进制*/查表法:将所有的元素临时存储起来。建立对应关系。每一次&15后的值作为索引去查建立好的表.就可以找对应的元素.建立方法:可以通过数组的形势进行建立class ArrayTest6 {public static void toHex{char chs={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',};//定义一个临时容器。char arr= new char;//pos获得数组的长度int pos = arr.length;//定义一个循环,如果这个数不是0那么继续进入循环while{//这个数与1111将值给tempint temp=num&15;//数组的倒数前一位进行存储arr = chs;//右移四位num = num>>>4;}System.out.println;for{System.out.print;} }//主函数public static void main{toHex;}}4-11//十进制→二进制public static void toBin{char chs={'0','1'};//建立容器char arr=new char;//定义数组的指针int pos = arr.length;//进行判断while{int temp = num&1;arr = chs;num = num>>>1;}4-12进制转换优化package Demo;//功能优化class ArrayTest7 {//十进制→二进制public static void toBin{trans;}//十进制→八进制public static void toOct{trans;}//十进制→十六进制public static void toHex{trans;}//功能函数public static void trans{if{System.out.println;return ;}char chs={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',};//定义一个容器char arr= new char;int pos = arr.length;//进行判断while{int temp = num & base;arr = chs;num = num >>> offset;}//进行遍历for{System.out.print;}System.out.println;}//主函数public static void main{toBin;toOct;toHex;} }4-13二维数组//一位数组 int arr = new int;格式一:int arr = new int;格式二:int arr = new int;class Array2Demo {public static void main{/*** 动态初始化方式*/int arr = new int;//定义数组arr = new int;//对数组进行初始化arr = new int;arr = new int;System.out.println;//打印二位数组的长度System.out.println;//打印二维数组中第一个数组的长度/*** 静态初始化方式*/int arr1={{3,4,5},{2,3,4},{2,3,1}};//计算一下所有数据的和。int sum = 0;for{forsum = sum +arr1;}System.out.println;}}4-14小练习int x,y;a. x = y;b. y = x;c. y = x;d. x = y;e. y = x;f. x=y;正确答案:b、e解析:一位数组:int x;int x二维数组: int y;int y;int y;int x,y相当于int x; int y;5-01面向对象面向对象三个特征:封装,继承,多态面向对象是相对过程而言的面向对象是基于面向过程的。5-02面向对象举个例子: 打开冰箱,存储进冰箱,关闭冰箱冰箱.打开;冰箱.存储;冰箱.关闭面向对象的思想:能让复杂问题简单化,让执行者→指挥者例如:面试官用面向对象思考方式思考问题,找一些具备专业功能的对象其实,您就是在找我的功能为公司创造价值。最牛的话------万物皆对象。总结一下:有对象,直接拿过来用,没有对象就自己造一个对象来用5-03类与对象的关系找对象,建对象,用对象,并维护对象之间的关系/**比如:人开门:名次提炼法。* 人* {* 开门* {* 门.开;* }* }* * 门* {* 开{操作门轴等.}* }*/类和对象的关系类:就是对现实生活中实物的描述对象:就是这类事物事实存在的个体。例如:张三,李四。就是现实生活中的对象。想要描述:提取对象中共性内容。对具体的抽象。描述时:这些对象的共性有:姓名,年龄,性别,学习Java的功能映射到java中,描述就是class定义的类。具体对象就是对应Java在堆内存中用new建立的实体。* 描述实物就是在描述实物的属性和行为* 需求:描述汽车* 属性:对应类中的变量,行为对应类中的函数总结:定义类,就是在描述实物,就是在定义属性和行为。属性和行为共同成为类中的成员类类型变量指向对象.class Car {//描述颜色String color = "红色" ;//描述轮胎数int num = 4;//运行行为void run{System.out.println;}}class CarDemo{public static void main{//生产汽车。在java中通过new操作符来完成//其实就是在堆内存中产生一个实体Car c = new Car;//c就是一个类类型变量。类类型变量指向对象//需求:将已有车的颜色改成蓝色。指挥该对象做使用。在java指挥方式是:对象.对象成员c.color = "blue";c.run;//打印:blue..4}}5-04成员变量,局部变量1,作用范围:成员变量作用于整个类中,局部变量作用于函数中或者语句中2,在内存中的位置成员变量在堆内存中,因为对象的存在,才在内存中存在;局部变量在栈内存中。3成员变量,都有默认值;局部变量,不初始化,不可能参与运算5-05匿名对象的应用Car c = new Car;c.num = 5;以上两句可以简写为:new Car.num = 5;再来两个: new Car.color = "blue";new Car.run;//打印的是:4..red匿名对象使用方式一:当对对象的方式只调用一次时,可以用匿名对象来完成,这样写比较简化如果对一个对象进行多个成员调用,必须给这个对象起个名字。匿名对象使用方式二:可以将匿名对象作为实际参数进行传递show;5-06封装-概述封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式好处:将变化隔离;便于使用;提高重用性;提高安全性。原则:将不需要对外提供的内容都隐藏起来;把属性隐藏,提供公共方法对其访问。5-07封装 privateprivate:私有,权限修饰符,用于修饰类中的成员.私有只在本类中有效.注意:私有仅仅是封装的一种表现形式。之所以对外提供访问方式,就因为可以在访问方式中加入访问判断逻辑语句对访问的数据进行操作。提高代码健壮性。//将age私有化以后,类以外即使建立了对象也不能直接访问。//但是人应该有年龄,就需要在person类中提供对应的访问方式。class Person {private int age;//设置public void setAge{if{age = a;speak;}elseSystem.out.println;}//获取public int getAge{return age;}void speak{System.out.print;}}class PersonDemo{public static void main{Person p =new Person;//p.age = 20;p.setAge;//p.speak;}}成员变量,都有默认值;局部变量,不初始化,不可能参与运算5-08构造函数1,函数名与类名相同2,根本就不需要定义返回值类型3,所以不能写return;作用:给对象进行初始化注意:!!对象一建立就会自动调用与之对应的构造函数构造函数小细节:当一个类中没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。当在类中自定义了构造函数后,默认的构造函数就木有啦。class Person{person{}//默认的构造函数}//构造函数,创建一个孩子,获取姓名,并且哭。。class Person1{private String name;private int age;Person1{System.out.println;cry;}//哭static void cry{System.out.println;}}class PersonDemo2{public static void main{Person1 p1 =new Person1;p1.cry;}}总结:构造函数与一般函数在写法上不同构造函数与一般函数在运行上也有不同。构造函数是在对象一建立就运行。给对象初始化。而一般方法是对象调用才执行,是给对象添加对象具备的功能。一个对象简历,构造函数只运行一次。而一般方法可以被对象调用多次。构造函数的定义时间:当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中5-09构造代码块class Person{ Private String name;Private int age;//构造代码块{System.out.println;}//构造函数Person{name = a;System.out.println;}}作用:给对象进行初始化对象一建立就运行,而且优先于构造函数执行与构造函数的区别:构造代码块,是给所有对象进行统一初始化;而构造函数,是给对应的对象进行初始化。构造代码块中定义的是不同对象共性的初始化内容。5-10this关键字class Person{private String name;private int age; Person3{this.name = name;}}this:看上去,是用于区分局部变量和成员变量同名情况。this为什么可以解决这个问题?this到底代表的是什么呢?this:就代表本类的对象,到底代表哪一个呢?this代表它所在函数所属对象的引用简而言之:哪个对象在调用this所在的函数,this就代表哪个对象。5-11this关键字的应用当定义类中功能时,该函数内部要用到调用该函数的对象时,这时用this来表示这个对象但凡本类功能内部使用了本类对象,都用this表示/*** 需求:给人定义一个用于比较年龄是否相同的功能,也就是说是否是同龄人*/class Person4{private int age;//建立一个构造函数Person4{this.age = age;}//定义一个函数compare,进行对比public boolean compare{return this.age==Person.age;}}class PersonDemo4 {public static void main{Person4 p1 = new Person4;Person4 p2 = new Person4;//将对比的结果传给bboolean b = p1.compare;System.out.println;}}5-12this关键字在构造函数间调用注意哈:构造函数间调用,只能用this语句。this语句:用于构造函数之间互相调用this;注意:this语句只能放在this语句的第一行,例如//正确的方式this;this.age = age;//错误的方式this.age = age;this;总结:一般函数是不能直接调用构造函数的。this只能在构造函数间应用。6-01static关键字静态:static用法:是一个修饰符,用于修饰成员当成员被静态修饰后,就多了一种调用方式,除了可以被对象调用外,还可以直接被类名调用格式:类名.静态成员static特点:1,随着类的加载而加载2,优先于对象存在3,被所有对象所共享4,可以直接被类名调用实例变量和类变量的区别:1,存放位置。类变量随着类的加载存在于方法区中。实例变量随着对象的建立而存在于堆内存中2,生命周期。类变量生命周期最长,随着类的消失而消失。实例变量生命周期随着对象的消失而消失。静态的使用注意事项:1,静态方法只能访问静态成员。非静态方法即可以访问静态成员也可以访问非静态成员。2,静态方法中不可以定义this,super关键字。因为静态优先于对象存在。所以静态方法中不可以出现this3,主函数是静态的静态有利有弊利:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象都存在一份。可以直接被类名调用。弊:生命周期过长。访问出现局限性。6-02main函数public static void main主函数:是一个特殊的函数。作为程序的入口,可以被jvm调用主函数定义:public:代表着最大的权限static:代表主函数随着类的加载就已经存在了。void:主函数没有具体的返回值main:不是关键字0.0;但是是一个特殊的单词~.~可以被jvm识别函数的参数,函数的类型是一个参数,该数组中的元素是一个字符串,字符串类型的数组主函数是固定格式的:jvm识别。jvd在调用主函数时,传入的是new String;注意注意哈,是0个元素class MainDemo {public static void main//new String{System.out.println;}}6-03静态什么时候使用?要从两方面下手:因为静态修饰的内容有成员变量和函数。第一方面,啥时候定义静态变量呢?答:当对象中出现共享数据时,该数据被静态所修饰;对象中的特有数据要定义成非静态存在于堆内存中第二方面,啥时候定义静态函数呢?当功能内部没有访问到非静态数据,那么该功能可以定义成静态的。eg1:class Person1{String name;public static void show//show没有访问到name,所以可以添加一个static{System.out.println;}}eg2:class Person2{String name;public void show//shor有访问到name,所以不能加static{System.out.println;}}6-04静态的应用-工具类每一个应用程序中都有共性的功能,可以将这些功能进行封装,以便复用 虽然可以通过建立ArrayTool的对象使用这些工具方法,对数组进行操作。发现了问题:1,对象是用于封装数据的,可是ArrayTool对象并未封装特有的数据。2,操作数组的每一个方法都没有用到ArrayTool对象中的特有数据。这时候考虑,让程序更加严谨,是不需要对象的。可以让ArrayTool中的方法都定义成static的,直接通过类名调用即可.将方法都静态后,可以方便于使用,但是该类还是可以被其它程序建立对象的。为了更为严谨,强制让该类不能建立对象-.-可以通过将构造函数私有化完成class ArrayTool {//私有化,嘿嘿,别人就调用不了我了private ArrayTool{};//获取最大值public static int getMax{int max = 0;for{if{max = x;}}return arr;}//获取最小值public static int getMin{int min = 0;for{if{min = x;}}return arr;}//从大到小校排序public static void selectSort{for{for{if{swap;}}}}//从小到大public static void bubbleSort{for{for{if{swap;}}}}//调换位置排序,我让你们看,所以我就弄成了私有化private static void swap{int temp = arr;arr = arr;arr = temp;}//打印输出public static void printArray{System.out.print;for{if{System.out.print;}elseSystem.out.println;}} }//新创建一个文件class ArrayToolDemo {public static void main{int arr={3,1,87,32,8,7,9,10};int max = ArrayTool.getMax;System.out.println;ArrayTool.printArray;ArrayTool.bubbleSort;ArrayTool.printArray;/*int arr={3,1,87,32,8,7,9,10};ArrayTool tool = new ArrayTool;int max = tool.getMax;System.out.println;tool.printArray;tool.bubbleSort;tool.printArray;tool.selectSort;tool.printArray;*/ }}6-05帮助文档的制作!!开始制作程序的说明书。java的说明书通过文档注释来完成。注意,必须进行public才能进行制作帮助文档/**内容*/javadoc -d myhelp -author -version abc.java命令 目录 作者 版本 java文件只有两种权限会被体现出来.一种是public,另一种是后面会学到一个类中默认会有一个空参数的构造函数默认构造函数的权限所属权限和所属类一致。6-06静态代码块特点:随着类的加载而执行,并且只执行一次。用于给类进行初始化。格式:static{静态代码块中的执行语句。}例如:class StaticCode {static{System.out.println;}}//小例子class StaticCode {StaticCode{System.out.println;} //静态代码块给类初始化/①static {System.out.println;}//构造代码块给对象初始化②{System.out.println;}//构造函数给对应对象初始化的③StaticCode{System.out.println;}public static void show{System.out.println;}}class StaticCodeDemo{public static void main{new StaticCode;}}//结果a c d6-07对象的初始化过程。建立过程:Person1 p = new Person1;该句话都做了什么事情?1,因为 new用到了Person.class,所以会先找到Person.class文件并加载到内存中。2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化。3,在堆内存中开辟空间。分配内存地址。4,在堆内存中建立对象的特有属性,并进行默认初始化。5,对属性进行显示初始化。6,对对象进行构造代码块初始化。7,对对象进行对应的构造函数初始化。8,将内存地址赋值给栈内存中的p变量。class Person1{private String name;private int age;private static String country = "cn";Person1{this.name = name;this.age = age;}public void setName{this.name = name;}public void speak{System.out.println;}public static void showCountry{System.out.println;}}class PersonDemo {public static void main{Person1 p = new Person1;}}6-08对象调用成员过程备注一下哈,静态所属的是类,非静态所属的是this!!!!就这么回事0.06-09单例设计模式一设计模式:解决某一类问题最行之有效的方法。Java中有23中设计模式单例设计模式:想要保证对象唯一。1,为了避免其它程序过多建立该类对象。先控制禁止其它程序建立该类对象2,还为了让其它程序可以访问到该类对象,只好在本类中自定义一个对象。3,为了方便其它程序对自定义对象的访问,可以对外提供一些访问方式。代码体现:1,将构造函数私有化。2,在类中创建一个本类对象。3,提供一个方法可以获取该对象。对于事物该怎么描述,还怎么描述。当需要将该事物的对象保证在内存中唯一时,就将以上的三步加上class Single{private Single{}private static Single s = new Single;public static Single getInstance{return s;}}class SingleDemo {public static void main{Single sss = Single.getInstance;}}再举个例子class Student{private int age;//第一步 private Student{}//第二步 private static Student s = new Student;//第三步 public static Student getStudent{reutrn s;}public void setAge{this.age = age;}public int getAge{return age;}}class SingleDemo {public static void main{//这俩是一个对象0.0Single ss1 = Student.getStudent;Single ss2 = Student.getStudent;}}//饿汉式的特点:Single类一进内存就已经创建对象了!!开发时候一般用饿汉式!!6-09单例设计模式二//对象是方法被调用时,才初始化,也叫做对象的延时加载。成为:懒汉式。//Single类进内存,对象还没有存在,只有在调用getInstance方法时,才建立对象。class Single{private static Single s = null;private Single{}//我上一个锁在static后面添加synchronized,一次只执行一次。但是效率就变低了public static Single getInstance{//最终解决方案/* if* {* Synchronized* {* if* {* s = new Single;* }* }* return s;* }*/ifs = new Single;return s;}}//!!!记录原则:定义单例时,饿汉式。面向对象第二个特征-继承7-01继承好处:1,提高了代码的复用性。2,让类与类之间产生了关系,有了这个关系,才有了多态的特性。注意:千万不要为了获取其他类的功能,简化代码而继承;必须是有类与类之间有所属关系才可以继承。所属关系is aeg:class Person{String name;int age;}class Student extends Person{void study{System.out.println;}}7-02继承-如何进行判断呢?如果不确定的话,就继承一下,判断一下是否是父类当中的所有元素都应该是子类应该有的。如果父类中有的元素不是子类的话,那么,就不应该有继承。Java语言当中:java只支持但集成,不支持多继承。因为多继承容易带来安全隐患:当多个父类定义了相同功能,因为功能不同,所以不确定运行哪一个。但是java保留这种机制。并用另一种体现形式来完成表示,多实现。java支持多层继承。A extends B extends C也就是说一个继承体系。如何实用哦一个继承体系中的功能呢?想要使用体系,先查阅体系父类的描述,因为父类中定义的是该体系中的共性功能。通过了解共性功能,就可以知道该体系的基本功能。那么这个体系基本就可以使用了。那么在具体调用时,要创建最子类的对象,为嘛呢??一是因为有可能父类不能创建对象,二是创建子类对象可以使用更多的功能,包括基本的,也包括特有的。简而言之:查阅弗雷功能,创建子类对象使用功能。7-03面线对象-聚焦关系聚集:has a聚合:球员与球队的关系。组合:7-04子父类中变量的特点。新关键字:super例如:this.numsuper.numpackage Demo;/*** 子父类出现后,类成员的特点:* 类中成员:* 1,变量* 2,函数* 3,构造函数*1,变量:如果子父类中出现了非私有的同名成员变量时,子类要访问本类中的变量,用this,子类要访问父类中的同名变量,用super*this的使用和super的使用几乎一致**/class Fu{int num = 4;}class Zi extends Fu{//int num = 5;void show{System.out.print;} }class ExtendsDemo2 {public static void main{Zi z = new Zi;z.show;}}//输出的是47-05面向对象2,子父类中的函数.特点:当子类出现和父类一模一样的函数时,当子类对象调用该函数,会运行子类函数的内容。如同父类的函数被覆盖一样。这中情况是函数的另一个特性,重写当子类继承了父类,沿袭了父类的功能到子类中。但是子类虽有该功能,但是功能的内容却和父类不一致。这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义并重写功能内容。覆盖:1,子类覆盖谷类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。2,静态只能覆盖静态。//覆盖class Tel{ void show{System.out.println;} }class NewTel extends Tel{void show{//System.out.println;super.show;System.out.println;System.out.println;}}!!!!记住大家:重载:只看同名函数的参数列表。重写:子父类方法要一模一样7-06子父类中构造函数的特点-子类实例化过程3,子父类构造函数特点:在对子类对象进行初始化时,父类的构造函数也会运行。那是因为子类的构造函数,默认第一行有一条隐式的语句,super;super;会访问父类中空参数的构造函数;而且子类中所有的构造函数默认第一行都是super;为什么子类一定要访问父类中的构造函数?因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。所以,子类在对象初始化时,要现访问一下父类中的构造函数。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式指定。注意:super语句一定要放在子类构造函数的第一行。子类的实例化过程:结论:子类的所有构造函数默认都会访问父类中空参数的构造函数;因为子类的每一个构造函数内都有一句隐式的super。当父类中没有空参数的构造函数时,子类必须手动通过super或者this语句形势来指定要访问的构造函数。当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。子类中至少会有一个构造函数会访问父类中的构造函数。class Fu4 //extends Object{Fu4{System.out.println;}}class Zi4 extends Fu4{Zi4{//super;System.out.println;}}class ExtendsDemo4 {public static void main{Zi4 z = new Zi4; }}//fu run //Zi run7-07final 关键字1,可以修饰累,函数,变量2,被final修饰的类不可以被继承.为了避免被继承,被子类复写功能。3,被final修饰的方法不可被覆写 4,被final修饰的变量是一个常量,只能赋值一次。既可以修饰成员变量,也可以修饰局部变量。当在描述事物时,一些数据的出现,值是固定的。那么这时为了增强阅读性,都给这些值起个名字。方便阅读。而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所有字母都大写,如果多个单词组成,单词通过_连接。5,内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。7-08继承的下半部分--抽象类1当多个类中出现相同功能,但是功能主体不同,这时可以进行向上抽取,这时只抽取功能定义,而不抽取功能主体。注意哈,抽象方法必须放在抽象类当中.抽象:看不懂0.0抽象类的特点:1,抽象方法一定定义在抽象类当中2,抽象方法和抽象类都必须被abstract关键字所修饰3,抽象类不可以用new创建对象,因为调用抽象方法没意义。4,抽象类中的抽象方法要被使用,必须由子类覆写其所有的抽象方法后,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。abstract class Student{ abstract void study;}class BaseStudent extends Student{void study{System.out.println;}}class AdvStudent extends Student{void study{}{System.out.println;}}class AbstractDemo{public static void main{ }}7-09继承的下半部分--抽象类2抽象类和一般类没有太大的不同。该如何描述事物,就如何描述事物。只不过该事物出现了一些看不懂的东西。这些不确定的部分,也是该实物的功能,需要明确出来,但是无法定义主体。通过抽象方法来表示。抽象类比一般类多了个抽象函数,就是在类中可以定义抽象方法,抽象类不可以实例化。特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。7-10抽象类-练习package Test;/* 假如我们在开发一个系统时需要对员工进行建模,员工包括3个属性:* 姓名、工号、以及工资,经理也是员工,除了含有员工的属性外,另外还有* 奖金属性。请使用继承的思想设计出员工类和经理类。要求类中提供必要的* 方法进行属性访问。* 分析:* 员工类:name id pay* 经理类:继承了员工,并有自己特有的奖金属性*///定义员工都有的属性abstract class Employee{@SuppressWarningsprivate String name;@SuppressWarningsprivate String id;@SuppressWarningsprivate double pay;//直接在构造函数中初始化Employee{this.name = name;this.id = id;this.pay = pay;}public abstract void work;}//定义普通员工class Pro extends Employee{Pro{super;}public void work{System.out.println;}}//定义经理class Manager extends Employee{@SuppressWarningsprivate int house;Manager{super;this.house = house;}public void work{System.out.println;}}//主函数class Test {public static void main{ }}7-11模版设计模式。当代码完成优化,就可以解决这类问题。这种方式:模版设计模式。什么是模版方法呢?在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,那么这时候将不确定的部分暴露出去,由该类的子类去完成。既可以提高扩展性,又提高复用性。package Demo;/*** 需求:获取一段程序运行的时间* 原理:获取程序开始与结束的时间并相减即可。* 获取时间:System.currentTimeMillis*/abstract class GetTime{//定义一个固定的方法final void gettime{long start = System.currentTimeMillis;code;long end = System.currentTimeMillis;System.out.println);}//定义一个必须覆写的不确定函数public abstract void code;}//子类继承父类,覆写抽象类class SubTime extends GetTime{public void code{for{System.out.print;}}}//主函数class TemplateDemo {public static void main{SubTime time = new SubTime;time.gettime;}}7-12接口1初期理解,可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口定义时,格式特点:1,接口中常见定义,常量,抽象方法。2,接口中的成员都有固定修饰符。常量:public static final方法:public abstract记住:接口中的成员都是public的。eg;interface Inter{public abstract void show;}接口:是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口的抽象方法全部覆盖后,子类才可以实例化。否则子类是一个抽象类。7-13接口2接口可以被类多实现,也是对多继承不支持的转换形势,Java支持多实现一个类在继承一个类之后也能实现多个接口.7-14接口的特点1,对外暴露的规则;2,程序的功能扩展;3,可以用来多实现;4,类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。5,接口与接口之间可以有继承关系。7-15实例举例:abstract class Sporter{abstract void play;}interface Study{}class LiSi extends Sporter implements Study{}8-01-02面向对象特征3-多态事物存在的多种体现形态。比如:人:男人,女人。动物:猫,狗。再比如:猫 x = new 猫;动物 x = new 猫;1,多态的体现父类的引用指向了自己的子类对象父类的引用也可以接收自己的子类对象。2,多态的前提必须是类与类之间有关系,要么继承,要么实现.通常还有一个前提:存在覆盖。3,多态的好处多态的出现,大大的提高了程序的扩展性。4,多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员。5,多态的应用6,多态的出现代码中的特点在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,便用通过;如果没有,编译失败。在运行时期:参阅对象所属的类中是否有调用的方法。总结:成员函数在多态调用时,编译看左边,运行看右边。在多态中,成员变量的特点:无论编译和运行,都参考左边在多态中,静态成员函数的特点:无论编译和运行,都参考左边8-02多态的体现package Demo;abstract class Animal{public abstract void eat;}//猫class Cat extends Animal{public void eat{System.out.println;}public void catchMouse{System.out.println;}}//狗class Dog extends Animal{public void eat{System.out.println;}public void kanJia{System.out.println;}}//猪class Pig extends Animal{public void eat{System.out.println;}public void gongDi{System.out.println;}}//主函数class DuoTaiDemo {public static void main{function;function;function;}public static void function{a.eat;}}8-03/**介绍个新的关键字*用法if//判断a是否是猫*{}*/多态-转型多态自始至终都是子类对象做着变化。......class DuoTaiDemo{public static void main{//Animal a = new Cat;//类型提升,向上转型//a.eat;//如果想要调用猫的特有方法时,如何操作?//强制将父类的引用转成子类类型,向下转型.//Cat c = a;//c.catchMouse;//这样不行:将父类对象转成子类类型.//Animal a = new Animal;//Cat c = ;//我们能转换的是父类引用指向了自己的子类对象时,该对象可以被提升,也可以强制向下转型。function;}public static void function{a.eat;if{Cat c = a;c.catchMouse;}else if{Dog c = a;c.kanJia;}else if{Pig c = a;c.GongDi;}}}8-04多态-示例/*** 基础班学生:* 学习,睡觉* 高级班学生:* 学习,睡觉* 可以将这两类实物进行抽取。*///学生共有的属性abstract class Student{public abstract void study;public void sleep{System.out.println;}}//基础班学生class BaseStudent extends Student{public void study{System.out.println;}public void sleep{System.out.println;}}//高级班学生class AdvStudent extends Student{public void study{System.out.println;}}//创建一个工具类,实现方法class DoSome{public void doSome{stu.sleep;stu.study;}}//主函数class DuoTaiDemo4 {public static void main{DoSome ds = new DoSome;ds.doSome;ds.doSome;}}8-05多态中成员的特点在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,便用通过;如果没有,编译失败。在运行时期:参阅对象所属的类中是否有调用的方法。总结:成员函数在多态调用时,编译看左边,运行看右边。在多态中,成员变量的特点:无论编译和运行,都参考左边在多态中,静态成员函数的特点:无论编译和运行,都参考左边8-06多态的主板示例package Test;/* 需求:电脑运行示例。* 电脑运行基于主板。* 主板上有多个PIC插槽,可以进行网卡,声卡等的扩展。*///定义一个PCI接口interface PCI{public void open;public void close;}//主板class MainBoard{//主板泡一下public void run{System.out.println;}//PCI插槽public void usePci{//判断插槽是不是空的if{p.open;p.close;}}}//来个网卡class NetCard implements PCI{public void open{System.out.println;}public void close{System.out.println;}}//再来一个声卡class SoundCard implements PCI{public void open{System.out.println;}public void close{System.out.println;}}//主函数class DuoTaiTest5 {public static void main{MainBoard mb = new MainBoard;mb.run;mb.usePci;mb.usePci;}}8-07多态的扩展示例package Demo;/*需求:数据库的操作。*数据是:用户信息 *1,连接数据库。JDBC Hibername*2,操作数据库*3,关闭数据库*///定义一个接口桥接操作数据库层与主程序interface UserInfoDao{public void add;public void delete;}//假设是JDBC型的class UserByJDBC implements UserInfoDao{public void add{System.out.println;//1,连接数据库//2,操作数据库//3,关闭数据库}public void delete{System.out.println;//1,连接数据库//2,操作数据库//3,关闭数据库 }}//假设是Hibernate的class UserByHibernate implements UserInfoDao{public void add{System.out.println;//1,连接数据库//2,操作数据库//3,关闭数据库}public void delete{System.out.println;//1,连接数据库//2,操作数据库//3,关闭数据库 }}//主程序class DBOperate {public static void main{UserInfoDao ui = new UserByJDBC;//UserInfoDao ui = new UserByHibernate;ui.add;ui.delete;}}8-08Object类-equalsJava认为所有的对象都能进行比较。object:是所有对象的直接后者间接父类,传说中的上帝。该类中定义的肯定是所有对象都具备的功能。object类中已经提供了对对象是否相同的比较方法。如果自定义类中也有比较相同的功能,没有必要重新定义。只要沿袭父类中的功能,建立自己特有的比较内容即可,这就是覆盖。//对比Demo与Demo是否相同//并且对比DemoPerson是否相同class Demo{private int num;Demo{this.num = num;}public boolean equals{//进行判断类型是否是Demo的if)return false;Demo d =obj;return this.num == d.num;}}class Person{@SuppressWarningsprivate int num;Person{this.num = num;}}//主函数class ObjectTest {public static void main{Demo d1 = new Demo;Demo d2 = new Demo;//进行判断是否相同System.out.println);Person p = new Person;System.out.println);}}8-09toStringJava认为所有类型都能用字符串来打印。//getClass.getName + '@' + Integer.toHexStringclass Demo{private int num;Demo{this.num = num;}public boolean equals{//进行判断类型是否是Demo的if)return false;Demo d =obj;return this.num == d.num;}}class ObjectDemo{public static void main{Demo d = new Demo;Class c = d1.getClass;System.out.println;System.out.println);//上面的打印结果跟下面一样System.out.println;}}说明了啥呢,说明了好多定义的方法都有可能要被覆写。9-01-02内部类将一个类定义在另一个类的里面,对里面那个类成为内部类访问特点:1,内部类可以直接访问外部累的成员,包括私有成员。原因:之所以可以直接访问外部类中的成员,是因为内部类中持有了外部类的引用。格式:外部类名.this2,而外部累要访问内部类中的成员必须要建立内部类的对象访问格式:当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。可以直接建立内部类对象。格式:外部类名.内部类名 变量名 = 外部类名.内部类对象;Outer.Inner oi = new Outer.new Inner;当内部类在成员位置上,就可以被成员修饰符所修饰,比如:private,将内部类在外部类中进行封装static:内部类就具备了静态的特性当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。在外部其他类中,如何直接访问内部static类中的非静态成员呢?new Outer.Inner.function;在外部其他类中,如何直接访问内部static类中的静态成员呢?Outer.Inner.function;注意:当内部类中定义了静态成员,该内部类必须是static的。当外部类中的静态方法访问内部类时,内部类也必须是static的。class Outer{int num = 3;class Inner//内部类{int num = 4;void function{ int num = 5;System.out.println;//num5,this.num4,Outer.this.num3}}void method{Inner in = new Inner;in.function;}}class InnerClassDemo {public static void main{Outer.Inner oi = new Outer.new Inner;oi.function;}}9-03内部类定义原则当描述事物时,事物的内部还有事物,该事物用内部类来表述。因为内部事务在使用外部实物的内容。class Body{class XinZang{void tiaodong{System.out.println;}}public void show{XinZang xz = new XinZang;xz.tiaodong;}}class Person{public static void main{Body s = new Body;s.show;}}注意了哈:局部内部类是不能定义静态成员的。内部类定义在局部时,,1,不可以被成员修饰符修饰2,可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它锁在的局部中的变量。只能访问被final修饰的局部变量。class Outer{int x = 3;void method{//不可以new Inner.function;因为下面还没有读到呢。int y = 4;class Inner{void function{//想要输出a,y都要定义成final类型的变量System.out.println;}}new Inner.function;}}class InnerClassDemo3 {public static void main{new Outer.method;}}9-04匿名内部类1,匿名内部类其实就是内部类的简写形势2,定义匿名内部类的前提:内部类必须继承一个类或者实现接口3,匿名内部类的格式:new 父类或者接口{定义子类的内容}4,其实匿名内部类就是一个匿名子类对象,而且这个对象有点胖,也可以理解为带内容的对象.5,一般匿名内部类的方法为一个或者两个,最好不会有第三个abstract class AbsDemo{abstract void show;}class Outer{int x = 3;/*把这部分进行简化class Inner extends AbsDemo{void show{System.out.println;}}*/public void function{//以及这部分进行简化//new Inner.show; //从这里开始,就是匿名内部类,相当于上面的简化//这个整体,是一个对象,是AbsDemo的子类对象// AbsDemo a = new AbsDemo//把下面这行换成这行new AbsDemo{void show{System.out.println;}void abc{System.out.println;}}.show;//一直到这里结束//a.show;//这个是可以的//a.abc;//这个是不可以的,因为多态,起名字的时候起的是父类的,但是父类中没有这个方法,所以编译失败} }class InnerClassDemo4{public static void main{Outer o = new Outer;o.function; }}//小练习题:interface Inter{void method;}class Test{//补足代码,用匿名内部类的方法}class InnerClassTest {public static void main{Test.function.method;}}解答:interface Inter{void method;}class Test{//补足代码,通过匿名内部类/* //非匿名类方法* static class Inner implements Inter* {* public void method* {* System.out.println;* }* }* static Inter function* {* return new Inner;* }*///接下来是匿名内部类,static是因为主函数中类调用Inter类型的哦。static Inter function{return new Inter{public void method{System.out.println;}};}}class InnerClassTest {public static void main{//Test.function;Test类中有一个静态的方法function.//.method;function这个方法运算后的结果是一个对象。而且是一个Inter类型的对象//因为只有是Inter类型的对象,才可以调用method方法Test.function.method;}}9-05异常概述异常:就是程序在运行时出现不正常情况。异常的由来:问题也是现实生活中一个具体事物,也可以通过java的类的形式进行描述。并进行封装。其实就是java对不正常情况进行描述后的对象体现。对于问题的划分:两种,一种是严重的问题;一种是非严重的问题。对于严重的问题:java通过Error类进行描述。对于error一般不编写针对性的代码对其进行处理。对于非严重的问题:java通过Exception类进行描述对于Exception可以使用针对性的处理方式.无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。Throwable!--Error!--Exception9-06异常处理java提供了特有的语句进行处理try{需要被检测的代码:}catch{处理异常的代码:}finally{一定会执行的语句;}3,对捕获到的异常进行常见方法操作e.getMessage;//获取异常信息.e.toString;//异常名称: 异常信息e.printStackTrace;//异常名称,异常信息,异常出现的位置//其实jvm默认的异常处理机制,就是在调用printStackTrace打印异常在堆栈中的异常信息错误代码如下:class Demo{int div{return a/b;}}class ExceptionDemo {public static void main{Demo demo = new Demo;int x = demo.div;System.out.println;System.out.println;}}修改代码如下:class Demo{int div{return a/b;}}class ExceptionDemo {public static void main{Demo demo = new Demo;try{int x = demo.div;System.out.println;}catch//Exception e = new ArithmeticException;{System.out.println;System.out.println;// / by zeroSystem.out.println;//异常名称: 异常信息e.printStackTrace;//异常名称,异常信息,异常出现的位置//其实jvm默认的异常处理机制,就是在调用printStackTrace打印异常在堆栈中的异常信息}System.out.println;}}9-07异常声明throwsclass Demo1{int divthrows Exception//在功能上通过throws的关键字声明了一下,该功能有可能会出现问题.{return a/b;}}class ExceptionDemo1 {public static void main//throws Exception{Demo1 d = new Demo1;try{int x = d.div;System.out.println;}catch{System.out.println;}System.out.println;}}9-08多异常处理1,声明异常时,建议声明更为具体的异常。这样处理的更具体。2,对方声明几个异常,就对应几个catch块,不要定义多余的catch块如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面建议在进行catch处理时,catch中一定要定义具体处理方式。一定不要简单定义一句e.printStackTrace也不要简单的就写一句输出语句class Demo2{int divthrows ArithmeticException,ArrayIndexOutOfBoundsException//在功能上通过throws的关键字声明了一下,该功能有可能会出现问题.{int arr = new int;System.out.println;return a/b;}}class ExceptionDemo2 {public static void main{Demo1 d = new Demo1;try{int x = d.div;System.out.println;}catch{System.out.println;}catch{System.out.println;}catch {e.printStackTrace;}System.out.println;}}9-09自定义异常因为项目中会出现特有的问题, 而这些问题,并未被java所描述并封装对象。所以对这些特有的问题,可以按照java对问题封装的思想将特有的问题进行自定义的异常封装.package Demo;/*** 在本程序中,对于除数是-1,也视为是错误的,是无法进行运算的。* 那么就需要对这个问题进行自定义描述.* * 当在函数内部出现了throw抛出异常对象,那就必须给出对应的处理动作* 1,要么在内部try catch处理* 2,要么在函数上声明让调用者处理。* * 一般情况下,函数内出现异常,函数上需要声明。* * 发现打印的结果中只有异常的名称,却没有异常的信息。* 因为自定义的异常并未定义信息.* * 如何定义异常信息呢?* 因为父类中已经把异常信息的操作都完成了。* 所以子类只需要在构造时,将异常信息传递给父类通过super语句。* 那么就可以通过getMessage方法获取自定义的异常信息.* * 自定义异常:* 必须是:自定义类继承Exception* * 继承Exception的原因:* 异常体系特点:因为异常类和异常对象都需要被抛出。* 它们都具备可抛性,这个可抛性是Throwable这个体系中的独有特点。* 只有这个体系中的类和对象才可以被throws和throw操作.* */class FuShuException extends Exception{private int value;FuShuException{super;}//打印错误内容FuShuException{super;this.value = value;}public int getValue{return value;}}/*如何定义异常信息呢?具体可以参考如下*class Person*{* private String name;* Person* {* this.name = name;* }* public String getName* {* return name;* }*}*class Student extends Person*{* Student* {* super;* }*}*/class Demo3{int divthrows FuShuException{ifthrow new FuShuException;//手动通过throw关键字抛出异常对象return a/b;}}class ExceptionDemo3 {public static void main{Demo3 d = new Demo3;try{int x = d.div;System.out.println;}catch{System.out.println;//System.out.println;System.out.println;}}}9-10throws与throw的区别throws使用在函数上,throw使用在函数内throws后面跟的是异常类,可以跟多个,用逗号隔开.throw后面跟的是异常对象9-11RuntimeExceptionException有一个特殊的子类异常RuntimeException如果在函数内抛出该异常,函数上,可以不用声明,编译一样通过。如果在函数上声明了该异常,调用者可以不用进行处理,编译一样进行通过。之所以不用在函数上声明,是因为不需要让调用者处理。当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后由程序猿对代码进行修正。自定义异常时,如果该异常的发生,无法再继续进行运算,就让自定义的异常继承RuntimeException对于异常分两种:1,编译时被检测的异常。2,编译时不被监测的异常class FuShuException1 extends RuntimeException{FuShuException1{super;}}class Demo5{int div//throws ArithmeticException{ifthrow new FuShuException1;ifthrow new ArithmeticException;return a/b;}}class ExceptionDemo4 {public static void main{Demo5 d5 = new Demo5;int x = d5.div;System.out.println;}}9-12异常练习package Test;/** 毕老师用老师上课* 开始思考上课中上课的问题* 比如问题是:* 电脑蓝屏* 电脑冒烟* 要对问题进行描述,封装成对象。* * 可是当冒烟发生后,出现讲课进度无法继续。* 出现了讲师的问题:课时计划无法完成.*///蓝屏class LanPingException extends Exception{LanPingException{super;}}//冒烟class MaoYanException extends Exception//RuntimeException{MaoYanException{super;}}//电脑class NoPlanException extends Exception{NoPlanException{super;}}class Computer{//定义一个状态1正常状态,2异常状态private int state = 3;public void runthrows LanPingException,MaoYanException{ifthrow new LanPingException;ifthrow new MaoYanException;System.out.println;}public void reset{state = 1;System.out.println; }}//老师class Teacher{private String name;private Computer cmpt;//初始化Teacher{this.name = name;cmpt = new Computer;}//讲课方法public void prelectthrows NoPlanException{try{cmpt.run;}catch{cmpt.reset;}catch{test;throw new NoPlanException;}System.out.println;}public void test{System.out.println;}}class ExceptionTest {public static void main{Teacher t = new Teacher;try{t.prelect;}catch{System.out.println;System.out.println;}}}10-01异常-finallyfinally中是一定会执行的代码通常用于关闭资源比如:class NoException extends Exception{NoException{super;}}public void methodthrows NoException{try{连接数据库;数据库操作;//throw new SQLException;}catch{会对数据库数据进行异常处理;throw new NoException;}finally{关闭资源;}}10-02异常-处理语句其他格式cathch是用于处理异常的,如果没有 catch就代表异常没有被处理过,如果该异常是检测异常,就必须被声明。第一个格式:try{}catch{}第二个格式:try{}catch{}finally{}第三个格式try{}flnally{}第四个格式try{}catch{}catch{}....异常小处理Demo1~Demo4class Demo1{public void method//编译失败,因为异常抛出去了,所以这里要加上throws Exception{throw new Exception;}}class Demo2//编译通过,因为在方法内部问题直接被解决了{public void method{try{throw new Exception;}catch{}}}class Demo3{public void method{try{throw new Exception;}catch//编译失败,因为又把异常往外抛{throw e;}}}class Demo4//编译又通过了0.0,因为异常又被处理了。{public void method{try{throw new Exception;}catch{try{throw e;}catch{}}}}好,看了上面的4个小例子,下面继续讲解-_-class Demo{public void method//这里必须被声明!!添加:throws Exception{try{throw new Exception;}finally{//关闭资源,一定要执行的代码}}}10-03异常-覆盖时的异常特点1,子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类Exception!--AException!--Bexception!--CException这个时候如果B出现问题了,只能抛B,或者A异常,不能抛出C异常2,如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。3,如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常,就必须进行try处理!!绝对不能抛10-04练习package Test;/** 有一个圆形和长方形。* 都可以获取面积,对于面积,如果出现非法的数值,视为获取面积出现问题。* 问题通过异常来表示.* 先要对这个程序进行基本设计* *///如果出现错误的话,抛出异常,由于错误是用户造成的,所以继承RuntimeException,直接跳出@SuppressWarningsclass NoValueException extends RuntimeException{NoValueException{super;}}//定义一个接口,面积interface Shape{void getArea;}//长方形面积class Rec implements Shape{private int len,wid;Rec{ifthrow new NoValueException;this.len = len;this.wid = wid;}public void getArea{System.out.println;}}//园的面积class Circle implements Shape{private double radius;//因为PI是常量,可以定义为全局最终常量public static final double PI = 3.14;Circle{//如果判断一下,如果错误的话,就抛出去ifthrow new NoValueException;this.radius = radius;}public void getArea{System.out.println;}}//主函数class ExceptionTest1 {public static void main{Rec rec = new Rec;rec.getArea;Circle circle = new Circle;circle.getArea;System.out.println;}}10-05异常-总结:异常是啥呢?是对问题的描述.将问题进行对象的封装。异常体系:Throwable|--Error|--Exception|--RuntiomeException异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性.也就是说可以被throw和throws关键字所操作.只有异常体系具备这个特点。throw和throws的用法:throw定义在函数内,用于抛出异常对象throws定义在函数上,用于抛出异常类,可以抛出多个异常用逗号隔开。当函数内容有throw抛出异常对象,并未进行处理,必须在函数上进行声明,否则编译失败!!注意:RuntimeException异常除外,如果函数内抛出的是RuntimeException函数上可以不用声明异常如果函数声明了异常,调用者需要进行处理。处理方式:可抛可try异常有两种:编译时被检测异常;该异常在编译时如果没有处理,结果就是编译失败;该异常被标识,代表可以被处理。运行时异常在编译时,不需要处理,编译器不检查。该异常的发生,建议不处理,让程序停止,需要对代码进行修正。异常处理的语句:try{需要被检测的代码;}catch{处理异常的代码;}finally{一定被执行的代码;}三个格式第一个格式:try{}catch{}第二个格式:try{}catch{}finally{}第三个格式try{}flnally{}!!注意:1,finally中定义的通常是 关闭资源代码,因为资源必须释放。2,只有这种形式finally读不到,System.exit; 系统,退出。jvm结束,finally就读不到了自定义异常:定义类继承Exception或者RuntimeException1,为了让该自定义类具备可抛性;2,让该类具备操作异常的共性方法。当要定义自定义异常的信息时,可以使用父类已经定义好的功能。将异常信息传递给父类的构造函数class MyException extends Exception{MyException{super;}}自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。异常的好处:1,讲问题进行封装;2,将正常流程代码和问题处理代码相分离,方便于阅读。异常的处理原则:1,处理方式有两种:try或者throws2,调用到抛出异常的功能时,抛出几个,就要处理几个。一个try对应多个catcp,多个catch,父类的catch放在最下面4,catch内需要定义针对性的处理方式,不要简单的定义printStackTrace、输出语句.也别不写.当捕获到的异常,本功能处理不了时,可以继续在catch中抛出try{throw new AException;}catch{throw e;}如果该异常处理不了,并不属于该功能出现的异常。可以将异常转换后,再抛出和该功能相关的异常。或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,当调用者知道,并处理。也可以将捕获处理后转换成新的异常.try{throw new AException;}catch{//对AException处理。throw new BException;}比如:汇款的例子try{汇款没有成功//throw new AException;}catch{ATM机把汇的钱又吐出来了//对AException处理。告诉人汇钱没有成功//throw new BException;}异常的注意事项:在子父类覆盖时:1,子类抛出的异常必须是父类异常的子类或者子集2,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛ExceptionTest.java ExceptionTest1.java10-06练习0.01.写出程序运行结果class Dmeo{public static void func{try{throw new Exception;}finally{System.out.println;}}public static void main{try{func;System.out.println;}catch{System.out.prinltn;}System.out.println;}}答:编译不通过,需要在func函数后加上throws Exception加上之后的运行结果是B C D2.写出运行结果class Test{Test{System.out.println;}}class Demo extends Test{Demo{//默认有一个空参数的构造函数super;System.out.println;}public static void main{new Demo;new Test;}}答:Test Demo Test3.写出程序结果interface A{}class B implements A{public String func{return "func";}}class Demo{public static void main{A a = new B;System.out.println;}}答:编译失败,因为A接口中没有并未定义func方法.4.写出程序结果class Fu{boolean show{System.out.prinltn;return true;}]class Demo extends Fu{public static void main{int i = 0;Fu f = new Demo;Demo d = new Demo;for;f.show&&;f.show){i++;d.show;}}boolean show{System.out.println;return false;}}答:A B 5写出程序运行结果interface A{}class B implements A{public String test{return "yes";}}class Demo{static A get{return new B;}public static void main{A a = get;System.out.println;}}答:编译失败.因为A接口中没有定义test方法6. 写成程序运算结果class Super{int i = 0;public Super{System.out.println;i = 1;}public Super{System.out.println;i+=2;}}class Demo extends Super{public Demo{//super;这是没有参数的,所以i赋值为2System.out.println;i=5;}public static void main{int i = 4;Super d = new Demo;System.out.println;}}答:B C 57.interface Inter{void show;void func;}class Demo{public static void main{//补足代码,调用两个函数,要求用匿名内部类//代码.......}}答:代码如下:Inter in =new Inter{//权限要足够大publicpublic void show{}public void func{}};in.show;in.func;8写出程序结果class TD{int y = 6;class Inner{static int y = 3;void show{System.out.println;}}}class TC{public static void main{TD.Inner ti = new TD.new Inner;ti.show;}}答:编译失败,非静态内部类中不可以定义静态成员内部类如果定义了静态成员,该内部类一定被静态修饰.9.选择题,写出错误答案错误的原因。用单行注释的方式。class Demo{int show{return 0;}}下面哪些函数可以存在与Demo的子类中。A.public int show{return 0;}//可以,覆盖。B.private int show{return 0;}//不可以,权限不够C.private int show{return 0;}//可以,和父类不是一个函数,没有覆盖。相当于重载D.public short show{return 0;}//不可以,因为该函数不可以和给定函数出现在同一类中,或者子父类中E.static int show{return 0;}//不可以,静态只能覆盖静态。10.写出this关键字的含义,final有那些特点?答:this:表示本类对象.哪个对象调用this对象所在的函数,this就代表哪个对象。final:1,修饰类,变量,函数.2,修饰的类不可以被继承。3,修饰的函数不可以被覆盖。4,修饰的变量是一个常量,只能赋值一次。5,内部类只能访问局部中的final修饰局部变量11.写出运算结果class Fu{int num = 4;void show{System.out.println;}}class Zi extends Fu{int num = 5;void show{System.out.println;}}class T{public static void main{Fu f = new Zi;Zi z = new Zi;System.out.println;System.out.println;f.show;z.show;}}答:4 5 showZi showZi12.interface A{void show;}interface B{void add;}class C implements A,B{//程序代码//-----答//-----答private int a,b;public void add{this.a = a;this.b = b;}public void show{System.out.println;}//-----结束//-----结束}class D{public static void main{C c = new c;c.add;c.show;//通过该函数打印以上两个函数的和}}13写出程序结果class Demo{public static void main{try{showExce;System.out.println;}catch{System.out.println;}finally{System.out.println;}System.out.println;}public static void showExce throws Exception{throw new Exception;}}答:B C D14写出程序结果class Super{int i = 0;//改:这里可以加一行Super{}public Super{i = 1;}}class Demo extends Super{public Demo{i = 2;}public static void main{Demo d = new Demo;System.out.println;}}//编译失败,因为父类中缺少空参数的构造函数。//或者子类应该通过super语句指定要调用的父类中的构造函数.15写出程序结果class Super{public int get{return 4;}}class Demo15 extends Super{public long get{return 5;}public static void main{Super s=new Demo15;System.out.println;}}答:编译失败,因为子父类中的get方法没有覆盖,但是子类调用的时候不恩那个明确返回的值是谁。所以这样的函数不可以存在子父类中。16写出程序运行结果:class Demo{public static void func{try{throw new Exception;//记住throw单独存在时,下面不要定义语句,执行不到System.out.println;}catch{System.out.println;}}public static void main{try{func;}catch{System.out.println;}System.out.println;}}//编译失败,因为打印字符串A的执行语句执行不到//记住throw单独存在时,下面不要定义语句,执行不到17class Demo{public void func{//位置1;}class Inner{}public static void main{Demo d = new Demo;//位置2}}A.在位置1写 new Inner;//对的。B.在位置2写 new Inner;//不对,因为主函数是静态的,如果要访问,Inner需要被静态修饰C.在位置2写 new d.Inner;//格式错误 new new Demo.Inner;D.在位置2写 new Demo.Inner;//错误,因为inner不是静态的。18写出程序结果class Exc0 extends Exceptionclass Exc1 extends Exc0{}class Demo{public static void main{try{throw new Exc1;}catch{System.out.println;}catch{System.out.println;}}}//编译失败,因为多个catch时,父类的catch要放在下面19interface Test{void func;}class Demo{public static void main{//补足代码:}void show{t.func;}}答//因为show方法是静态的 所以new Demo.new Demo.show;20.写出程序结果class Test{public static String output="";public static void foo{try{ifthrow new Exception;output+="1";}catch{output+="2";return;}finally{output+="3";}output+="4";}public static void main{foo;System.out.println;foo;System.out.println;}}//1 3 4 // 1 3 4 2 321。10-4练习22.补足compare函数内代码.不许添加其它函数.class Circle{private static double pi=3.14;private double radius;public Circle{radius = r;}public static double compare{//程序代码//其实就是在求数组中的最大值}}class TC{public static void main{Circle cir = new Circle;//创建了一个类类型数组.cir = Circle;cir = Circle;cir = Circle;System.out.println);}}答:int max = 0;//或者double max = cir.radius;for{ifmax = x;}return cir.radius;23写出程序结果public class Demo{private static int j = 0;private static boolean methodB{j += k;return true;}public staitc void methodA{boolean b;b = i < 10 | methodB;b = i < 10 || methodB;}public static void main{methodA;System.out.println;}}答:410-07包对类文件进行分类管理。给类提供多层命名空间。写在程序文件的第一行。类名的全称是:报名.类名包也是一种封装形式.javac -d . PackageDemo.java//这个样子编译java pack.PackageDemo//这个样子运行javac -d c:myclass PackageDemo.java//这样子就存在了c:myclass目录下set classpath=c:myclass//配置一下环境变量,也就是说只需要指向父目录即可.java PackageDemo10-08包与包之间的访问不同包之间的类该如何访问呢?总结:包与包之间进行访问,被访问的包中的类以及类中的成员需要public修饰。不同包中的子类还可以直接访问父类中被protected权限修饰的成员.包与包之间可以使用的权限只有两种,public protected.总结一下权限问题:①public②protected③④private同一个类中①②③④同一个包中①②③子 类①②不同 包中①protected保护权限10-09导入import为了简化类名的书写,使用一个关键字importimport导入的是包中的类import packb.haha.hehe.*;//这个样子是可以的import packb.haha.hehe.Demo2;//建议这样子写建议:不要写通配符*,需要用到包中的哪个类,就倒入哪个类.注意!!如果倒入多个包,类名前必须加包名eg:import packa.*;import packb.*;......packb.DemoC c = new packb.DemoC;......建议定义包名:不要重复,可以使用url来完成定义。url是唯一的。eg:package cn.itcast.demo;package cn.itcast.test;10-09jar包Java的压缩包举个小例子如果在目录下有packa与pack示例 1:将两个类文件归档到一个名为 classes.jar 的归档文件中:jar -cf classes.jar Foo.class Bar.class-c:创建.jar包-f:指定归档文件名查看:jar -tf haha.jar-t:列出归档目录C:Userstingzi>jar用法: jar {ctxui} files ...选项包括:-c 创建新的归档文件-t 列出归档目录-x 解压缩已归档的指定文件-u 更新现有的归档文件-v 在标准输出中生成详细输出-f 指定归档文件名-m 包含指定清单文件中的清单信息-e 为捆绑到可执行 jar 文件的独立应用程序指定应用程序入口点-0 仅存储;不使用任何 ZIP 压缩-M 不创建条目的清单文件-i 为指定的 jar 文件生成索引信息-C 更改为指定的目录并包含其中的文件如果有任何目录文件,则对其进行递归处理。清单文件名、归档文件名和入口点名的指定顺序与 "m"、"f" 和 "e" 标志的指定顺序相同。示例 1:将两个类文件归档到一个名为 classes.jar 的归档文件中:jar cvf classes.jar Foo.class Bar.class示例 2:使用现有的清单文件 "mymanifest" 并将 foo/ 目录中的所有文件归档到 "classes.jar" 中:jar cvfm classes.jar mymanifest -C foo/ .来个牛的:jar -tf a.jar >c:1.txt上面的命令就是把信息放到了C盘下的1.txt文件中11-01多线程进程:正在执行中的程序,每一个进程执行,都有一个执行的顺序。该顺序是一个执行路径,或者叫一个控制单元。线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行。一个进程中至少有一个线程.Java VM启动时会有一个进程java.exe.该进程至少一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。该线程称之为主线程。扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。好处:加快处理速度。打个比方:一个程序一大堆内容,如果是多线程的话,可以是一边执行,一边回收垃圾;如果是单线程的话,执行到一半,垃圾装不下了,就停掉进程,处理完垃圾继续回来执行,就慢了。。11-02创建线程-继承Thread类1,如果在自定义的代码中,自定义线程呢?通过对api的查找,java已经提供了对线程这类事物的描述。就是Thread类创建线程的第一种方式:继承Thread类.步骤:1,继承Thread类2,覆写Thread类中的run方法3,调用线程的start方法,该方法有两个作用:①启动线程②调用run方法发现运行结果每一次都不同。因为多线程都获取cpu的执行权。cpu执行到谁,谁就运行。明确一点:某一时刻,只能有一个程序在运行。cpu在做着快速切换。以打到看上去同时运行的结果。形象滴把多线程的运行比喻为:在互相抢夺cpu的执行权。这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多久,cpu说的算。package Demo;class Demo extends Thread{public void run{forSystem.out.println;}}class ThreadDemo1{public static void main{Demo d = new Demo;//其实定义了一个对象就创建好了一个线程d.start;//11-03开启线程并执行该线程的run方法。d.run;//11-03仅仅是对象调用方法。而线程创建了,并没有运行。forSystem.out.println;}}11-03创建线程run和start特点d.start;//开启线程并执行该线程的run方法。d.run;//仅仅是对象调用方法。而线程创建了,并没有运行。为啥要覆盖run方法呢?目的:将自定义代码存储在run方法中,让线程运行。Thread类用于描述线程。该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法也就是说Thread中的run方法,用于存储线程要运行的代码.11-04//创建两个线程,和主线程交替运行//线程Threadclass Thread1 extends Thread{private String name;Thread1{this.name = name;}public void run{for{System.out.println;}}}//main主线程class ThreadTest1 {public static void main{Thread1 t1 = new Thread1;t1.start;Thread1 t2 = new Thread1;t2.start; for{System.out.print;}}}11-05线程运行状态①被创建②运行③冻结状态④临时状态⑤消亡线程从①被创建→②运行是通过start②运行→⑤消亡,是通过stop或者run方法运行结束②运行→③冻结状态是通过sleep,冻结结束是因为time结束|休眠对应的是唤醒②有一个状态是:④临时状态,因为可能cpu没有运行,就是说有运行的资格,但是并没有执行权当然了③冻结状态,恢复到运行状态时,也不一定马上就能获得执行权,也可能转到④临时状态。11-06获取线程对象以及名称原来线程都有自己默认的名称。Thread-编号 该编号从0开始两种获取名称的方法static Thread currentThread:获取当前进程对象。getName:获取线程的名称设置线程名称:setName或者构造函数自定义名称:class Thread1 extends Thread{Thread1{super;}public void run{for{System.out.println;}}}//main主线程class ThreadTest1 {public static void main{Thread1 t1 = new Thread1;t1.start;Thread1 t2 = new Thread1;t2.start; for{System.out.print;}}}11-07售票的例子/** 需求:简单的买票程序* 多个窗口卖票*/class Ticket extends Thread{private int tick = 100;public void run{while{if{System.out.println;}}}}class TicketDemo {public static void main{Ticket c1 = new Ticket;//这是卖了400张票//Ticket c2 = new Ticket;//Ticket c3 = new Ticket;//Ticket c4 = new Ticket;c1.start;c1.start;c1.start;c1.start;}}11-08创建线程-实现Runable接口).步骤1,定义类实现Runnable接口2,覆盖Runnble接口中的run方法,将要实现的代码放在run方法当中3,通过Thread类建立线程对象.4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数.为什么要将Runnable接口的子类对象传递给Thread的构造函数。因为,自定义的run方法所属的对象是Runnable接口的子类对象所以要让线程去指定 指定对象的run方法。就必须明确该run方法所属对象。5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法实现方式和继承方式的区别!!!!!!实现方式:好处在于避免了但集成的局限性。在定义线程时,建议使用实现方式implements继承Thread:线程代码存放Thread子类run方法中。实现Runnable:线程代码存在接口的子类run方法.package Test;/*正确滴方式哦^_^* 需求:简单的买票程序* 4个窗口卖票,第二种方式*/class Ticket2 implements Runnable{private int tick = 100;public void run{while{if{System.out.println;}}}}class TicketDemo2 {public static void main{Ticket2 tick1 = new Ticket2;Thread t1 = new Thread; t1.start;Thread t2 = new Thread; t2.start;Thread t3 = new Thread; t3.start;Thread t4 = new Thread; t4.start;}}11-09多线程的安全问题通过分析,发现,打印出0,-1,-2等错票。多线程的运行出现了安全问题。!!!问题的原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完另一个线程就参与进来执行,导致共享数据的错误。解决办法:对多条草错共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行Java对于多线程的安全问题提供了专业的解决方式:同步代码块synchronized{需要被同步的代码}class Ticket2 implements Runnable{private int tick = 100;Object obj = new Object;public void run{while{synchronized//加上的正确代码..{//加上的正确代码..if{//让程序稍等10毫秒try{Thread.sleep;}catch{}System.out.println;}}//加上的正确代码..}}}class TicketDemo2 {public static void main{Ticket2 tick1 = new Ticket2;Thread t1 = new Thread; t1.start;Thread t2 = new Thread; t2.start;Thread t3 = new Thread; t3.start;Thread t4 = new Thread; t4.start;}}11-10多线程同步代码块synchronized{需要被同步的代码}对象如同锁,持有锁的线程可以在同步中执行。没有持有锁的线程,即使获取cpu的执行权,也进不去,因为没有获取锁例子:火车上的卫生间--经典!!同步的前提:1,必须要有两个或者两个以上的线程。2,必须是多个线程使用同一个锁必须保证同步中只能有一个线程在运行好处:解决了多线程的安全问题。弊端:多个线程都需要判断锁,较为消耗资源,就变慢了11-11同步函数package Test;/*需求:* 银行有一个金库。* 有两个储户,分别存300元,每次存100,分3次* 目的:该程序是否有安全问题,如果有,如何解决?* * 如何找问题* 1,明确哪些代码是多线程运行代码。* 2,明确共享数据* 3,明确多线程运行代码中哪些语句是操作共享数据的。*/class Back{private int sum;public synchronized void add{//Object obj = new Object;//synchronized//{try{Thread.sleep;}catch{}sum = sum + n;System.out.println;//}}}class Cus implements Runnable{private Back b = new Back;public void run{for{b.add;}}}class BackDemo {public static void main{Cus c = new Cus;Thread t1 = new Thread;Thread t2 = new Thread;t1.start;t2.start;}}11-12多线程-同步函数的锁是this同步函数用的是哪一个锁呢?函数需要被对象调用。那么函数都有一个所属对象引用。就是this所以同步函数使用的锁是this.package Demo;/*验证锁是 this* 一个线程在同步代码块中。* 一个线程在同步函数中。* 都在执行卖票*/class Ticket2 implements Runnable{private int tick = 100;Object obj = new Object;boolean flag = true;public void run{if{while{synchronized//把this换成obj结果有问题。{if{try{Thread.sleep;}catch{}System.out.println;}}}}elsewhilethis.show;}public synchronized void show{if{//让程序稍等10毫秒try{Thread.sleep;}catch{}System.out.println;}}}class ThisLockDemo {public static void main{Ticket2 tick1 = new Ticket2;Thread t1 = new Thread; Thread t2 = new Thread;t1.start;try{Thread.sleep;}catch{}tick1.flag=false;t2.start;}}11-13多线程-静态同步函数的锁是Class对象如果同步函数被静态修饰后,使用的锁是啥呢?竟然不是。。this了静态进内存时,内存中没有本类对象,但是一定有该类对象对应的字节码文件。类名.class 该对象的类型是Class静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class/*验证锁是class* 一个线程在同步代码块中。* 一个线程在同步函数中。* 都在执行卖票*/class Ticket implements Runnable{private static int tick = 100;Object obj = new Object;boolean flag = true;public void run{if{while{synchronized{if{try{Thread.sleep;}catch{}System.out.println;}}}}elsewhileshow;}static public synchronized void show{if{//让程序稍等10毫秒try{Thread.sleep;}catch{}System.out.println;}}}class StaticMethodDemo {public static void main{Ticket tick1 = new Ticket;Thread t1 = new Thread; Thread t2 = new Thread;t1.start;try{Thread.sleep;}catch{}tick1.flag=false;t2.start;}}11-14多线程-单例设计模式-懒汉式/**单例设计模式。* 懒汉设计模式**//*饿汉式class Single{private static final Single s = new Single;private Single{}public static Single getInstance{return s;}}*///延迟加载的单例设计模式模式示例!!!!!!!!!!!!!!!!!很重要。。//懒汉式,特点在于延迟加载,懒汉式如果多线程访问时,可能出现同步问题,用双重锁会出现效率问题class Single{private static Single s = null;private Single{}public static Single getInstance{ifsynchronized{ifs = new Single;}return s;}}class SingleDemo {}11-15多线程-死锁咦...程序就挂那里不动了0.0同步中嵌套同步,但是锁却不同package test;/** 0.0死锁*/class Test implements Runnable{private boolean flag;Test{this.flag = flag;}public void run{if{while{//a锁中有b锁synchronized{System.out.println;synchronized{System.out.println;}}}}else{while{//b锁中有a 锁synchronized{System.out.println;synchronized{System.out.println;}}}}}}//创建一个锁class Lock{static Lock locka = new Lock;static Lock lockb = new Lock;}//主函数class DeadLockTest {public static void main{Thread t1 = new Thread);Thread t2 = new Thread);t1.start;t2.start;}}12-01线程间通讯:其实就是多个线程操作同一个资源;但是操作的动作不同。package demo;/* 线程间通讯* 先来一段有问题的代码。*/class Res{String name;String sex;}//输入class Input implements Runnable{private Res r;Input{this.r = r;}public void run{boolean b = true;while{if{r.name = "mike";r.sex = "man";b = false;}else{r.name = "小王";r.sex = "女";b = true;}}}}//输出class Output implements Runnable{private Res r;Output{this.r = r;}public void run{//建立循环,为了多次执行输出,找错误while{System.out.println;}}}class InputOutputDemo {public static void main{Res r = new Res;Input in = new Input;Output ou = new Output;Thread t1 = new Thread;Thread t2 = new Thread;t1.start;t2.start; }}12-02嘿..嘿..嘿..嘿解决上面的问题,老简单了/* 线程间通讯*/class Res{String name;String sex;}//输入class Input implements Runnable{private Res r;Input{this.r = r;}public void run{boolean b = true;while{synchronized{if{r.name = "mike";r.sex = "man";b = false;}else{r.name = "小王";r.sex = "女";b = true;}}}}}//输出class Output implements Runnable{private Res r;Output{this.r = r;}public void run{//建立循环,为了多次执行输出,找错误while{synchronized{System.out.println;}}}}class InputOutputDemo {public static void main{Res r = new Res;Input in = new Input;Output ou = new Output;Thread t1 = new Thread;Thread t2 = new Thread;t1.start;t2.start; }}12-03线程间通信-等待唤醒机制总结:wait;notify;notifyAll;都要使用在同步中,因为要对持有监视器的线程操作所以要使用在同步中,因为只有同步才有锁的概念.为什么这些操作线程的操作要定义在Object类中呢?因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒;不可以对不同锁中的线程进行唤醒.也就是说,等待和唤醒必须是同一把锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。package demo;/* 线程间通讯*加上了唤醒机制*/class Res{String name;String sex;boolean flag = false;}//输入class Input implements Runnable{private Res r;Input{this.r = r;}public void run{boolean b = true;while{synchronized{iftry{r.wait;}catch{}if{r.name = "mike";r.sex = "man";b = false;}else{r.name = "小王";r.sex = "女";b = true;}r.flag = true;r.notify;}}}}//输出class Output implements Runnable{private Res r;Output{this.r = r;}public void run{//建立循环,为了多次执行输出,找错误while{synchronized{iftry{r.wait;}catch{}System.out.println;r.flag = false;r.notify;}}}}class InputOutputDemo {public static void main{Res r = new Res;Input in = new Input;Output ou = new Output;Thread t1 = new Thread;Thread t2 = new Thread;t1.start;t2.start; }}12-04线程间通讯-代码优化package test;/* 线程间通讯*加上了唤醒机制*/class Res{//设置年龄private String name;//设置性别private String sex;//用于判断是否等待private boolean flag = false; //提供获取的方法,因为需要同步,而且代码比较少,所以直接用同步修饰方法public synchronized void set{if{try{this.wait;}catch{}}this.name = name;this.sex = sex;this.flag = true;this.notify;}//提供输出的方法public synchronized void out{if{try{this.wait;}catch{}}System.out.println;this.flag = false;this.notify;}}//获取类class Input implements Runnable{//创建对象private Res r;Input{this.r = r;}public void run{//多循环几次,看看正不正确while{r.set;r.set;}}}//输出类class Output implements Runnable{private Res r;Output{this.r = r;}public void run{while{r.out;}}}//主函数class InputOutTest {public static void main{Res a = new Res;new Thread).start;new Thread).start;}}12-05线程间通信-生产者消费者package demo;/** 需求:多个生产者-多个消费者* 要求:生产一次,消费一次*///资源Resourceclass Resource{private String name;private int count = 1;private boolean flag = false;//生产功能public synchronized void set{whiletry{wait;}catch{ }this.name = name+"--"+count++;System.out.println;flag = true;this.notifyAll;}public synchronized void out{whiletry{wait;}catch{ }System.out.println;flag = false;this.notifyAll;}}//生产者class Producer implements Runnable{private Resource res;Producer{this.res = res;}public void run{while{res.set;}}}//消费者class Consumer implements Runnable{private Resource res;Consumer{this.res = res;}public void run{while{res.out;}}}//主函数class ProducerConsumerDemo {public static void main{Resource re = new Resource;Producer pro = new Producer;Consumer cou = new Consumer;Thread t1 = new Thread;Thread t2 = new Thread;Thread t3 = new Thread;Thread t4 = new Thread;t1.start;t2.start;t3.start;t4.start; }}对于多个生产者和消费者。为啥要定义while 判断标记。原因:让被唤醒的线程再一次判断标记。为啥要定义notifyAll因为需要唤醒对方线程。因为只用notify,容易出现只唤醒奔放县城的情况。导致程序中的所有线程都等待.12-06线程间通信-生产者消费者JDK5.0升级版提供了多线程的升级解决方案,将synchronized替换成了显示的Lock操作将Object中的 wait,notify,notifyAll替换成了Condition对象await,signal,signalAll该对象可以通过Lock锁进行获取在该示例中,实现了本方只唤醒对方的操作package demo2;import java.util.concurrent.locks.*;/***ProducerConsumerDemo2的升级版**需求:多个生产者-多个消费者*要求:生产一次,消费一次*@author Chen_zyan*///资源Resourceclass Resource{private String name;private int count = 1;private boolean flag = false;private Lock lock = new ReentrantLock;private Condition condition_pro = lock.newCondition;private Condition condition_con = lock.newCondition;//生产功能public void setthrows InterruptedException {lock.lock;try{whilecondition_pro.await;this.name = name+"--"+count++; System.out.println;flag = true;condition_con.signal;}finally{lock.unlock;}}public void outthrows InterruptedException {lock.lock;try{whilecondition_con.await;System.out.println;flag = false;condition_pro.signal;//释放对方的锁}finally{lock.unlock;//释放锁的动作一定要执行}}}//生产者class Producer implements Runnable{private Resource res;Producer{this.res = res;}public void run{while{try {res.set;} catch { }}}}//消费者class Consumer implements Runnable{private Resource res;Consumer{this.res = res;}public void run{while{try{res.out;}catch{}}}}//主函数class ProducerConsumerDemo2 {public static void main{Resource re = new Resource;Producer pro = new Producer;Consumer cou = new Consumer;Thread t1 = new Thread;Thread t2 = new Thread;Thread t3 = new Thread;Thread t4 = new Thread;t1.start;t2.start;t3.start;t4.start; }}12-07停止线程stop方法已经过时。如何停止线程?只有一种,run方法结束。开启多线程运行,运行代码通常都是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束特殊情况:当线程处于冻结状态,就不会读取到标记,那么线程就不会结束.当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行汇总来。这样就可以操作标记让线程结束。Thread类中提供了该方法interrupt;方法package demo;/**需求:停止线程* @author Chen_zyan*/class StopThread implements Runnable{private boolean flag = true;public synchronized void run{while{try{wait;}catch{System.out.println;//如果都已经捕获到异常了,就更改flag的状态this.flag =false;}System.out.println;}this.flag = false;}}class StipThreadDemo {public static void main{StopThread st = new StopThread;Thread t1 = new Thread;Thread t2 = new Thread;t1.start;t2.start; int num = 0 ;while{if{//结束进程t1.interrupt;t2.interrupt;break;}System.out.println;}System.out.println;}}12-08守护线程setDaemonpublic final void setDaemon将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。 该方法必须在启动线程前调用。 通俗点说:就是前台进程全部结束完之后,守护线程自动就退出了。package demo2;/**需求:停止线程* @author Chen_zyan*/class StopThread implements Runnable{private boolean flag = true;//public synchronized void runpublic synchronized void run{while{try{wait;}catch{System.out.println;//如果都已经捕获到异常了,就更改flag的//this.flag =false;}System.out.println;}this.flag = false;}}class SetDaemonDemo {public static void main{StopThread st = new StopThread;Thread t1 = new Thread;Thread t2 = new Thread;//setDaemon必须要在现在标记出来。t1.setDaemon;t2.setDaemon;t1.start;t2.start; int num = 0 ;while{if{//结束进程//t1.interrupt;//t2.interrupt;break;}System.out.println;}System.out.println;}}12-09join方法当A线程执行到了B线程的.join方法时,A就会等待。等B线程都执行完A才会执行。join可以用来临时加入线程执行joinpublic final void jointhrows InterruptedException等待该线程终止。 抛出: InterruptedException - 如果任何线程中断了当前线程。当抛出该异常时,当前线程的中断状态 被清除。//join形象一点比喻:等着去死吧0.0//意思就是执行完join方法之后再执行其它方法.class Demo implements Runnable{public void run{for{System.out.println;}}}class JoinDemo {public static void mainthrows Exception{Demo d = new Demo;Thread t1 = new Thread;Thread t2 = new Thread;t1.start;t1.join;t2.start;for{System.out.println;}System.out.println;}}12-10优先级%yield方法/*先说点其它的*toString*public String toString返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 *覆盖:*类 Object 中的 toString*返回:*该线程的字符串表示形式。*System.out.println;*System.out.println;*打印结果示例:Thread....69***优先级:注意,默认的优先级都是5*setPriority*public final void setPriority更改线程的优先级。 *首先调用线程的 checkAccess 方法,且不带任何参数。这可能抛出 SecurityException。 **在其他情况下,线程优先级被设定为指定的 newPriority 和该线程的线程组的最大允许优先级相比较小的一个。 *参数:*newPriority - 要为线程设定的优先级 **static int MAX_PRIORITY * 线程可以具有的最高优先级。 *static int MIN_PRIORITY * 线程可以具有的最低优先级。 *static int NORM_PRIORITY * 分配给线程的默认优先级。 *eg:* t1.start;* t1.setPriority;*注意:即使设置了优先级,虽然执行频率变高了,但是仍然不会持续执行。/下面说点有意思的yield暂停当前正在执行的线程对象,执行其它对象。也就是说:稍微减缓执行频率.也就是说让线程几乎都有运行机会.package test;/*** 来个正式点的,一般开发的时候如何写线程.* @author tingzi*匿名内部类的方法封装一下子,当然也可以不用*/class ThreadTest {public static void main{//封装方式1new Thread{public void run{for{System.out.println;}}}.start; for{System.out.println;} //封装方式2Thread r = new Thread{public void run{for{System.out.println;}}};r.start;//Test1 t1 = new Test1;//Thread th = new Thread;//th.start; }}/*class Test1 implements Runnable{public void run{for{System.out.println;}}}*/13-01String特点:字符串最大特点,一旦被初始化,就不可以被改变//方式①:String s1 = "abc";//s1是一个类类型变量,"abc"是一个对象。s1 = "张三";System.out.println;//输出的是张三,是s1变了,abc这个对象并没有变,而是s1指向的对象变了。//方式②String s2 = new String;System.out.println;//falseSystem.out.println);//true;//String类复写了Object类中的equals方法,该方法用于判断字符串是否相同。//Object类中equals中的方法是比较地址值s1和s2有啥区别?答:s1在内存中有一个对象,s2在内存中有两个对象13-02StringString类是用于描述字符串实物。那么它就提供了多个方法对字符串进行操作。常见的操作有哪些?"abcd";1,获取 !!!!!!!!!!!!!!!!!!1.1根据字符串中包含的字符数,也就是字符串的长度。int length:获取长度1.2根据位置获取位置上的某个字符char charAt;1.3根据字符获取该字符在字符中的位置int indexOf//因为接受的是ASCⅡ码,返回的是ch在字符串中出现的第一次位置int indexOf//从fromIndex指定位置获取ch在字符串中出现的位置。 int indexOf//返回的是str在字符串中第一次出现的位置int indexOf //返回的是str在位置fromIndex后字符串中出现的第一次位置int lastIndexOf//反向索引的位置 //获取字符串中元素的位置以及位置的元素public static void method_get{String str = "abecdde4a";String s1 = "cdd";sop;//获取长度sop);//获取4位置上的字符。如果没有的话,抛出异常StringIndexOutOfBoundsExceptionsop);//获取a在字符串中的第一次找到的位置,如果没找到,返回值是-1sop);//获取字符串s1在str中的起始位置sop);//获取e在字符串中数组3后面的位置sop);//从尾巴数}2,判断2.1字符串中是否包含某一个子串;boolean contains;!!!!特殊之处:indexOf:可以索引str第一次出现位置,如果返回-1,表示str不在字符串中存在。所以,也可以用于对指定判断是否包含。if!==-1)//就说明有而且该方法既可以判断,又可以获取出现的位置。2.2 字符串中是否有内容;boolean isEmpty;原理:就是判断长度是否为0,""是对象 null是空2.3字符串是否是以指定内容开头boolean startsWith;2.4字符串是否是以指定内容结尾boolean endsWith;2.5判断字符串的内容是否相同,覆写了Object类中的equals方法boolean equals;2.6判断内容是否相同,并忽略大小写比较boolean equalsIgnoreCase;//判断字符串中的字符串class StringMethodDemo {public static void method_is{String str = "ArrayDemo.java";//判断字符串中开头是否是Arraysop);//判断字符串结尾是否是.javasop);//判断字符串中间是否有Demosop); }//13-03以下下面省略此处代码public static void main{method_is;//method_get;/*String s1 = "abc";String s2 = new String;String s3 = "abc";System.out.println;//falseSystem.out.println;//true;说明的是s1与s3指向了同一对象*/}//13-03下面省略此处代码public static void sop{System.out.println;}}13-03String3转换3.1将字符数组转成字符串构造函数:String将字符数组转换成字符串String将数组中的一部分转换成字符串注解:char是数组;fooset是起始位;fount是个数.静态方法:static String copyValueOf;static String copyValueOf//字符数组中的一部分转换成字符串 static String ValueOf;//看3.5~_~其实与上面的功能是一样的。 3.2将字符串转成字符数组!!!!!!!!char toCharArray; 3.3将字节数组转成字符串.String将字符串中的一部分转换成数组String 3.4将字符串转成字节数组byte getBytes;3.5将基本数据类型转换成字符串。static String valueOfstatic String valueOf3+"";//String.valueOf;//后者比较专业,其实都是一样滴.特殊:字符串和字节数组在转换过程中,是可以指定编码表的。//转换public static void method_trans{ //将数组转换成字符串char arr = {'a','b','c','d','e','f'};//StringString s = new String;sop;String s1 = "xsdcdrbs";char chs = s1.toCharArray;for{sop;}}13-04切割和替换以及子串4.替换返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。String replace String replace public static void method_replace{String s = "hello java";//示例:将字符串a转换成nString s1 = s.replace;//如果要替换的字符串不存在,那么,返回的还是原串//示例:将字符串中java转换成world;String s2 = s.replace;sop;sop;sop;}5.切割String split;//里面存的也是规则,但是不是正则的//切割逗号是拿不到的public static void method_split{String s = "zhangsan,lisi,wangwu";String arr=s.split;for{sop;}}6.子串,获取字符串中的一部分.String substring;//从begin开始到结尾处,如果角标不存在,会存在字符串角标越界异常。String substring;//包含头不包含尾,public static void method_sub{String s = "abcdef"; sop);sop);}13-05转换,比较和去除空格7.转换,比较和去除空格7.1将字符串转成大写或小写String toUpperCase;//转换成大写String toLowerCase;//转换成小写7.2将字符串两端的多个空格去除。String trim;7.3对两个字符串进行自然顺序的比较int compareTo;如果参数字符串等于此字符串,则返回值 0;如果此字符串按字典顺序小于字符串参数,则返回一个小于0的值;如果此字符串按字典顺序大于字符串参数,则返回一个大于0的值。 //转换大小写,去除两端空格public static void method_7{String s = " Hello Java ";//小写sop;//大写sop;//去除两端空格sop; String s1 = "acc";String s2 = "aab";sop); }13-06字符串练习1,模拟一个trim方法,去除字符串两端的空格。思路:判断字符串第一个位置是否是空格,如果是继续向下判断,知道不是空格位置。结尾处判断空格也是如此。当开始和结尾都判断到不是空格时,就是要获取的字符串。2将一个字符串进行反转.将字符串中指定部分进行反转,"abcdefg";abfedcg思路:曾经学习过对数组的元素进行反转;将字符串变成数组,对数组反转;将反转后的数组变成字符串;只要将或反转的开始和结束位置作为参数传递即可。3,获取一个字符串在另一个字符串中出现的次数。"abkkcdkkefkkskk"思路:定义个计数器;获取kk第一次出现的位置;从第一次出现为止后剩余的字符串中继续获取kk出现的位置,每获取一次就技术一次。当获取不到时,技术完成。4,获取两个字符串中最大同子串,第一个动作:将断的那个串进行长度一次递减的子串打印。"abcwerthelloyuiodef""cvhellobnm"思路:将断的那个子串按照窗独递减的方式获取到;将每获取到的子串去长子串中判断是否包含,如果包含,已经找到!。package test;//第一题,那个那个,那个啥,自己创建一个trimpublic class Test1 {//创建输出public static void sop{System.out.println;}//创建一个方法myTrimpublic static String myTrim{int start = 0,end = str.length-1;while==' ')start++;while==' ')end--;String s = str.substring;return s;}public static void method_arr{String st = " abde ";sop");myTrim;String s2 = myTrim;sop");}//主函数public static void main{method_arr;}}13-07//第二题将字符串反转public class Test2 {//创建输出public static void sop{System.out.println;}public static String reverseString{/*//字符串变成数组char chs = s.toCharArray;//反转数组reverse;//return new String;*/return reverseString;}//定义开始段,结束段,反转public static String reverseString{//字符串变成数组char chs = s.toCharArray;//反转数组reverse;//return new String;}//翻转方法@SuppressWarningsprivate static void reverse{for{swap;}}//翻转方法定义开始段,结束段,反转private static void reverse{for{swap;}}//翻转数组private static void swap{char temp = arr;arr = arr;arr =temp;}public static void main{String st = " ab ce ";System.out.println;sop");sop+")");System.out.println;sop+")");}}13-08package test;/*3,获取一个字符串在另一个字符串中出现的次数。"abkkcdkkefkkskk"思路:定义个计数器;获取kk第一次出现的位置;从第一次出现为止后剩余的字符串中继续获取kk出现的位置,每获取一次就技术一次。当获取不到时,技术完成。*/class Test3 {//先来一个比较笨的方法public static int getSubCount{//定义一个计数器int count = 0;//定义一个位置int index = 0;while)!=-1){//打印一下,瞅瞅字符串变化过程sop;str = str.substring;//每出现一次,计数器就加一count++;}return count;} //方式二public static int getSubCount_2{int count = 0;int index = 0;while)!=-1){sop;index = index +key.length;count++;}return count;} public static void main{String st ="abkkcddkkcefkkskk";sop);sop);}public static void sop{System.out.println;}}13-9package test;/*4,获取两个字符串中最大同子串,第一个动作:将断的那个串进行长度一次递减的子串打印。"abcwerthelloyuiodef""cvhellobnm"思路:将断的那个子串按照窗独递减的方式获取到;将每获取到的子串去长子串中判断是否包含,如果包含,已经找到!。*/public class Test4 {public static String getMaxSubString{//进行判断,将长的字符串复制给max,将短的赋值给minString max = "",min = "";max = ?s1:s2;min = ?s1:s2;//进行遍历//外循环遍历的是元素的行数for{//内循环遍历的是控制元素减少for{String temp = min.substring;//sop;if);return temp;}}return "";}public static void main{String s1= "worldhellossa";String s2 ="hello";sop);}public static void sop{System.out.println;}}13-10-11StringBufferStringBuffer是字符串缓冲区是一个容器特点:1,而且长度是可以变化的。2,可以直接操作多个数据类型。3,最终会通过toString方法变成字符串 C creat U update R read D delete 1,存储;StringBuffer append;将指定的数据作为参数,添加到已有数据的结尾处.StringBuffer insert;将数据插入指定位置上2,删除;StringBuffer delete;包含start,不包含endStringBuffer deleteCharAt;删除指定位置的字符3,获取;char charAt;获取一个int indexOf;根据字符串获取位置int lastIndexOf;根据字符串从后面获取位置int length;//获取长度String substring;获取子串String substring;获取子串,不包含尾巴4,修改;StringBuffer replace//修改:头,尾巴,字符串void setCharAt//注意喽,没有返回类型5,反转;StringBuffer reverse//反转6,将缓冲区中的指定数据存储到指定字符数组中void getChars 13-12StringBuilder在JDK1.5版本之后出现了StringBuilder不同之处:StringBuffer是线程同步StringBuilder是线程不同步的升级三个因素:提高效率、简化书写、提高安全性。13-13基本数据类型对象包装类!!!!!!!!!byteByteshortShortintIntegerlongLongboolean---------BooleanfloatFloatdoubleDoublecharCharacter基本数据类型包装类的最常见作用:就是用于基本数据类型和字符串类型之间做转换基本数据类型转换成字符串。基本数据类型+""基本数据类型.toString如:Integer.toString;//将34整数转换成字符串"34";字符串转换成基本数据类型基本数据类型包装类.例如:xxx a = Xxx.parseXxx; int a = Integer.parseInt; double a = Double.parseDouble;boolean a = Boolean.parseBoolean;以上均为静态方式Integer i = new Integer;int num = i.intValue;//非静态的,对象调用方式----十进制转换其它进制static String toBinaryString //10→2进制static String toHexString //10→16static String toOctalString //10→8其它进制转换十进制parseInt;//radix进制,你想转换成几进制,就写几^_^13-14基本数据类型包装类新特性JDK1.5版本以后出现的新特性Integer x = 4;//自动装箱,//相当于Integer x = new Integer;x = x/* 原理:x.intValue*/+2;//x+2,x进行了自动拆箱,变成了int类型,和2进行加法运算。//再将和装箱赋值给x Integer m = 128;Integer n = 128;sop);//falseInteger a = 127;Integer b = 127;sop);//true因为:当数值在byte范围内时,对于新特性,如果该数值已经存在不会再开辟一个新的空间。注意,如果是equals判断,则都为truepublic static void sop{System.out.println;}14-01集合框架工具包中的一员java.util.Collection;Collection 有两个常见的接口: List,Set;List 下面有ArrayList,LinkedList,VectorSet 下面有HashSet,TreeSet为啥会出现这么多的容器呢?因为每一个容器对数据的存储方式都有不同。这个存储方式称之为:数据结构14-02集合框架boolean add;增加方法boolean addAll;一次性添加一堆元素void clear;清空容器boolean remove;删除一个元素boolean removeAll;删除一堆元素boolean cotains;进行判断boolean cotainsAll;比较一堆元素int hasCode;返回哈希码值boolean isEmpty;集合中是否有元素int size;判断元素的个数,只要为零,则为空boolean retainAll;取交集Object toArray;将集合变为数组Iterator iterator;取出例如:package Demo;/*** 1,add方法的参数类型是Object.以便接收任意类型的对象* 2,集合中存储的都是对象的引用*/import java.util.ArrayList;class CollectionDemo{public static void main{method_2; }public static void method_2{ArrayList al1 = new ArrayList;al1.add;al1.add;al1.add;al1.add; ArrayList al2 = new ArrayList;al2.add;al2.add;al2.add;al2.add; //取al1与al2中的交集,并保存在al1中//al1.retainAll; //将al1与al2中相同的元素,并将al1中删除相同后的剩下的元素保存在al1中//al1.removeAll;sop;sop;}//基本方法public static void base_method{//创建一个集合容器。使用Collection接口的子类ArrayListArrayList al = new ArrayList; //1:添加元素al.add;//为啥用add;答曰:因为添加的内容是任意类型的,所以用Object类型的来接收al.add;al.add;al.add; //打印集合sop; //2:获取对象的长度//sop; //3:删除元素//al.remove;//al.clear;//清空集合 //4:判断元素//sop);//sop; sop; } //创建一个输出方法public static void sop{System.out.println;}}14-03迭代器Interator iterator;什么是迭代器呢?其实就是集合的取出元素的方式/*Iterator出现的原因:就把取出方式定义在集合的内部,这样去除方式就可以直接访问集合内容的元素。那么取出方式就被定义成了内部类。而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都有共同内容:判断和取出。那么可以将共性抽取。那么这些内部类都符合一个规则,该规则是:Iterator.如何获取集合的去除对象呢?通过一个对外的提供方法。iterator;*/迭代器的基本使用class IteratorDemo{public static void main{method;}public static void method{ArrayList al1 = new ArrayList;al1.add;al1.add;al1.add;al1.add; /*我是,啊Iterator it = al1.iterator;//获取迭代器,用于取出元素while{sop;}*///这个跟“啊”一样,正常开发,用这个,对内存的管理效率比较高for{sop;}}//创建一个输出方法public static void sop{System.out.println;}}14-04List,集合共性方法Collection|--List:元素是有序的,元素可以重复.因为该集合体系有索引|--ArrayList:底层的数据结构是数组结构。特点:查询速度很快,但是添加删除很慢.线程不同步|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询速度很慢,|--Vector:底层是数组数据结构。线程同步.无论增删,查询都很慢。被ArrayList代替了|--Set:元素是无序的,元素不可以重复。List:特有方法。凡是可以操作角标的方法都是该体系特有的方法.增addaddAll删remove;改set;查get;subList;listIterator;import java.util.ArrayList;import java.util.Iterator;class ListDemo {public static void main{ArrayList al = new ArrayList; //添加元素al.add;al.add;al.add;//打印原有元素sop; //在指定位置上添加元素//al.add;//sop; //删除指定位置的元素//al.remove;//sop; //修改元素//al.set; //通过角标获取元素.//sop="+al.get);//sop;//获取所有元素for{sop);}//迭代器获取元素System.out.println;for{sop;} //通过indexOf获取对象锁在位置sop); //获取部分位置元素List sub = al.subList;sop;} public static void sop{System.out.println;}}14-05ListIterator:列表迭代器!!!List集合特有的迭代器,ListIterator是Iterator的子接口在迭代时,不可以通过集合对象的方法操作集合中的元素。因为会发生并发修改异常所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断、取出、操作,如果想要做其它的操作如:添加,修改等,就需要使用其子接口,ListIterator.该接口只能通过List子集合ListIterator方法获取{....//在迭代过程中添加或者删除元素ListIterator lis = al.listIterator;while{//将java02修改为java007Object obj = lis.next;iflis.set;}sop; //逆向遍历while{sop;}}14-06List集合具体对象的特点|--List:元素是有序的,元素可以重复.因为该集合体系有索引|--ArrayList:底层的数据结构是数组结构。特点:查询速度很快,但是添加删除很慢.线程不同步|--LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询速度很慢,|--Vector:底层是数组数据结构。线程同步.无论增删,查询都很慢。被ArrayList代替了14-07Vector,中的枚举/枚举就是Vector的取出方式,发现枚举和迭代器很像其实,枚举和迭代是一样的。因为枚举的名称以及方法的名称都过长。所以被迭代器取代了。枚举就郁郁而终了。import java.util.Enumeration;import java.util.Vector;class VectorDemo {public static void main{Vector v = new Vector;v.add;v.add;v.add;v.add; Enumeration en = v.elements;while{System.out.println;}}}14-08LinkedList,链表结构LinkedList:特有方法:addFirst;addLast;getFirst;getLast;获取元素,但是不删除元素,如果集合中没有元素,会出现:NoSuchElementExceptionremoveFirst;removeLast;获取元素,但是元素被删除.如果集合中没有元素,会出现:NoSuchElementException在JDK1.6出现了替代方法:add→offerFirst;add→offerLast;get→peekFirst;get→peekLast;获取元素,但是不删除元素,如果集合中没有元素,会返回nullremove→pollFirst;remove→PollLast;获取元素,但是元素被删除.如果集合中没有元素,会返回nullpackage Demo;import java.util.LinkedList;class LinkedListDemo {public static void main{LinkedList link = new LinkedList;link.addLast;link.addLast;link.addLast;link.addLast; sop;//打印结果 //sop;//java04//sop;//java01sop;//4sop;//打印结果:java01sop;//3 //不用迭代器while{sop;}}public static void sop{System.out.println;}}14-09LinkedList,练习!!!!------必须会------/*** 使用LinkedList模拟一个堆栈或者队列数据结构* *堆栈:先进后出,*队列:先进先出 First in First out*///队列class DuiLie{private LinkedList link;DuiLie{link = new LinkedList;}public void myAdd{link.addFirst;}public Object myGet{return link.removeLast;}//如果判断是否为空public boolean isNull{return link.isEmpty;}}//堆栈class DuiZhan{private LinkedList link;DuiZhan{link = new LinkedList;}//添加方法public void myAdd{link.addFirst;}//获取方法public Object myGet{return link.removeFirst;}//判断方法public boolean myNull{return link.isEmpty;}}//主函数class LinkedListTest {public static void main{DuiLie dl = new DuiLie;dl.myAdd;dl.myAdd;dl.myAdd;dl.myAdd;while{sop;}}public static void sop{System.out.println;}}14-10ArrayList,练习注意:在迭代时,循环中next调用一次,就要hasNext判断一次,否则就出现异常package test;import java.util.ArrayList;import java.util.Iterator;//去除相同的元素class ArrayListTest {public static void main{ArrayList al = new ArrayList;al.add;al.add;al.add;al.add;al.add;al.add;al.add;//先打印一下al集合中有哪些元素sop;//调用以下取出元素方法al = singleElement;//再次打印一下集合中有哪些元素sop; }//取出元素方法public static ArrayList singleElement{//创建一个容器ArrayList newAl = new ArrayList;//创建一个容器,取出集合中元素Iterator it = al.iterator; while{//创建第三方对象,将迭代器出来的元素赋值给objObject obj = it.next;//进行判断,如果newAl容器中不包含obj对象,就将obj对象存储斤newAl容器中if)newAl.add;}//最后将剩下的newAl进行返回return newAl;} //取出元素public static void sop{System.out.println;}}14-11ArrayList,练习2List集合判断元素是否相同,依据的是元素的equals方法package test2;import java.util.ArrayList;import java.util.Iterator;/*将自定义对象作为元素存储到ArrayList集合中,并取出重复元素。*比如:存人对象。同姓名,同年龄,视为同一个人.为重复元素* *思路:*1,对人描述,将数据封装进人对象。*2,定义容器,将人存入*3,取出*/class Person{private String name;private int age;Person{this.name = name;this.age = age;}//判断姓名,年龄是否相同public boolean equals{if)return false; Person p = obj;System.out.println; return this.name.equals && this.age == p.age; } public String getName {return name;}public int getAge {return age;}}class ArrayListTest2 {public static void main{ArrayList al = new ArrayList;al.add);//因为这里al.add所以下面要做强制类型转换al.add);al.add);al.add);al.add);al.add); //去除相同元素al = singleElement; Iterator it = al.iterator;while{//Object obj = it.next;//Person p = obj;//以上两句可以这么写Person p = it.next;//这里要做强制类型转换sop;} } //取出元素方法public static ArrayList singleElement{//创建一个容器ArrayList newAl = new ArrayList;//创建一个容器,取出集合中元素Iterator it = al.iterator; while{//创建第三方对象,将迭代器出来的元素赋值给objObject obj = it.next;//进行判断,如果newAl容器中不包含obj对象,就将obj对象存储斤newAl容器中if)newAl.add;}//最后将剩下的newAl进行返回return newAl;} public static void sop{System.out.println;}}14-12HashSet,|--Set:元素是无序的,元素不可以重复|--HashSet:底层数据结构是哈希表。HashSet是如何保证元素唯一性的呢?是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true;如果元素的HashCode值不同,不会调用equals 注意, 对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法.|--TreeSet:Set集合的功能和Collection是一致的.import java.util.HashSet;import java.util.Iterator;//注意,存的的顺序与取出的顺序并不一定一样。class HashSetDemo {public static void main{HashSet hs = new HashSet;hs.add;hs.add;hs.add;hs.add; Iterator it = hs.iterator;while{sop;}}public static void sop{System.out.println;}}14---13HashSet,是如何保证元素唯一性的呢?是通过元素的两个方法,hashCode和equals来完成。如果元素的HashCode值相同,才会判断equals是否为true;如果元素的HashCode值不同,不会调用equalsHashSet,判断和删除的依据注意, 对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法.package test;/*往hashSet集合中存入自定对象* 姓名和年龄相同为同一个人,重复元素.* */import java.util.*;class HashSetTest {public static void main{HashSet hs = new HashSet; hs.add);hs.add);hs.add);//hs.add); Iterator it = hs.iterator;//判断元素是否相同//sop));//判断删除元素hs.remove);//直接比了一下hashCode while{Person p = it.next;sop;}}public static void sop{System.out.println;}}class Person{private String name;private int age;Person{this.name = name;this.age = age;}public int hashCode{ System.out.println;//这句是用来看如何运行的。//计算各自的hashCodereturn name.hashCode+age;//顺便说一下age*39,可以避免哈希值相同}//判断姓名,年龄是否相同public boolean equals{if)return false; Person p = obj;//左面是参数的,右面是当前对象System.out.println;//这句是用来看如何运行的。 return this.name.equals && this.age == p.age; } public String getName {return name;}public int getAge {return age;}}!!!!以下这句话很重要!!!!小小总结:ArrayList紧紧依赖equals,而HashSet则先依赖于HashCode后依赖于与equals!!!!以上这句话很重要!!!!15-01TreeSetTerrSet//上限TreeSet//比较器,下限..,只能用父类的方法Set:无序,不可以重复元素|--HashSet:数据结构是哈希表。线程非同步的.保证元素唯一性的原理:判断元素的hashCode值是否相同。如果相同,还会继续判断元素的equals方法,是否为true|--TreeSet:可以对Set集合中的元素进行排序.底层数据结构是二叉树。保证元素唯一性的依据:compareTo方法return 0。 TreeSet:排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法这种方式也成为元素的自然顺序,也叫默认顺序 TreeSet:排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时,就需要让集合自身具备比较性在集合初始化时,就有了比较方式.import java.util.Iterator;import java.util.TreeSet;class TreeSetDemo {public static void main{TreeSet tre = new TreeSet;tre.add;tre.add;tre.add;tre.add; Iterator it = tre.iterator; while{System.out.println;}}}15-02TreeSet存储自定义对象public interface Comparable此接口强行对实现它的每个类的对象进行整体排序。记住,排序时,当主要条件相同时,一定要判断一下次要条件./* 需求:* 往TreeSet集合中存储自定义对象学生。* 想按照学生的年龄进行排序* */import java.util.Iterator;import java.util.TreeSet;class TreeSetDemo {public static void main{TreeSet tre = new TreeSet;tre.add);tre.add);tre.add);tre.add); Iterator it = tre.iterator; while{Student stu = it.next;System.out.println;}}}class Student implements Comparable//该接口强制让学生具备比较性{private String name ;private int age;Student{this.name = name;this.age = age;} public int compareTo//compare在这里{if)throw new RuntimeException;Student s = obj; //这一句是看一下程序是如何运行的System.out.println; ifreturn 1;//只要是一个正数就行if//如果年龄相同,那么就比较姓名{return this.name.compareTo;} return -1;}public String getName{return name;}public int getAge{return age;}}15-03二叉树二叉树就是每个节点最多有两个子树的树结构。通常子树通常子树被称作“左子树”和“右子树”。举个例子,22,13,18,20,24,26,1122/ 13 24/ 11 18 2620TreeSet:排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法 public int compareTo//compare在这里{return -1;//-1为倒叙,1为正序,0就返回第一个值}15-04Comparator方式排序package demo2;import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;/** 当元素自身不具备比较性,或者具备的比较性不是所需要的。* 这时需要让容器自身具备比较性。* 定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数.* * 需求变了,想要按照姓名排序* * 当两种排序都存在时,以比较器为主。* 定义一个类,实现Comparator接口,覆盖compare方法*/class TreeSetDemo2 {public static void main{TreeSet tre = new TreeSet;tre.add);tre.add);tre.add);tre.add);tre.add); Iterator it = tre.iterator; while{Student stu = it.next;System.out.println;}}}class Student implements Comparable//该接口强制让学生具备比较性{private String name ;private int age;Student{this.name = name;this.age = age;} public int compareTo//compare在这里{//return -1; if)throw new RuntimeException;Student s = obj; //这一句是看一下程序是如何运行的//System.out.println; ifreturn 1;//只要是一个正数就行if//如果年龄相同,那么就比较姓名{return this.name.compareTo;} return -1; }public String getName{return name;}public int getAge{return age;}}//比较器器class MyCompare implements Comparator{public int compare{Student s1 = o1;Student s2 = o2; int num = s1.getName.compareTo;if{ //封装成整数对象return new Integer.compareTo);/*ifreturn 1;ifreturn 0;return -1;*/}return num;}}15-05/*** 练习:按照字符串长度排序* 字符串本身具备比较性,所以这时候需要用比较器!!*/import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;class TreeSetTest {public static void main{TreeSet ts = new TreeSet;ts.add;ts.add;ts.add;ts.add;ts.add;ts.add; Iterator it = ts.iterator;while{System.out.println;}}}//比较器class StrLenSinMyCompare implements Comparator{public int compare{String st1 = obj1;String st2 = obj2; int num = new Integer.compareTo);if{return st1.compareTo;}return num; }}15-06-07泛型概述JDK1.5版本以后出现的新特性。用于解决类型安全问题,是一个安全机制例如:ArrayList al = new ArrayList;Iterator it = al.iterator;好处:1,将运行时期出现的classCastException,转移到了编译时期。方便于程序员解决问题。让运行时问题减少,安全。2,避免了强制类型麻烦泛型格式:通过<>来定义要操作的引用数据类型。在使用java提供的对象时,什么时候写泛型呢?通常在集合框架中很常见,只要见到<>就要定义泛型其实<>就是用来接受类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可.import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;class TreeSetDemo2 {public static void main{TreeSet ts = new TreeSet;ts.add;ts.add;ts.add;ts.add;ts.add;ts.add; Iterator it = ts.iterator; while{System.out.println;}}}//自定义比较器class MyCompare2 implements Comparator{public int compare{//比较st1与st2的长度,因为是要逆向比较,所以仅需将st1与st2调换位置int num = new Integer.compareTo);if//这里调换位置即可return st2.compareTo;return num;}}15-08泛型类什么时候定义泛型类?当类中要操作的!!引用数据类型!!不确定的时候,早起定义Object来完成扩展现在定义泛型来完成扩展class Worker{ }class Students{ }//原来的class Tool{private Object obj;public void setTool{this.obj = obj;}public Object getObject{return obj;}}//现在的泛型类class Utils{private QQ q;public void setObject{this.q = q;}public QQ getObject{return q;}}class GenericDemo3 {public static void main{//来个现在的Utils st = new Utils;st.setObject;// 这里如果传了一个new Worker会在编译的时候就出错。Students sr = st.getObject;System.out.println; /*这个是以前的,这个在编译的时候不会出错,只有在运行的时候才会出错。Tool t = new Tool;t.setTool;Worker w = t.getObject;*/}}15-09泛型方法泛型类定义的泛型,在整个类中有效。如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。//纯正泛型类,此类方法中,指定了类型之后,所有方法均必须是制定类型参数class Demo1{public void show{System.out.println;}public void print{System.out.println;}}//类中有方法,各自可以调用格子的类型class Demo2{public void show{System.out.println;}public
void print{System.out.println;}}//泛型类中有泛型方法,泛型方法可以有自己的类型。而其它的必须使用是定的类型class Demo3{public void show{System.out.println;}public void print{System.out.println;}public void method{System.out.println;}}class GenericDemo4 {public static void main{//针对Demo1Demo1d1 = new Demo1 ;d1.show;d1.print; //针对Demo2Demo2 d2 = new Demo2;d2.show;d2.print;//这里可以是Integer类型的 //针对Demo3Demo3 d3 = new Demo3 ;d3.show;d3.print;d3.method;//这里可以是任意类型的 }}15-10静态方法泛型特殊之处:静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。!!格式: 放在返回类型的前面,修饰符的后面例如:class Demo {public void show{}//静态的public static void print{}}15-11泛型接口//泛型定义在接口上interface Inter {void show;}//这种是我已经已经知道了类型,指定了类型滴class InterImpl implements Inter {public void show{System.out.println;}}//不知道类型滴class InterImpl1 implements Inter {public void show{System.out.println;}}class GenericDemo5 {public static void main{//已经知道类型是字符串,所以必须传字符串,否则编译失败InterImpl in1 = new InterImpl;in1.show; //这个是我自定义类型滴InterImpl1 in2 = new InterImpl1 ;in2.show; }}15-12泛型限定? 通配符,也可以理解为占位符泛型限定:? extends E:可以接收E类型或者E的子类型。上限? super E:可以接受E类型或者E的父类。下限//以下的例子仅供参考,仅供理解上限,下限。因为例子中有错误,并不能编译通过package demo3;import java.util.ArrayList;import java.util.Comparator;import java.util.Iterator;class GenericDemo6 {public static void main{/*ArrayList a1 = new ArrayList ;a1.add;a1.add;a1.add; ArrayList a2 = new ArrayList ;a2.add;a2.add;a2.add; printColl;printColl;*/ ArrayList a1 = new ArrayList ;a1.add);a1.add);a1.add); ArrayList a2 = new ArrayList ;a2.add);a2.add);a2.add); //printColl;printColl;}public static void printColl{Iterator<? extends Person> it = a1.iterator; while{System.out.println;}} /*public static void printColl//当类型左右两边的类型不确定的时候可以用?通配符{Iterator<?> it = al.iterator;while{System.out.println;}}*/}class Person{private String name;Person{this.name = name;}public String getName{return name;}}class Student extends Person{Student{super;}}class Student_c implements Comparable //<? super E>{public int compareTo{this.getName;//这里就不能编译通过}}class Comp implements Comparator {public int compare{//Person s1 = new Student;return s1.getName.compareTo;}}TreeSet ts = new TreeSet ;ts.add);ts.add);ts.add);15-13泛型限定2//既能接受Person,也能接受Person的子类型public static void printCollpackage demo7;import java.util.*;class GenericDemo7 {public static void main{ TreeSet ts = new TreeSet ;ts.add);ts.add);ts.add);ts.add); Iterator it = ts.iterator; while{System.out.println;} TreeSet ts1 = new TreeSet ;ts1.add);ts1.add);ts1.add);ts1.add); Iterator it1 = ts1.iterator; while{System.out.println;}}}/*//比较器class StuComp implements Comparator {public int compare{return s1.getName.compareTo;}}//比较器2class WorkerComp implements Comparator {public int compare{return s1.getName.compareTo;}}*///超级比较器!!class Comp implements Comparator {public int compare{return p1.getName.compareTo;}}class Person{private String name;Person{this.name = name;}public String getName{return name;}public String toString{return "Person:"+name;}}class Student extends Person{Student{super;}}class Worker extends Person{Worker{super;}}坏亭子--2013/04/1116-01-02Map特点:该集合存储键值对,一对一对往里存,而且要保证键的唯一性。1,添加put//增加pubAll//增加一大片2,删除clear//全部删除remove//按照指定键删除3,判断containsValue//是否包含某个值containsKey//是否包含某个键isEmpty//判断是否有键值关系,如果没有,返回true4,获取get//获取size//获取长度values//获取所有值entrySetkeySetMap|--Hashtable:底层是哈希表数据结构,不可以存入null键,null值.该集合是同步的,JDK1.0出现的,效率低|--HashMap:底层是哈希表数据结构。并允许使用null键和null值,该集合是不同步的,JDK1.2出现的,效率高|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序和Set很像。其实大家,Set底层就是使用了Map集合.16-03Map共性方法详情看注释import java.util.Collection;import java.util.HashMap;import java.util.Map;class MapDemo {public static void main{Map map = new HashMap ; //添加元素;添加元素,如果出现添加相同的键,那么后添加的值会覆盖原有键对应值,并put方法会返回被覆盖的值.sop);sop);map.put;map.put; //查询键值为02的元素对是否存在sop); //删除键值为"02"的元素//sop); //获取键值为023的元素键,如果不存在,返回为nullsop); map.put;sop);//可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断. //获取map集合中的所有值Collection coll = map.values;sop;sop;//因为底层结构是hashCode所以是无序的,应该说是按照哈希表排序的 } public static void sop{System.out.println;}}16-04map集合的两种取出方式1,Set keySet:将map中所有的键存入到Set集合。因为set具备迭代器.所有可以迭代方式取出所有的键。再根据get方法获取每一个键对应的值 Map集合的取出原理:将map集合转换成set集合,通过迭代器取出.2,Set<> entrySetimport java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;class MapTest {public static void main{Map map = new HashMap ; //添加元素map.put;map.put;map.put;map.put; //利用KeySet方法,获取Set值Set keySet = map.keySet; //利用Set的迭代器获取键值,注意,此处的泛型要与Set的泛型一致Iterator it = keySet.iterator; while{String key = it.next;//通过键值获取Value值String Value = map.get;sop;}}public static void sop{System.out.println;}}16-05map集合的两种取出方式1,Set keySet:将map中所有的键存入到Set集合。因为set具备迭代器.所有可以迭代方式取出所有的键。再根据get方法获取每一个键对应的值 Map集合的取出原理:将map集合转换成set集合,通过迭代器取出.2,Set > entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是Map.Entrymap→→→→→→→Set那么关系对象Map.Entry获取到后,就可以通过Map.Entry中的getKey和getValue方法获取关系中的键和值package demo;import java.util.*;class MapDemo2_2 {public static void main{Map map = new HashMap ; map.put;map.put;map.put;map.put; //将Mao集合中的映射关系取出,存入到Set集合中Set > entrySet = map.entrySet; Iterator > it = entrySet.iterator; while{Map.Entry me = it.next;String Key = me.getKey;String Value = me.getValue;System.out.println;} }}Map.Entry其实Entry也是一个接口,它是Map接口中的另一个接口interface Map{public static interface Entery{public abstract Object getKey;public abstarct Object getValue;}}class HashMap implements Map{class Hahs implements Map.Entry{public Object getKey{}public Object getValue{}}}16-06package test;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;/**练习* 每一个学生都有对应的归属地。* 学生Student,地址String.* 学生属性:姓名,年龄。* 注意:姓名和年龄相同的视为同一个学生.* 保证学生的唯一性.* * @author Chen_zyan* * 1,描述学生。* 2,定义map容器,将学生作为键,地址作为值。存入.* 3,获取map集合中的元素.*///注意,以后写的时候一定要做这几个动作:1,实现Comparable,2,覆盖hashCode与equals方法//定义学生,因为有可能会存储到二叉树当中,所以要覆写二叉树方法,实现Comparableclass Student implements Comparable {private String name;private int age;Student{this.name = name;this.age = age;}//覆写public int compareTo{int num = new Integer.compareTo);if{return this.name.compareTo;}return num;} //覆盖两个方法public int hashCode{return name.hashCode+age*22;}public boolean equals{if)throw new ClassCastException;Student s = obj; return this.name.equals && this.age == s.age;} public String getName{return name;}public int getAge{return age;} public String toString{return name+":"+age;} }class MapTest1 {public static void main{HashMap hm = new HashMap ; hm.put,"beijing");hm.put,"shanghai");hm.put,"nanjing");hm.put,"wuhan"); //第一种取出方式keySetSet keySet = hm.keySet; Iterator it = keySet.iterator; while{Student stu = it.next;String addr = hm.get;System.out.println;} //第二种取出方式 Set > entrySet = hm.entrySet; Iterator > iter = entrySet.iterator; while{Map.Entry map = iter.next;Student stu = map.getKey;String addrs = map.getValue;System.out.println;}}}16-07package test;/**需求:对学生对象的年龄进行升序排序* * 因为数据是以键值对形式存在的。* 所以要使用可以排序的Map集合。TreeMap* * @author tingzi**/import java.util.*;//自己创建一个比较器class StuNameComparator implements Comparator {public int compare{int num = st1.getName.compareTo;if{return new Integer.compareTo);}return num;}}class MapTest2 {public static void main{ //将比较器传进来TreeMap tm = new TreeMap ;tm.put,"beijing");tm.put,"shanghai");tm.put,"nanjing");tm.put,"wuhan"); Set > entrySet = tm.entrySet; Iterator > it = entrySet.iterator; while{Map.Entry me =it.next; Student stu = me.getKey;String add = me.getValue; System.out.println;}}}16-08注意了,当发现有映射关系时,可以选择map集合。因为map集合中存放的就是映射关系什么时候使用map集合呢?当数据之间存在着映射关系时,就要先想到map集合。练习package test;/**练习:* "sdfgzxcvsdfxcvdf"获取该字符串中的字母出现的次数。* * 希望打印结果:ac....* * @author tingzi*通过结果发现,每一个字母都有对应的次数。*说明字母和次数之间都有对应关系。**分析:第一次用a字符作为键去找集合。那么集合没有a这个键,所以也没有对应的次数。返回null。*如果为null,就将a字母和1存入集合。*如果指定的键已经存在,说明有对应的次数,就将对应的次数取出,并自增厚再重新存入集合**思路:*1,将字符串转换成字符数组。因为要对每一个字母进行操作。**2,定义一个map集合,因为打印结果的字母有顺序,所以要使用treemap集合。**3,遍历字符数组。* 将每一个字母作为键去差map集合。* 如果返回null,说明该字母在和1存入到map集合中。* 如果返回不是null,说明该字母在map集合已经存在并有对应次数* 那么就获取该次数并进行自增,然后将该字母和自增厚的次数存入到map集合中,覆盖调用原来键所对应的值**4,将map集合中的数据变成指定的字符串形式返回。*/import java.util.*;class MapTest3 {public static void main{String st = charCount;System.out.println;}public static String charCount{char chs = str.toCharArray; TreeMap tm = new TreeMap ; int count = 0;for{//判断如果不是字符串则继续循环if)continue; Integer value = tm.get; ifcount = value;count++;tm.put; //因为已经赋值,所以要进行清零,否则下一个字母进入之后,用的仍是原来的countcount = 0; /*此处的与上面的判断数组的方式是一样的if{tm.put;}else{value = value +1;tm.put;}*/}//System.out.println; StringBuilder sb = new StringBuilder; Set > entrySet = tm.entrySet;Iterator > it =entrySet.iterator; while{Map.Entry me = it.next;Character ch = me.getKey;Integer value = me.getValue;sb.append");} return sb.toString;} }16-09Map扩展知识package demo3;import java.util.HashMap;import java.util.Iterator;/*** map集合被使用是因为具备映射关系.* * "yureban" "01" "zhangsan"* "yureban" "02" "lisi";* * "jiuyeban" "01" "wangwu"* "jiuyeban" "02" "zhaoliu"**一个学校有多个教室。每一个教室都有名称*/class MapDemo3 {public static void main{//第一步应该创建学校HashMap > czbk = new HashMap >; //班级,预热班HashMap yure = new HashMap ;//班级,就业班HashMap jiuye = new HashMap ; //学校与班级的关系czbk.put;czbk.put;//预热班中学生学号与学生姓名的关系yure.put;yure.put; //就业班中学生学号与学生姓名的关系jiuye.put;jiuye.put; //打印预热班级所有的学生//getStudentInfo; //打印就业班既所有的学生//遍历czbk集合,获取所有的教室Iterator it = czbk.keySet.iterator; while{String roomName = it.next;HashMap room = czbk.get;//打印教室System.out.println; //打印教室中的学生即可getStudentInfo;}} //想要取出某个班级所有的学生,要告诉我学校,以及学校学生public static void getStudentInfo{Iterator it = roomMap.keySet.iterator; while{String id = it.next;String name = roomMap.get;System.out.println;}}}package demo3;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;/*** map集合被使用是因为具备映射关系.* * "yureban" Student;* "yureban" Student;* * "jiuyeban" "01" "wangwu"* "jiuyeban" "02" "zhaoliu"**一个学校有多个教室。每一个教室都有名称*/class Student{private String id;private String name;Student{this.id = id;this.name = name;}public String toString{return id+":::"+name;}}class MapDemo3 { public static void demo{HashMap > czbk = new HashMap >; List yure = new ArrayList ;List jiuye = new ArrayList ; czbk.put;czbk.put; yure.add);yure.add); jiuye.add);jiuye.add); Iterator it = czbk.keySet.iterator; while{String roomName = it.next;List room = czbk.get; System.out.println;getInfos;}}public static void getInfos{Iterator it = list.iterator;while{Student s = it.next;System.out.println;}} public static void main{demo;} //想要取出某个班级所有的学生,要告诉我学校,以及学校学生public static void getStudentInfo{Iterator it = roomMap.keySet.iterator; while{String id = it.next;String name = roomMap.get;System.out.println;}} }坏亭子--2013/04/1217-10集合框架工具类Collections-sortCollections,都是静态的举个例子class Student{}list.add;//备注一下,下面的T代表Student//sort中的T必须进行比较性,所以就对T进行了一下泛型限定T必须是Comparable的子类,而且Comparable也带着泛型//为了让比较性更强,所以Comparable的泛型也可以是T的父类。因此出现了: >//这个也叫泛型定义时的限定public static > void sort{}import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;class CollectionsDemo {public static void main{ sortDemo;}public static void sortDemo{List list = new ArrayList ;list.add;list.add;list.add;list.add;list.add;list.add;list.add; sop; //Collections.sort;sop;Collections.sort;sop;}public static void sop{System.out.println;}}//比较器,按照长度排序,从小到大class StrLenComparator implements Comparator {public int compare{ifreturn 1;ifreturn -1;//如果长度相等,就进行字母排序return s1.compareTo;}}17-11Collections-max返回最大值//可以将字段代码直接防止到17-10当中//max返回顺序中的最大值public static void maxDemo{List list = new ArrayList ;list.add;list.add;list.add;list.add;list.add;list.add;list.add; //原来的自然排序Collections.sort;sop;//备注里面的是按照自定义的将最小的排序方法String max = Collections.max;sop;}17-12Collections-binarySearch查找角标。//binarySearch原理public static int halfSearch{int max,min,mid;max = list.size-1;min = 0;while{mid = >>1;//获取中间角标对应的元素String str = list.get;// /2//字符串可以进行比较,并返回一个值int num = str.compareTo;ifmax = mid -1;else if min = mid +1;elsereturn mid;} return -min-1;}//------原理结束 //binarySearch原理2,如果传过来的没有比较性质,那么,要进行自定义比较器比较Comparator cmp是传来的自定义比较器public static int halfSearcp{int max,min,mid;max = list.size-1;min = 0;while{mid = >>1; String str = list.get;//这里有变动int num = cmp.compare;ifmax = mid -1;else if min = mid +1;elsereturn mid;} return -min-1;}//------原理2结束17-13Collections-替换反转fill,将集合中的元素全部都替换成xx例如:public static void fillDemo{List list = new ArrayList ; list.add;list.add;list.add;list.add;sop;Collections.fill;sop; }//打印结果:/** 练习,fill方法可以将list集合中所有元素替换成指定元素* 需求:将list集合中部分元素替换成元素*/import java.util.*;class CollectionsTest2 {public static void main {List list = new ArrayList ;list.add;list.add;list.add;list.add; fillTest;}//list:集合;start:开始的元素;end:结束元素,不包含end;str:指定元素public static void fillTest{try{//获取角标start到end的元素,不包括endList al = list.subList;sop;//替换指定元素Collections.fill;}//捕获范围异常catch{throw new IndexOutOfBoundsException;} //打印输出sop;}public static void sop{System.out.println;} }Collection-replaceAll,替换,//用老值替换新值public static void repaceAllDemo{List list = new ArrayList ; list.add;list.add;list.add;list.add;//集合,老值,新值Collections.replaceAll;sop;}Collection-reverse,反转//将集合中的元素反转public static void reverseDemo{List list = new ArrayList ; list.add;list.add;list.add;list.add;sop;Collection.reverse;sop;}17-14Collection-reverseOrder强行逆转的比较器这玩应超级嗨!!^_^/比如17-10中的StrLenComparator按照长度比较是从小到大。那么我要是想从大到小的长度我可以直接这个样子TreeSet ts = new TreeSet );import java.util.Collections;import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;class CollectionDemo2 {public static void main{orderDemo;}public static void orderDemo{//TreeSet ts = new TreeSet ;//直接传一个逆向比较器Collections.reverseOrderTreeSet ts = new TreeSet );ts.add;ts.add;ts.add;ts.add; Iterator it = ts.iterator; while{sop;}}public static void sop{System.out.println;}}//重写比较器,让数据反转class StrLenComparator implements Comparator {public int compare{/* int num = s1.compartTo;* if* return -1;* if* return 1;* return num;*/return s2.compareTo;}}17-15Collection-SynListstatic List synchronizedList 返回指定列表支持的同步列表。 顺便说一下将指定角标i与角标j更换位置swapCollection-shuffle//将集合中的元素随机变换public static void reverseDemo{List list = new ArrayList ; list.add;list.add;list.add;list.add;sop;Collection.shuffle;sop;}17-16Arrays:用于操作数组的工具类。里面都是静态方法.binarySearch:二分查找例如:binarySearch copyOf:复制指定的数组例如:copyOf copyOfRange:复制一定范围例如:copyOfRangeequals:比较两个数组中的内容是否相同例如:equals deepEquals:深度比较,就是说不仅仅比较数组,还比较数组中元素的内容例如:deepEquals fill:替换数组中的值例如:fill hashCode:获取数组中的哈希值例如:hashCode 基于指定数组的内容返回哈希码。sort:排序例如:sort 对指定的 byte 型数组按数字升序进行排序。toString:返回字符串例如:toString 返回指定数组内容的字符串表示形式。import java.util.Arrays;class ArraysDemo {public static void main{int arr ={2,3,4};//将数组中的元素转换成字符串打印输出System.out.println);}}!!!!!!!!!!!!重点在这里!!!!!!!!!!!!asList:将数组变成List集合注释:a - 支持列表的数组/*把数组变成list集合有什么好处?* 可以使用集合的思想和方法来操作数组中的元素。* 注意:将数组变成集合,不可以使用集合的增删方法* 因为数组的长度是固定的。* 可以使用contains,get,indexOf,subList;都可以用* 如果使用增删,会发生UnsupportedOperationException*//*如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素*如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在*/ package demo;import java.util.Arrays;import java.util.List;class ArraysDemo {public static void main{//int arr ={2,3,4};//将数组中的元素转换成字符串打印输出//System.out.println); String arr = {"abc","cc","fff"}; /*把数组变成list集合有什么好处?* 可以使用集合的思想和方法来操作数组中的元素。* 注意:将数组变成集合,不可以使用集合的增删方法* 因为数组的长度是固定的。* 可以使用contains,get,indexOf,subList;都可以用* 如果使用增删,会发生UnsupportedOperationException*/ List list = Arrays.asList; //变成集合之后可以直接判断是否有cc这个元素sop);sop; //特殊数组int nums = {2,4,5};List li =Arrays.asList;sop; Integer numss = {1,2,3};List lii = Arrays.asList;sop;/*如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素*如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在* */}//如果不变成集合的话,要这么写public static boolean myCotains{for{if)return true;}return false;} public static void sop{System.out.println;}}17-17集合转成数组1,指定类型的数组到底要定义多长呢?当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组,长度为size当制定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组所以创建一个刚刚好的数组最优:new String2,为什么要将集合变数组?为了限定对数组的操作,不需要进行增删了.import java.util.ArrayList;import java.util.Arrays;class CollectionToArray {public static void main{ArrayList al = new ArrayList ; al.add;al.add;al.add; String arr = al.toArray;System.out.println);}}17-18高级for循环格式:for或数组){}注意:对集合进行遍历,只能获取元素,但是不能对集合进行过多的操作迭代器除了遍历,还可以进行remove集合中元素的动作.如果使用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。传统for和高级for有什么区别呢?高级for有一个局限性,必须有被遍历的目标。建议在遍历数组的时候,还是希望用传统for,因为传统for可以定义角标package demo;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;import java.util.Set;class ForEachDemo {public static void main{ ArrayList al = new ArrayList ; al.add;al.add;al.add; for{System.out.println;} //数组也可以哦int arr = {3,4,5};for{System.out.println;} HashMap hm = new HashMap ; hm.put;hm.put;hm.put; //第一种方式Set keySet = hm.keySet;for{System.out.println);}//第二种方式//Set > entrySet = hm.entrySet;//for//这里的类型,Set里面存啥类型,就写啥类型for{System.out.println;}}}17-19可变参数JDK1.5版本出现的新特性:方法的可变参数.在使用时注意:可变参数一定要定义在参数列表的最后面package demo;class ParamMethodDemo {public static void main{/*//show;int arr = {3,4};show; int arr1 = {3,4,5,6,7};show;*/ /** 可变参数.* 其实就是上一种数组参数的简写形势。* 不用每一次都手动的建立数组对象。* 只要将要擦uozuode数组作为参数传递即可。* 隐式将这些暑促封装成了数组*/show; }public static void show{System.out.println;}/*public static void show{ }*//*public static void show{System.out.println;} */}17-20静态导入当类名重名时,需要指定具体的包名。当方法重名时,指定具体所属的对象或者类如果没写satic,倒入的都是类写了static的时候,倒入的都是某一个类中的静态成员.package demo;import java.util.Arrays;import static java.util.Arrays.*;//倒入的是Arrays这个类中的所有静态成员import static java.lang.System.*;//倒入了静态的输入class StaticImportDemo //extends Object{public static void main{int arr = {3,1,5}; //排序sort;//Arrays.sort;//二分查找,注意下哈,必须排序了之后才能二分查找int index = binarySearch;//Arrays.binarySearch;//变成字符串打印sop);//注意!,这里不行,因为继承的是Object类,因为Object类中也有toString方法sop;}public static void sop{out.println;//System.out.println;}}坏亭子 ---2013/04/1318-01其他对象 java.lang.包中Properties在 java.util.包中/**System:类中的方法和属性都是静态的* out:标准输出,默认是控制台* in :标准输入,默认是键盘* 描述系统一些信息* * 获取系统属性信息 :Properties getProperties;*/因为Properties是Hashtable的子类,也就是Map集合中的一个子类那么可以通过map的方法取出该集合中的元素.该集合存储的都是字符串,没有泛型定义//打印输出系统信息class SystemDemo {public static void main{Properties prop = System.getProperties;//获取所有属性信息for{String value = prop.get;System.out.println;}}}如何在系统中设置一些信息呢?setPropertySystem.setProperty;//可不可以在jvm启动时,动态加载一些属性信息呢?//答曰:java -D = //例如,java -Dhaha=qqqq SystemDemo//就会输出:v=qqqqString v = System.getProperty; System.out.println;//结果为v=null18-02其它对象 java.lang包当中每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取运行时,应用程序不能创建自己的Runtime类实例。该类中并没有提供构造函数。说明不可以 new对象。那么可以直接想到该类中的方法都是静态的。发现该类中还有非静态方法。说明该类中肯定会提供了方法获取本类对象。而且该方法是静态的,并且返回值类型是本类类型。由这个特点可以看出,该类使用了单例设计模式完成。该方法是static Runtime getRuntime/*内容如下:* 运行进程* 等待* 杀死进程*/class RuntimeDemo {public static void mainthrows Exception{//调用getRuntime方法,返回值类型依然为RuntimeRuntime r = Runtime.getRuntime; //调用运行程序,注意异常!!由于异常是IOException,但是导包麻烦,这里就先抛出了ExceptionProcess p = r.exec; //等待//Thread.sleep;//杀死进程p.destroy;}}18-03其它对象 java.util.包中TimeZoneDateFormatSimpleDateFormat java.text.包中说几个参数y M w W D d F E a H kKhm s S z Z简单点哈yyyy年MM月dd日E hh:mm:ssimport java.text.SimpleDateFormat;import java.util.Date;class DateDemo {public static void main{//获取当前系统时间Date d = new Date; //自定义时间格式SimpleDateFormat sdf = new SimpleDateFormat; //调用format方法格式化时间格式String time = sdf.format; //显示时间System.out.println; }}18-04其它对象- java.util.包中package demo;/*获取年月日* */import java.util.Calendar;class CalendarDemo {public static void main{Calendar c = Calendar.getInstance; //利用查表法,输出格式为大写月份,大写星期//月份表String months = {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"};//星期表String weeks = {"星期六","星期日","星期一","星期二","星期三","星期四","星期五"}; int mon = c.get;int we = c.get; //获取年sop+"年"); //获取月//sop+1)+"月");sop;//获取日sop+"日"); //获取星期//sop-1));sop; }public static void sop{System.out.println;}}package demo;/** 设置年月份*/import java.util.Calendar;class CalendarDemo2 {public static void main{Calendar c = Calendar.getInstance; //设置日期为2012年3月23号, 注意,2代表的是3月//c.set; //在今天的基础上往前推18天c.add; printCalendar; }public static void printCalendar{//利用查表法,输出格式为大写月份,大写星期//月份表String months = {"一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"};//星期表String weeks = {"星期六","星期日","星期一","星期二","星期三","星期四","星期五"}; int mon = c.get;int we = c.get; //获取年sop+"年"); //获取月//sop+1)+"月");sop;//获取日sop+"日"); //获取星期//sop-1));sop;}public static void sop{System.out.println;}}/*两个练习:1,获取任意年的二月有多少天思路:根据制定年花色之一个时间就是 c.set//某一年的3月1日c.add;//3月1日,往前一天,就是2月最后一天2,获取昨天的现在的时间c.add自己再添一个:3,获取某一段时间内的工作日*/18-05其它对象 java.lang包中static double abc返回绝对值static double ceil//返回大于指定数据的最小整数double d = Math.ceil;sop;//16.0static double floor//返回指定数据的最大整数floor d1 = Math.floor;sop;//15.0static long round//四舍五入static double pow//a的b次方!!!!static double random//随机数!!大于等于0,且小于1random 在java.util.包中也有。而且可以创建对象/*练习: 给定一个小数。保留该小数的后两位*/18-06IO流1,IO流用来处理设备之间的数据传输2,Java对数据的操作都是通过流的方式3,Java用于操作流的对象都在IO包中4,流按操作数据分两种:字节流,字符流5,流按流向分:输入流,输出流注意:4个都是抽象的字节流的抽象对象:InputStream,OutputStream字符流的抽象基类:Readr,Writeroo 子类的结尾都是以这4个类作为后缀名的如:InputStream的子类FileInputStream再如:Reader的子类FileReader18-07IO流,用于写入字符文件的便捷类先学习一下字符流的特点既然IO流是操作数据的,那么数据的最常见体现形式是:文件。那么先以操作文件为主,来演示。需求:在硬盘上创建一个文件并写入一些文字数据.找到一个专门用于操作文件的Writer子类对象。FileWriter 后缀名是父类名,前缀名是该流对象的功能步骤:首先第一步:创建一个FileWriter对象。该对象一被初始化,就必须要明确要被操作的文件。FileWriter fj = new FileWriter;第二步:调用write方法,将字符串写入到流中fw.write;第三步:刷新流对象中的缓冲中的数据。将数据刷新到目的地中fw.flush;//这一步一般可以不写第四步:关闭流fw.close;package demo2;import java.io.*;class FileWriterDemo {public static void mainthrows IOException{//第一步:创建一个FileWriter对象。该对象一被初始化,就必须要明确要被操作的文件。//而且该文件会创建到指定的目录下,如果该目录下已有同名文件,将被覆盖//其实该步就是在明确数据要存放到目的地FileWriter fw = new FileWriter; //第二步:调用write方法,将字符串写入到流中fw.write; //第三步:刷新流对象中的缓冲中的数据。//将数据刷新到目的地中fw.flush; fw.write; fw.flush;//第四步,关闭资源,但是关闭之前会刷新一次内部的缓冲中的数据//将数据刷新到目的地中,和flush的区别://flush刷新后可以继续使用close刷新后,会将流关闭fw.close;}}18-08IO异常处理方式package demo2;/** IO异常处理方式*/import java.io.FileWriter;import java.io.IOException;class FileWriteDemo2 {public static void main{ FileWriter fw = null;try{//这里需注意的是,写盘符一定要两个比如:c:demo.txtfw = new FileWriter; fw.write;}catch{System.out.println;}finally{try//fw.close;也有异常,所以要继续捕获{if//一定要判断不为空{fw.close;}}catch{System.out.println;}}}}18-09IO流import java.io.FileWriter;import java.io.IOException;/** 演示:对已有文件的续写*/class FileWriteDemo3 {public static void main{FileWriter fw = null; try{//续写文件,truefw = new FileWriter;//注意,记事本想换行要这个样子rnfw.write;}catch{System.out.println;}finally{try{if{fw.close;}}catch{ }}}}18-10IO流import java.io.FileReader;import java.io.IOException;class FileReaderDemo {public static void mainthrows IOException{//创建一个文件读取流对象,和制定名称的文件相关联//要保证文件是已经存在的,如果不存在,会发生异常FileNotFoundExceptionFileReader fr = new FileReader; //调用读取流对象的read方法。//read:一次读一个字符。而且会自动往下读 int ch = 0;while!=-1){System.out.printlnch);}/*while{int ch = fr.read;ifbreak;System.out.printlnch);}*/fr.close;}}18-11IO流//读取一个.java文件,并打印在控制台上import java.io.*;class FileReaderTest1 {public static void mainthrows IOException{FileReader fr = new FileReader;//一般定义都定义为1024的整数倍char cha = new char; int num = 0;//将字符数组长度给numwhile)!=-1){ //字符数组,开始,结束System.out.print);}fr.close;}}18-12练习-----读取一个.java文件,并打印在控制台上import java.io.*;class FileReaderTest1 {public static void mainthrows IOException{FileReader fr = new FileReader;//一般定义都定义为1024的整数倍char cha = new char; int num = 0;//将字符数组长度给numwhile)!=-1){ //字符数组,开始,结束System.out.print);}fr.close;}}18-13拷贝文本文件将C盘一个文本文件赋值到D盘原理:其实就是将C盘下的文件数据存储到D盘的一个文件中。步骤:1,在D盘创建一个文件。用于存储C盘文件中的数据。2,定义读取流和C盘文件关联。3,通过不断的读写完成数据存储。4,关闭资源package test2;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;class CopyTest {//从C盘独一个字符,就往D盘写一个字符。这种方式不建议public static void copy_1throws IOException{//创建目的地,写到此处FileWriter fw = new FileWriter; //与已有文件关联。FileReader fr = new FileReader; int ch = 0; while!=-1){fw.write;}fw.close;fr.close; }//第二种方式public static void copy_2{FileWriter fw = null;FileReader fr = null;try{fw = new FileWriter;fr = new FileReader; char buf = new char; int len = 0;while)!=-1){fw.write;}}catch{throw new RuntimeException;}finally{iftry{fr.close;}catch {}iftry{fw.close;}catch {}} }public static void mainthrows IOException{copy_1;copy_2;} }18-14图例,略....个人总结文字来讲解图:硬盘上的文件---通过fr.read--→char abcdef缓冲区----fw.write-----→new FileWriter.txt注意,最后一步调用完流要进行关闭。19-01IO流-BufferedWriter缓冲区的出现是为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要现有流对象。该缓冲区中提供了一个跨平台的换行符方法newLine;步骤1,创建字符写入流对象2,为了提高字符写入流效率。加入了缓冲技术.只需要将被提高效率的流对象作为参数传递给缓冲区的构造函数即可。3,将数据写入4,记住,只要用到缓冲区,就要记得刷新5,其实,关闭缓冲区,就是在关闭缓冲区中的流对象import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;/**IO流-BufferedWriter演示* @author tingzi*/class BufferedWriterDemo {public static void mainthrows IOException{//创建一个字符流对象buf.txtFileWriter fw = new FileWriter; //加入缓冲技术BufferedWriter bw = new BufferedWriter; //演示换行newLinefor{bw.write;bw.newLine;bw.flush;} //关闭缓冲区bw.close;}}19-02IO流-BufferedReader字符流读取缓冲区该缓冲区中提供了一个一次读一行的方法readLine,方便对文本数据的获取当返回null时,表示读到文件末尾.readLine方法返回的时候值返回回车符之前的数据内容,并不返回回车符步骤1,创建一个读取流对象和文件相关联。2,为了提高效率。加入缓冲技术。将字符读取流作为对象传递给缓冲对象的构造函数import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;/*** 演示BufferedReader* @author tingzi**/class BufferedReaderDemo {public static void mainthrows IOException{//创建一个读取流对象FileReader fr = new FileReader; //创建一个读的流缓冲区对象BufferedReader br = new BufferedReader; //演示一行一行读的方法readLine;String line = null;while!=null){System.out.println;} //关闭缓冲区br.close;}}19-03/*** 通过缓冲区复制.java文件* @author tingzi*/package test;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;class CopyTestByBuf1 {public static void mainthrows IOException{//创建一个字符流缓冲区bwBufferedWriter bw = null;//创建一个读取流缓冲区brBufferedReader br = null; //写bw = new BufferedWriter);//读br = new BufferedReader);//中转站lineString line = null; try{while!=null){bw.write;bw.newLine;bw.flush;}}catch{System.out.println;}finally{try{if{bw.close;}}catch{System.out.println;}try{if{br.close;}}catch{System.out.println;}}}}19-04readLine方法原理无论读取一行,获取读取多个字符。其实最终原理都是在硬盘上一个一个读去。所以最终使用的还是read方法一次读一个的方法也就是说,我先读数据,读完之后存到缓冲区当中。遇到n,我就输出19-05IO流-MyBufferedReadimport java.io.FileReader;import java.io.IOException;/**明白了BufferedReader类中特有方法readLine的原理后*可以自定义一个类中包含一个功能和readLine一致的方法。*来模拟一下BufferedReader*/class MyBufferedReader{//因为要基于FileReader的方法,所以要把FileReader方法传进来 //因为要作用于整个类的话,所以定义一个成员变量 private FileReader r ;//一初始化就有一个流对象进来MyBufferedReader{this.r = r;} //可以一次读一行的方法public String myReadLinethrows IOException{//定义一个临时容器,原BufferReader中封装的是字符数组。//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串StringBuilder sb = new StringBuilder;int ch = 0;while!=-1){//如果读到的是r就继续循环ifcontinue;ifreturn sb.toString;else//读一个字符就存到缓冲区当中sb.appendch);}ifreturn sb.toString; return null;}public void myClosethrows IOException{r.close;}}class MyBufferedReaderDmeo{public static void mainthrows IOException{//创建一个读取对象FileReader fr = new FileReader; //创建一个读的流缓冲区对象MyBufferedReader br = new MyBufferedReader; //演示一行一行读的方法readLine;String line = null;while!=null){System.out.println;} //关闭缓冲区br.myClose;}}19-06IO流-装饰设计模式装饰设计模式:当想要对以后的对象进行功能增强时。可以定义类,将已有对象传入,基于以后的功能,并提供加强功能。那么自定义的该类就称为:装饰类装饰类通常会通过构造方法接受被装饰的对象。并基于被装饰的对象功能,提供更强的功能。class Person{public void chifan{System.out.println;}}//来一个为了增强吃饭的东东class SuperPerson{//首先,先创建要装饰的对象成员private Person p;//通过构造函数,调用被装饰对象SuperPerson{this.p = p;}public void supchifan{System.out.println;p.chifan;System.out.println;}}class PersonDemo {public static void main{Person p = new Person;//p.chifan;SuperPerson sp = new SuperPerson;sp.supchifan;}}19-07IO流-装饰和继承的区别MyReader//专门用于读取数据的类.|---MyTestReader|---MyBufferTextReader|---MyMediaReader|---MyBufferMediaReader|---MyDataReader|---MyBufferDataReaderclass MyBufferReader{MyBufferReader{}MyBufferReader{}MyBufferReader{}}//上面这个类扩展性很差。找到其参数的共同类型。通过多态的形势。可以提高扩展性。class MyBufferReader extends MyReader{private MyReader r;MyBufferReader{}}MyReader//专门用于读取数据的类.|---MyTestReader|---MyMediaReader|---MyDataReader|---MyBufferReader装饰模式比继承要灵活。避免了继承体系的臃肿。而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的。只不过提供了更强功能。所以装饰类和被装饰类通常都是一个体系当中的。19-08IO流-自定义装饰类也就是说,不知道自己如何定义的时候,就覆盖掉父类中的方法,但是引用的方法,跟父类的一样。/** 覆盖Reader类中的抽象方法*/public int readthrows IOException{return r.read;}public void closethrows IOException{r.close;}19-09IO流-LineNumberReaderDemosetLineNumber;//设置行号getLineNumber;//获取行号import java.io.FileReader;import java.io.IOException;import java.io.LineNumberReader;class LineNumberReaderDemo {public static void mainthrows IOException{FileReader fr = new FileReader; LineNumberReader lnr = new LineNumberReader;lnr.setLineNumber;//从100行开始String line = null;while!=null){System.out.println;}lnr.close;}}//练习:模拟一个带行号的缓冲区对象myLineNumberReader19-10MyLineNumberReaderimport java.io.FileReader;import java.io.IOException;import java.io.Reader;//简化版class MyLineNumberReader extends MyBufferedReader{private int lineNumber;MyLineNumberReader{super;} public String myReaderLinethrows IOException{lineNumber++;return super.myReadLine;}public void setLineNumber{this.lineNumber = lineNumber;}public int getLineNumber{return lineNumber;} }/*class MyLineNumberReader{private Reader r;private int lineNumber;MyLineNumberReader{this.r = r;} public String myReadLinethrows IOException{lineNumber++;StringBuilder sb = new StringBuilder;int ch = 0;while!=-1){ifcontinue;ifreturn sb.toString;sb.appendch);}ifreturn sb.toString;return null;} public void setLineNumber{this.lineNumber= lineNumber;}public int getLineNumber{return lineNumber;} public void myClosethrows IOException{r.close;}}*/class MyLineNumberReaderDemo {public static void mainthrows IOException{FileReader fr = new FileReader; MyLineNumberReader mnr = new MyLineNumberReader; String line = null;while!=null){System.out.println;}mnr.myClose;}}19-11IO流-字节流File读写操作字符流:FileReaderFileWriterBufferedReaderBufferedWriter字节流:InputStreamOutputStreamBufferedInputSreamBufferedOutputSreamimport java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/*需求:想要操作图片数据。这时就要用到字节流* */class FileStreamDemo {//读3,FileInputStream的特有方法a.available;public static void readFile_3throws IOException{FileInputStream fis = new FileInputStream; //int num = fils.available; byte buf = new byte;//定义一个刚刚好的缓冲区,不用再次循环了 fis.read; System.out.println); fis.close; }//读2,注意,一般情况下用这种方法public static void readFile_2throws IOException{FileInputStream fis = new FileInputStream; byte buf = new byte;int len = 0;while)!=-1){System.out.println);}fis.close;} //读1public static void readFile_1throws IOException{FileInputStream fis = new FileInputStream; int ch = 0;while!=-1){System.out.printch);}fis.close;} //写public static void wirteFilethrows IOException{FileOutputStream fos = new FileOutputStream; fos.write; fos.close;} //主函数public static void mainthrows IOException{wirteFile;}}19-12IO流-拷贝图片package demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/*** 复制一个图片* 思路:* 1,用字节流读取流对象和图片关联* 2,用字节写入刘对象创建一个图片。用于存储获取到的图片数据。* 3,通过循环读写,完成数据的存储。* 4,关闭资源* @author Chen_zyan**/class CopyPic {public static void mainthrows IOException{copyPic;}//复制文件public static void copyPicthrows IOException{String s = "副本_";//创建滴FileOutputStream fos = null; //源文件FileInputStream fis = null; try{fos = new FileOutputStream;fis = new FileInputStream; byte buf = new byte;int ch = 0;while)!=-1){fos.write;}}catch{System.out.println;}finally{try{iffis.close;}catch{System.out.println;} try{iffos.close;}catch{System.out.println;}}} }19-13IO流-字节流的缓冲区import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;/**演示mp3的复制* BufferedOutputStream//写* BufferedInputStream//读* @author Chen_zyan**/class CopyMp3 {public static void mainthrows IOException{long start = System.currentTimeMillis;copy_1;long end = System.currentTimeMillis; System.out.println+"毫秒");}//通过字节流的缓冲区完成复制.public static void copy_1throws IOException{ BufferedInputStream bufis = new BufferedInputStream - 群星.mp3"));BufferedOutputStream bufos = new BufferedOutputStream - 群星_1.mp3")); int by = 0;while!=-1){bufos.write;}bufos.close;bufis.close;}//通过自定义字节流的缓冲区完成复制.public static void copy_2throws IOException{ MyBufferedInputStream bufis = new MyBufferedInputStream - 群星.mp3"));BufferedOutputStream bufos = new BufferedOutputStream - 群星_2.mp3")); int by = 0;while!=-1)//自动做了一个类型提升,byte => int{bufos.write;//自动做了一个类型降低,int=>byte//}bufos.close;bufis.myClose;}}19-14IO流-自定义字节流的缓冲区-read和write的特点1,定义数组2,定义指针3,定义计数器import java.io.IOException;import java.io.InputStream;/*** 自定义一个MyBfuueredInputStream* @author Chen_zyan**/class MyBufferedInputStream {private InputStream in; private byte buf = new byte; //定义指针pos 计数器countprivate int pos = 0,count = 0; MyBufferedInputStreamthrows IOException{this.in = in;} //一次读一个字节,从缓冲区获取public int myReadthrows IOException{//通过in对象读取硬盘上的数据,并存储到buf中.if{count = in.read;pos = 0;//取完之后,指针要归零if//如果计数器小于0了,说明就取完了return -1;byte b = buf; count--;pos++;return b&255;//这里是为了将byte提升为int类型,但是只保留后八位 }else if{byte b = buf; count--;pos++;return b&255;//这里是为了将byte提升为int类型,但是只保留后八位 }return -1;}public void myClosethrows IOException{in.close;} }19-15IO流-读取键盘录入-!!!!System.out:对应的是标准的输出设备,控制台System.in:对应的标准的输入设备:键盘public static void method_2throws IOException{InputStream in = System.in; StringBuilder sb = new StringBuilder; while{//将字符串存储到ch中int ch = in.read;if//如果遇到r再循环一次continue;if//如果遇到n就进行输出{String s = sb.toString;if)break;System.out.println;//转换成大写输出 //进行清空缓冲区sbsb.delete;}else//如果没按回车,就继续存入到sb缓冲区中,因为存入的是int,所以强转成字符串sb.appendch);} }19-16IO流-读取转换 InputStreamReader通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理,也就是readLine方法。能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中的方法而键盘录入的read方法是字节流InputStream的方法.那么能不能将字节流转换成字符流,再使用字符流缓冲区的readLine方法呢?/*** 将字节流转换成字符流对象,进行操作,提高效率*/import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;class TransStreamDemo {public static void mainthrows IOException{//获取键盘录入对象InputStream in = System.in; //将字节流对象转成字符流对象,使用转换流InputStreamReaderInputStreamReader isr = new InputStreamReader; //为了提高效率,将字符串进行缓冲区操作,使用BufferedReaderBufferedReader bufr = new BufferedReader; String line = null; //如果不等于空,那么就进行读while!=null){if){break;}System.out.println;}bufr.close;}}19-17IO流-读取转换 OutputStreamWriter//InputStream is = System.in;//InputStreamReader isr = new InputStreamReader;//BufferedReader bufr = new BufferedReader; //以上三句话,简写:,最常见的键盘录入!!!!!!!!!!!!!!!一定要记住BufferedReader bufr = new BufferedReader); //OutputStream out = System.out;//OutputStreamWriter osw = new OutputStreamWriter;//BufferedWriter bufw = new BufferedWriter;//以上三句话,简写:输出BufferedWriter bufw = new BufferedWriter); //System.out.println;//输出,可以写成下面的三句话bufw.write;bufw.newLine;bufw.flush;19-18IO流-流操作常规规律-1流操作的基本规律:最痛过苦的就是:流对象有很多,不知道该用哪一个通过三个明确来完成。1,明确源和目的。源:输入流,InputStream Reader目的:输出流,OutputStream Writer2,操作的数据是否是纯文本是:用字符流,Reader、Writer不是:字节流3,当体系明确后,再明确要使用哪个具体的对象。通过设备来区分;源设备:内存,硬盘,键盘目的设备:内存,硬盘,控制台1,将一个文本文件中的数据存储到另一个文件中。复制文件。源:因为是源,所以使用读取流。InputStream Reader是不是操作文本文件?是:所以这时选择Reader这样体系就明确了接下来明确要使用该体系中的哪个对象。明确设备:硬盘上的一个文件。Reader体系中可以操作文件的对象是FileReader 是否需要提高效率?是,加入Reader体系中的缓冲区BufferedRaderFileReader fr = new FileReaderBufferedReader bufr = new BufferedRader; ------目的:OutputStream Writer是否是纯文本?是,Writer明确设备:硬盘,一个文件。Writer体系中可以操作文件的对象是FileWriter 是否需要提高效率?是,加入Writer体系中的缓冲区BufferedWriterFileWriter fw = new FileWriter;BufferedWriter bw = new BufferedWriter练习:将一个图片中数据存储到另一个文件中。复制文件。要按照以上格式,自己完成三个明确//此处为说明输入输出源,以及目的,并非练习答案package demo;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;/*** 1,* 源:键盘录入* 目的:控制台* * 2,需求:想把键盘录入的数据存储到一个文件中* 源:键盘* 目的:文件* * 3,需求:想要将一个文件的数据打印在控制台上* 源:文件* 目的:控制台* @author Chen_zyan**/class TransStreamDemo2 {public static void mainthrows IOException{//text_1;text_2;//text_3;}//需求1public static void text_1throws IOException{BufferedReader bufr= new BufferedReader); BufferedWriter bufw = new BufferedWriter); String line = null;while!=null){if)break;bufw.write;bufw.newLine;bufw.flush;}}//需求2public static void text_2throws IOException{BufferedReader bufr = new BufferedReader); BufferedWriter bufw = new BufferedWriter)); String line = null;while!=null){if)break;bufw.write;bufw.newLine;bufw.flush;}bufr.close;}//需求3public static void text_3throws IOException{BufferedReader bufr = new BufferedReader)); BufferedWriter bufw = new BufferedWriter); String line = null;while!=null){if){break;}bufw.write;bufw.newLine;bufw.flush;}bufr.close;}}19-19IO流-操作规律-22,需求:将键盘录入的数据保存到一个文件中这个需求中,有源和目的都存在。那么分别分析,源:InputStream Reader 是不是纯文本?是,Reader 设备:键盘,对应的对象是System.in不是选择Reader吗?System.in对应的不是字节流么?为了操作键盘的文本数据方便。转成字符流按照字符串操作,最方便。所以,既然明确了Reader那么就将System.in转换成Reader用到了Reader体系中的转换流,InputStreamReaderInputStreamReader isr = new InputStreamReader;需要提高效率么?需要! BufferedReaderBufferedReader bufr = new BufferedReader;-----目的:OutputStream Writer是否是纯文本?Writer.设备:硬盘,一个文件。使用FileWriter.FileWriter fw = new FileWriter; 需要提高效率么?需要BufferedWriterBufferedWriter bufw = new BufferedWriter;重要0.0扩展一下,想要把录入的数据按照制定的编码表,将数据存到文件中。目的:OutputStream Writer是否是纯文本?Writer.设备:硬盘,一个文件。使用FileWriter.但是FileWriter是使用的默认编码表,GBK 但是存储时,需要加入制定的编码表utf-8,而制定的编码表只有转换流可以制定。所以要使用的对象是OutputStreamWriter.而该转换流对象要接受一个字节输出流。而且还可以操作文件的字节输出流。FileOutputStream OutputStreamWriter osw = new OutputStreamWriter; 需要高效么?需要。BufferedWriter bufw = new BufferedWriter;所以,记住。转换流什么时候使用?字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流练习:讲一个文本数据打印在控制台上,按照以上三个格式完成三个明确19-20IO流-改变标准输入输出设备setIn//重新分配"标准"输入流setOut//重新分配"标准"输入流import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.PrintStream;/** */class TransStreamDemo3 {public static void mainthrows IOException{//改变源//System.setIn);///改变目的//System.setOut); BufferedReader bufr = new BufferedReader); BufferedWriter bufw = new BufferedWriter); String line = null;while!=null){if)break;bufw.write;bufw.newLine;bufw.flush;}bufr.close;}}19-21异常的日志信息import java.io.IOException;import java.io.PrintStream;import java.text.SimpleDateFormat;import java.util.Date;class ExceptionInfo {public static void mainthrows IOException{try{int arr = new int;System.out.println;}catch{try{//创建日期对象Date d = new Date;//格式化日期SimpleDateFormat sdf = new SimpleDateFormat;//将创建的日期对象格式化String s = sdf.format; //生成日志文件PrintStream ps = new PrintStream;ps.println;System.setOut;}catch{throw new RuntimeException;} e.printStackTrace;}}}//网上有一个专门用于日志文件的工具:log4j19-22IO流-系统信息//打印系统信息import java.io.IOException;import java.io.PrintStream;import java.util.Properties;class SystemInfo {public static void mainthrows IOException{Properties prop = System.getProperties;//System.out.println;//将信息输出到Sysinfo.txtprop.list); }}20-01IO流-File概述-创建和删除-判断-获取用来将文件或者文件夹封装成对象;方便对文件和文件夹的操作属性信息进行操作;File对象可以作为参数传递给流的构造函数;了解File类中的常用方法.separator与系统有关的默认名称分隔符.简而言之:目录分隔符File类常见方法1,创建boolean createNewFile;//在指定位置创建文件,如果该文件已经存在,则不创建.返回false;和输出流不一样,输出流对象一建立就会创建文件.而且文件已经存在,会覆盖boolean mkdir;//创建一层文件夹boolean mkdirs;//创建多级目录2,删除boolean delete;//删除失败,返回false.void deletOnExit;//退出时删除制定文件3,判断exists;//判断文件是否存在isFile;//是否是文件 isDirectory;//是否是目录isHidden;//是否是隐藏文件isAbsolute;//判断是否是绝对路径,如果是返回true,即使文件不存在也能判断canExecute;//此文件是否可执行//canRead;//是否能读//canWrite;是否能写//compartTo;//比较文件大小,4,获取信息String getName;//获取名称String getPaht;//获取路径String getParent;//获取父目录String getAbsolutePath;//获取绝对路径File getAbsoluteFile;//获取绝对路径封装成对象long lastModified;//获取最后一次修改时间long length;//文件大小 5重命名boolean renameTo;//重命名package demo;/** * * * */import java.io.File;import java.io.IOException;class FileDemo {public static void mainthrows IOException{//consMethod;//method_1;//method_2;//method_3;//method_4;method_5; }public static void method_5{File f1 = new File;File f2 = new File;File f3 = new File; sop);//将文件1改名为文件名2 sop);//可以理解为,将文件2从C盘剪切到D盘,并重命名}public static void method_4{File f = new File; File f1 = new File; File f2 = new File;//获取路径sop;//获取绝对路径sop; //该方法返回的是绝对路径中的父目录如果获取的是相对路径返回null//如果相对路径中有上一层目录,那么该目录就是返回结果sop;//nullsop;//c:sop;//abc} public static void method_3{File f = new File; //为啥下面两个都是false呢,因为file.txt根本就不存在//所以!!在判断文件是目录或者是文件时,必须要判断文件是否存在,用exists判断sop;sop; //判断是否是绝对路径,是返回true,即使文件不存在也能返回truesop;} public static void method_2{File f = new File; //判断文件是否存在sop;//判断此文件是否可执行,如果是.exe或者其它的可执行文件则返回true//sop; } //演示createNewFile返回类型public static void method_1throws IOException{File f = new File;//演示createNewFile创建文件返回类型//sop; //演示是否删除成功sop; //创建目录File f1 = new File;//sop;sop;} //创建File对象,构造方法演示@SuppressWarningspublic static void consMethod{//将a.txt封装成File对象,可以将已有的和未出现的文件盒文件夹封装成对象.File f1 = new File; //第二种方式/父目录,文件下的文件名//好处,将文件目录和文件封装成两个对象File f2 = new File; //第三种方法File d = new File;File f3 = new File; sop;sop;sop;//这样的目录分隔符也可以.File f4 = new File;//最常见,最好且跨平台的方法File f5 = new File;} public static void sop{System.out.println;}}20-05File对象功能-文件列表static File listRoots;//列出文件列表功能String list;//列出目录下的文件以及文件夹package demo;import java.io.*;class FileDemo2 {public static void main{//listRootsDemo; listDemo;}//返回当前目录下的文件以及文件夹public static void listDemo{File f = new File;String names = f.list;//调用list方法的file对象必须是封装了一个目录,该目录必须存在 for{System.out.println;}} //返回所有跟目录listrootpublic static void listRootsDemo{File files = File.listRoots;for{System.out.println;}}}20-06File对象功能-文件列表2String list;//接口,文件名过滤此接口下方法boolean accept;//测试某一文件是否包含在此文件夹下//带参数的public static void listDemo_2{File dir = new File;String arr = dir.list{return name.endsWith;}}); for{System.out.println;}} 20-07IO流-列出目录下所有内容-递归因为目录中海油目录,只要使用同一个列出目录的功能的函数完成即可.在列出过程中出现的还是目录的话,还可以再次调用本功能.也就是函数自身调用函数自身.这种表现形式,或者变成手法,称为递归递归注意!!!1,限定条件2,要注意递归次数,避免内存溢出import java.io.File;/** 列出制定目录下文件或者文件夹,也包含目录中的内容* 也就是列出制定目录下所有内容* * 因为目录中海油目录,只要使用同一个列出目录的功能的函数完成即可.* 在列出过程中出现的还是目录的话,还可以再次调用本功能.* 也就是函数自身调用函数自身.* 这种表现形式,或者变成手法,称为递归*/class FileDemo3 {public static void main{File dir = new File;showdir;}public static void showdir{System.out.println;File files = dir.listFiles;for{if{showdir;}elseSystem.out.println;}}//求某一个数的2进制public static void toBin{if{toBin;sop;}}//求和运算public static int getSum{ifreturn 1;return num+getSum;} public static void sop{System.out.println;}}20-08列出目录下所有内容-带层次//层次..public static String getLevel{StringBuilder sb = new StringBuilder;sb.append;for{sb.insert;}return sb.toString;}public static void showDir_2{System.out.println+dir.getName); level++;File files = dir.listFiles;for{ifshowDir_2;elseSystem.out.println+files);}}20-09IO流-删除带内容的目录删除一个带内容的目录.删除原理:在window中,删除时从里往外删除的.既然是从里往外删除的,就需要用到递归class RemoveDir {public static void main{File dir = new File;removeDir;}public static void removeDir{File files = dir.listFiles;for{ifremoveDir;elseSystem.out.println;}System.out.println; }}20-10IO流-创建java文件列表package demo;import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.util.ArrayList;import java.util.List;/*** 练习:* 将一个指定目录下的java文件的绝对路径,存储到一个文本文件中.* 建立一个java列表文件.* * 思路:* 1,对制定的目录进行递归* 2,获取递归过程中所有的java文件的路径.* 3,将这些路径存储到集合中.* 4,将集合中的数据写入到一个集合中.*/class JavaFileList {public static void mainthrows IOException{File dir = new File; List list = new ArrayList ; fileToList; System.out.println; File file = new File;writeToFile;}public static void fileToList{File files = dir.listFiles;for{iffileToList;else{if)list.add;if)list.add;}}}public static void writeToFilethrows IOException{BufferedWriter bufw = null;try{bufw = new BufferedWriter);for{String path = f.getAbsolutePath;bufw.write;bufw.newLine;bufw.flush;}}catch{throw e;}finally{try{ifbufw.close;}catch{throw e;}}}}20-11IO流-Properties是hashtable的子类.!!!!!!!!具备了map集合的特点,而且他存储的键值对都是字符串.是集合中和IO技术相结合的集合容器.该对象的特点:可以用于键值对形式的配置文件.那么在加载数据时,需要数据有固定格式:键=值20-12IO流-Properties存取!!!!!!!!!!//设置和获取元素public static void setAndGet{Properties prop = new Properties;prop.setProperty;prop.setProperty;//System.out.println; String value = prop.getProperty;sop;}20-13IO流-Properties存取配置文件import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.util.Properties;class PropertiesDemo {public static void mainthrows IOException{//setAndGet;//method_1;loadDemo;}public static void loadDemothrows IOException{Properties prop = new Properties;FileInputStream fie = new FileInputStream;//加载prop.load; //对haha进行修改prop.setProperty;//将修改后的文件保存FileOutputStream fos = new FileOutputStream;prop.store;//sop;prop.list; fie.close;fos.close;} //演示,如何将刘忠的数据存储到集合中.//想要将info.txt中的键值数据存到集合中进行操作./*思路:* 1,用一个流和info.txt关联.* 2,读取一行数据,用该行数据用=进行切割.* 3,等号左边作为键,右边作为值,存入到Properties集合中,哦了么不就.*/public static void method_1throws IOException{BufferedReader bufr = new BufferedReader); String line = null;Properties prop = new Properties; while!=null){String arr = line.split;prop.setProperty;}bufr.close;sop; } //设置和获取元素public static void setAndGet{Properties prop = new Properties;prop.setProperty;prop.setProperty;//System.out.println; String value = prop.getProperty;sop;}public static void sop{System.out.println;}}20-14IO流-Properties练习package demo;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.Properties;/*用于记录应用程序运行次数* 如果使用次数已到,那么给出注册提示.* * 很容易想到的是:计数器.* 可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增* 可是随着该应用程序的退出,该计数器也在内存中消失了* * 下一次再启动改程序,又重新开始从0计数,so,这不是咱想要的.* * 程序即使结束,该技术企的值也存在.* 下次程序启动会加载该计数器的值,并加1后重新存储起来.* 所以要建立一个配置文件,用于记录该文件的使用次数.* * 该配置文件使用键值对的形式,这样便于阅读数据并操作数据.* * 键值对数据是map集合.数据是以文件形式存储,使用io计数.* 那么map+io -->properties.* 配置文件可以实现应用程序数据的共享.*/class RunCount {public static void mainthrows IOException{Properties prop = new Properties; File file = new File;iffile.createNewFile; FileInputStream fis = new FileInputStream; prop.load; int count = 0;String value = prop.getProperty; if{count = Integer.parseInt;if{System.out.println;return;}}count++; prop.setProperty; FileOutputStream fos = new FileOutputStream; prop.store; fos.close;fis.close; }}20-15IO流-PrintWriter打印流:该流提供了打印方法.可以将各种数据类型的数据都原样打印.字节打印流:PrintStream构造函数可以接受的参数类型:1,file对象.File2,字符串路径.String3,字节输出流.OutputStream字符打印流:PrintWriter构造函数可以接受的参数类型:1,file对象.File2,字符串路径.String3,字节输出流.OutputStream4,字符输出流.Writerimport java.io.BufferedReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;class PrintStreamDemo {public static void mainthrows IOException{BufferedReader bufr = new BufferedReader); PrintWriter out = new PrintWriter,true); String line = null; while!=null){if)break;out.println;}bufr.close;out.close;}}20-16IO流-合并流SequenceInputStream可以将多个流对象拼接成一个流对象package demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.Enumeration;import java.util.Vector;/*** 多个流合并成一个读取流* @author Chen_zyan**/class SequenceDemo {public static void mainthrows IOException{Vector v = new Vector ; v.add);v.add);v.add); Enumeration en = v.elements; SequenceInputStream sis = new SequenceInputStream; FileOutputStream fos = new FileOutputStream; byte buf = new byte; int len = 0;while)!=-1){fos.write;}fos.close;sis.close; }}20-17IO流-切割文件package demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.SequenceInputStream;import java.util.ArrayList;import java.util.Enumeration;import java.util.Iterator;class SplitFileDemo {public static void mainthrows IOException{//splitFile;merge;}//切割public static void splitFilethrows IOException{FileInputStream fis = new FileInputStream; FileOutputStream fos = null; byte buf = new byte; int len = 0;int count = 1;while)!=-1){fos = new FileOutputStream+".part");fos.write;fos.close;}fis.close;}//合并public static void mergethrows IOException{ArrayList al = new ArrayList ; for{al.add);} final Iterator it = al.iterator; Enumeration en = new Enumeration {public boolean hasMoreElements{return it.hasNext;}public FileInputStream nextElement{return it.next;}}; SequenceInputStream sis = new SequenceInputStream; FileOutputStream fos = new FileOutputStream; byte buf = new byte; int len = 0;while)!=-1){fos.write;}fos.close;sis.close; }}21-01IO流-对象的序列化二者均可直接操作对象.ObjectInputStreamObjectOutputStream注意:静态不能被序列化,非static的也不想序列化就加入一个transient修饰符/*** 对象序列化*/import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;class ObjectStreamDemo {public static void mainthrows Exception{//writeObj;//readObj;}//写入public static void writeObjthrows Exception{ObjectOutputStream oos = new ObjectOutputStream); oos.writeObject); oos.close;}//读取public static void readObjthrows Exception{ObjectInputStream ois= new ObjectInputStream); Object ob = ois.readObject; System.out.println; ois.close;}}//一定要实现Serializableimport java.io.Serializable;class Person implements Serializable{//标记:public static final long serialVersionUID = 3L; String name;int age; Person{this.name = name;this.age = age;}public String toString{return name+":"+age;} }21-02IO流-管道流PipedInputStreamPipedOutputStreampackage demo;import java.io.PipedInputStream;import java.io.PipedOutputStream;//读取管道class Read implements Runnable{private PipedInputStream in;Read{this.in = in;} public void run{try{byte buf = new byte; int len = in.read; String s = new String; System.out.println; in.close;}catch{throw new RuntimeException;}}}class Write implements Runnable{private PipedOutputStream out;Write{this.out = out;} public void run{try{Thread.sleep;out.write;out.close;}catch{throw new RuntimeException;}}}class PipedStreamDemo {public static void mainthrows Exception{//创建管道流PipedInputStream in = new PipedInputStream;PipedOutputStream out = new PipedOutputStream; in.connect; Read r = new Read;Write w = new Write;new Thread.start;new Thread.start; }}21-03IO流-RandomAccessFile该类不是IO体系中的子类,而是直接集成Object.但是它是IO包中的成员.因为它具备杜荷写的功能.内部封装了一个数组,而且通过指针对数组内的元素进行操作.可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置.其实完成读写的原理就是内部封装了字节输入流和输出流.通过构造函数可以看书,该类只能操作文件.而且操作文件还有模式:只读r,读写rw等.如果模式为r,不会创建文件,会去读取一个已存在的文件,如果文件不存在,则会出现异常.如果模式为rw,会自动创建,如果存在,则不会覆盖.import java.io.IOException;import java.io.RandomAccessFile;class RandomAccessFileDemo {public static void mainthrows IOException{//writeFile;//readFile; //writeFile_2;readFile_2;} //读public static void readFilethrows IOException{RandomAccessFile raf = new RandomAccessFile;//调整对象中指针.//raf.seek;//可以随意跳,可以往前跳,可以往后跳//跳过制定的字节数raf.skipBytes;//只能往后跳byte buf = new byte;raf.read; String name = new String;int age = raf.readInt; System.out.println;System.out.println; raf.close; } //写_1public static void writeFilethrows IOException{//因为是写,所以参数为rwRandomAccessFile raf = new RandomAccessFile; raf.write;raf.writeInt;raf.write;raf.writeInt; //关流raf.close;} //写_2,指定位置写public static void writeFile_2throws IOException{RandomAccessFile raf = new RandomAccessFile; raf.seek;raf.write;raf.writeInt; raf.close;}//读_2public static void readFile_2throws IOException{RandomAccessFile rad = new RandomAccessFile; rad.seek;byte buf = new byte;rad.read; String name = new String;int age = rad.readInt; System.out.println;System.out.println; rad.close;} }21-04IO流-操作基本数据类型的流对象DataStreamDataInputStream和DataOutputStream可以用于操作基本数据类型的流对象import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;class DataStreamDemo {public static void mainthrows IOException{// writeData;// readData;// writeUTF;// readUTF;// writeGbk;}//写1public static void writeDatathrows IOException{DataOutputStream dos = new DataOutputStream); dos.writeInt;dos.writeBoolean;dos.writeDouble; dos.close;}//读1public static void readDatathrows IOException{//注意,读的顺序与写的顺序要一直DataInputStream dis = new DataInputStream); int i =dis.readInt;boolean b = dis.readBoolean;double d = dis.readDouble; System.out.println;System.out.println;System.out.println; dis.close;} //写2,按照UTF方式写public static void writeUTFthrows IOException{DataOutputStream dos = new DataOutputStream); dos.writeUTF; dos.close;}//读2,按照UTF方式读public static void readUTFthrows IOException{DataInputStream dis = new DataInputStream); String s = dis.readUTF;System.out.println; dis.close;} //写3,按照正常utf方式写public static void writeUtfthrows IOException{OutputStreamWriter osw = new OutputStreamWriter,"utf-8"); osw.write; osw.close;} //写4,按照gbk方式写public static void writeGbkthrows IOException{OutputStreamWriter osw = new OutputStreamWriter,"gbk"); osw.write; osw.close;}}21-05IO流-ByteArrayStream用于操作字节数组的对象.ByteArrayInputStream:在构造的时候,需要接受数据源,而且数据源是一个字节数组.ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象已经内部封装了可变长度的数据.这就是数据目的地.因为这两个流对象都操作的是数据,并没有使用系统资源.所以,不用进行close关闭.在流操作规律讲解时:源设备:键盘System.in,硬盘FileStream,内存ArrayStream目的设备:控制台System.out,硬盘FileStream,内存ArrayStream用流的读写思想来操作数据.import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;class ByteArrayStream {public static void main{//数据源ByteArrayInputStream bis = new ByteArrayInputStream; //数据目的ByteArrayOutputStream bos = new ByteArrayOutputStream; int by = 0;while!=-1){bos.write;} System.out.println;System.out.println;}}21-06IO流-字符编码问题!!!!!加入编码变的两个流对象InputStreamReaderOutputStreamWriter先简单了解一下常见的编码表 ASCII:美国标准信息交换码ISO8859-1:拉丁码表.欧洲码表GB2312:中国的中文码表GBK:中国的中文码表升级版,融合了更多的中文文字符号.Unicode:国际标准码,融合了多种文字UTF-8:最多用三个字节来表示一个字符package demo;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;class EncodeStream {public static void mainthrows IOException{//writeText;readText;}//写public static void writeTextthrows IOException{OutputStreamWriter osw = new OutputStreamWriter,"utf-8"); osw.write; osw.close;}//读public static void readTextthrows IOException{InputStreamReader isr = new InputStreamReader,"gbk"); char buf = new char;int len = isr.read; String str = new String;System.out.println; isr.close; }}21-07字符编码编码:字符串变成字节数组String-->byte; str.getBytes;解码:字节数组变成字符串byte-->String; new String; import java.util.Arrays;/*** 如果出现乱码,再继续编码一次,然后在解码一次* 注意:如果是gbk转成utf-8继续出现乱码,再用utf-8编码gbk解码的话,仍然会出现乱码,原因是二者都识别中文* @author Chen_zyan**/class EncodeDemo {public static void mainthrows Exception{String s = "你好"; //用gbk编码byte b = s.getBytes; System.out.println);//用iso8859-1解码String s1 = new String;System.out.println; //用iso8859-1编码byte b1 = s1.getBytes;//用gbk编码String s2 = new String; System.out.println;}}21-08字符编码-联通用记事本保存的之后再打开会出现乱码原因,联通的二进制编码符合UTF-8所以保存的时候是gbk但是打开之后会成为utf-8所以会出现错误.想要解决的话,在"联通"前面加一个其它的汉字,或者保存的时候就保存为gbk21-09练习有五个学生,每个学生有3门课的成绩.从键盘输入以上数据输入的格式:如zhangsan,30,40,60计算出总成绩并把学生的信息计算出的总分数高低顺序存放在磁盘文件"stud.txt"中1,描述学生对象.2,定义一个可以操作对象的工具类思想:1,通过获取键盘录入的一行数据.并将该行中的信息去除封装成学生对象.2,因为学生对象有很多,那么就需要存储.使用到集合,因为要对学生的总分排序,所以可以使用TreeSet.3,将集合中的信息写入到文件中package test;/**练习* 有五个学生,每个学生有3门课的成绩.从键盘输入以上数据输入的格式:如zhangsan,30,40,60计算出总成绩并把学生的信息计算出的总分数高低顺序存放在磁盘文件"stud.txt"中1,描述学生对象.2,定义一个可以操作对象的工具类思想:1,通过获取键盘录入的一行数据.并将该行中的信息去除封装成学生对象.2,因为学生对象有很多,那么就需要存储.使用到集合,因为要对学生的总分排序,所以可以使用TreeSet.3,将集合中的信息写入到文件中*/import java.io.*;import java.util.*;//定义学生类class Student implements Comparable {//姓名private String name;//ma数学,cn语文,en英文private int ma,cn,en;//sum英文private int sum; //一初始化就有了,构造函数传递Student{this.name = name;this.ma = ma;this.cn = cn;this.en = en;sum = ma+cn+en;}//实现接口,覆盖方法,先比总分,public int compareTo{int num = new Integer.compareTo);ifreturn this.name.compareTo;return num;} //获取姓名public String getName{return name;}//获取总分public int getSum{return sum;} //覆盖hashCode,因为有可能存入到hashcode里面public int hashCode{return name.hashCode+sum*78;}//判断存入的是否是同一个人public boolean equals{//如果obj不是学生,类型不匹配抛异常if)throw new ClassCastException;Student s = obj; return this.name.equals && this.sum==s.sum;}//学生类对应的字符串表示形式public String toString{return "Student";}}//学生信息工具class StudentInfoTool{//没有比较器滴..public static Set getStudentsthrows IOException{return getStudents;} //返回集合 //可以传一个比较器进来public static Set getStudentsthrows IOException{//读取键盘BufferedReader bufr = new BufferedReader); //循环读String line = null;//进行一个判断,是否有比较器Set stus = null;ifstus = new TreeSet ;elsestus = new TreeSet ; while!=null){if)break;//如果不是,就切String info = line.split;//学生对象Student stu = new Student,Integer.parseInt,Integer.parseInt);//二叉树都排序了stus.add;}bufr.close; return stus;}//集合写到文件里面public static void write2Filethrows IOException{//目的BufferedWriter bufw = new BufferedWriter);//遍历集合for{//学生姓名bufw.write;//也可以stu.toString//学生总分bufw.write;//换行一次bufw.newLine;bufw.flush;}bufw.close;}}class StudentInfoTest {public static void mainthrows IOException{//比较器,强行逆转Comparator cmp = Collections.reverseOrder; Set stus = StudentInfoTool.getStudents; StudentInfoTool.write2File;}}22-01GUI概述全称:Graphical User Interface两个很重要的包java.Awt:需要调用本地系统方法实现功能.属重量级控件,跨平台性不是很好.javax.Swing: 在AWT的基础上,建立的一套图形化几面系统.其中提供了更多的组件,而且完全有Java实现,增强了可一致性,属轻量级控件顺便说一下,eclipse的界面用的包是java.xawt简单说一下体系Component|--Container这个组件作为一个组件,里面可以继续添加组件|--Window|--Frame|--Dialog|--FileDialog|--Panel//下面与Container同级,但是不能添加组件|--Button|--Label|--Checkbox|--TextComponent|--TextArea|--TextFileld22-02GUI-布局管理器容器中的组件的排放方式,就是布局常见的布局管理器:FlowLayout总左到右的顺序排列;Panel默认的布局管理器BorderLayout东南西北中Frame默认的布局管理器GridLayout规则的矩阵GardLayout选项卡GridBagLayout非规则的矩阵22-03GUI-Frame//创建图形化界面:1,创建frame窗体;2,对窗体进行基本设置,比如:大小,位置,布局;3,定义组件;4,将组件通过窗体的add方法添加到窗体中.5,让窗体显示,通过setVisible//创建图形化界面import java.awt.Button;import java.awt.FlowLayout;import java.awt.Frame;class AwtDemo {public static void main{Frame f = new Frame; //设置窗体大小f.setSize; //设备位置位置,距左面300,上面200xpf.setLocation; //设置布局管理f.setLayout; //按钮Button b = new Button; //将按钮添加到窗体当中f.add; //显示窗体f.setVisible; }}22-04GUI-事件监听机制事件监听机制的特点:1,事件源2,事件3,监听器4,事件处理方式事件源:就是awt包或者swing包中的那些图形界面组件事件:每一个事件源都有自己特有的对应事件和共性事件.监听器:可以出发某一个事件的动作都已经封装到了监听器中以上三者在java中都已经定义好了,直接获取其对象来用就可以了.我们需要做的事情是:就是对产生的动作进行处理.22-05GUI-窗体事件package demo;//创建图形化界面import java.awt.*;import java.awt.event.*;class AwtDemo {public static void main{Frame f = new Frame; //设置窗体大小f.setSize; //设备位置位置,距左面300,上面200xpf.setLocation; //设置布局管理f.setLayout; //按钮Button b = new Button; //将按钮添加到窗体当中f.add; //f.addWindowListener;//可以写个匿名内部类f.addWindowListener{System.out.println;System.exit;}//窗体前置public void windowActivated{System.out.println;}//窗体打开public void windowOpened{System.out.println;}}); //显示窗体f.setVisible;}}//应为WindowListener的子类windowASdapter已经实现了WindowListener接口.//并覆盖了其中的所有方法.那么我只需要继承自WindowAdapter覆盖我需要的方法即可class MyWin extends WindowAdapter{public void windowClosing{System.out.println;System.exit;}}/*class MyWin implements WindowListener{//覆盖了7个方法,可是我只用到了关闭的动作.//其它的动作都没有用到,可是必须复写}*/22-06GUI-Action事件//按钮中添加事件import java.awt.*;import java.awt.event.*;class FrameDemo {//定义该图形中所需的组件的引用.private Frame f;private Button but;FrameDemo{init;} //对图形界面初始化 public void init{f = new Frame;//对frame进行基本设置//setBoundsf.setBounds;f.setLayout; but = new Button; //将组件添加到窗体中f.add; //加载一下窗体上的事件myEvent;//显示窗体f.setVisible;}//将事件添加到这里public void myEvent{f.addWindowListener{System.exit;}});//让按钮具备退出程序的功能/** 按钮就是事件源* 那么选择哪一个监听器呢?* 通过关闭窗体示例了解到想要知道哪个组件具备什么样的特有监听器.* 需要查看该组件对象的功能* 通过查询Button的描述,发现按钮支持一个特有监听addActionListener,活动监听*/but.addActionListener{System.out.println;System.exit;}});} public static void main{new FrameDemo;}}22-07GUI-鼠标事件//鼠标事件import java.awt.*;import java.awt.event.*;class MouseEventDemo {private Frame f;private Button but;MouseEventDemo{init;} //对图形界面初始化 public void init{f = new Frame; f.setBounds;f.setLayout; but = new Button; f.add; myEvent;f.setVisible;} public void myEvent{//窗口关闭f.addWindowListener{System.exit;}});//按钮的活动事件,如果想要这个按钮键盘鼠标都能操作,建议用活动事件but.addActionListener{System.out.println;}});//鼠标事件but.addMouseListener{System.out.println;}public void mouseClicked{//getClickCount获取鼠标连击次数ifSystem.out.println;}}); }public static void main{new MouseEventDemo;}}22-08GUI-键盘事件package demo8;//键盘事件import java.awt.*;import java.awt.event.*;class KeyDemo{private Frame f;private Button but;private TextField tf;KeyDemo{init;}public void init{f = new Frame;but = new Button; tf = new TextField;//创建文本框 f.setBounds;f.setLayout;f.add;f.add; myEvent;f.setVisible;}public void myEvent{//窗口活动事件f.addWindowListener{System.exit;}}); tf.addKeyListener{int code = e.getKeyCode;if){ e.consume;//不会按照原事件执行System.out.println; }}}); //给but添加一个监听but.addKeyListener{//组合按键,ctrl+enterifSystem.exit;//如果按键是esc就退出//if// System.exit; //KeyEvent.getKeyText打印输入内容//System.out.println+"...."+e.getKeyCode);}}); }}class KeyEventDemo {public static void main{new KeyDemo;}}22-09GUI-练习, 列出指定目录内容package demo9;import java.awt.*;import java.awt.event.*;import java.io.File;class MyWindow{private Frame f;private Button but;private TextField tf;private TextArea ta; MyWindow{init;}//画界面public void init{//创建f窗体,but按钮,tf文本框,ta文本域f = new Frame;f.setBounds;//窗体坐标以及窗体大小f.setLayout;//布局方式 but = new Button;tf = new TextField;ta = new TextArea;//行,列 f.add;f.add;f.add; myEvent;f.setVisible; }public void myEvent{but.addActionListener{/*String text = tf.getText;//System.out.println;ta.setText;tf.setText;//清空内容*/ String dirPath = tf.getText;File dir = new File;//封装成对象if//dir存在,并且是目录{ta.setText;//清空上一次查询 String names = dir.list;for{//ta.setText;ta.append;}}}}); //窗口事件f.addWindowListener{System.exit;}});}}class MyWindowDemo {public static void main{new MyWindow;}}22-10GUI-对话框Dialogpackage demo10;//GUI-练习, 列出指定目录内容import java.awt.*;import java.awt.event.*;import java.io.File;class MyWindow{private Frame f;private Button but;private TextField tf;private TextArea ta; private Dialog d;//误操作提示框private Label lab;//private Button okBut;MyWindow{init;}//画界面public void init{//创建f窗体,but按钮,tf文本框,ta文本域f = new Frame;f.setBounds;//窗体坐标以及窗体大小f.setLayout;//布局方式 //创建错误滴那个东东的窗体d = new Dialog;//true,不关闭此窗口,后面的窗口操作不了,false后面的窗口可以继续操作d.setBounds;d.setLayout;lab = new Label;//封装错误信息滴okBut = new Button; d.add;d.add; but = new Button;tf = new TextField;ta = new TextArea;//行,列 f.add;f.add;f.add; myEvent;f.setVisible; }public void myEvent{ //按钮退出but.addActionListener{showDir;}});//弹出对话框的按钮事件okBut.addActionListener{d.setVisible;}}); tf.addKeyListener{ifshowDir;}}); //弹出对话框的窗体事件d.addWindowListener{d.setVisible;}}); //f的窗口事件f.addWindowListener{System.exit;}});}public void showDir{String dirPath = tf.getText;File dir = new File;//封装成对象if//dir存在,并且是目录{ta.setText;//清空上一次查询String names = dir.list;for{ta.append;}}else{//错误提示信息String info = "您输入的信息是:"+dirPath+"错误滴,请重新输入";lab.setText;d.setVisible;}}}class MyWindowDemo {public static void main{new MyWindow;}}22-11GUI-菜单Menu;//菜单,菜单既可以添加菜单,也可以添加菜单条MenuItem;//菜单条mb.add;//添加"文件"m.add;//文件下面添加子惨淡subMenu.add;//子条目m.add;文件Menu|--子菜单Menu|--子条目MenuItem|--退出MenuItem//菜单import java.awt.*;import java.awt.event.*;class MyMenuDemo {private Frame f;private MenuBar mb;//菜单栏private Menu m,subMenu;//菜单private MenuItem closeItem,subItem;//子菜单 MyMenuDemo{init;}public void init{f = new Frame;f.setBounds;f.setLayout; mb = new MenuBar;m = new Menu;closeItem = new MenuItem;subItem = new MenuItem;subMenu = new Menu;f.setMenuBar;//添加菜单mb.add;//添加"文件"m.add;//文件下面添加子菜单subMenu.add;//子条目m.add; myEvent;f.setVisible;}public void myEvent{//f的窗口事件f.addWindowListener{System.exit;}});closeItem.addActionListener{System.exit;}});}public static void main{new MyMenuDemo;}}22-12GUI-练习-打开文件package test11;//练习-打开文件import java.awt.*;import java.awt.event.*;import java.io.*;class MyMenuTest {private Frame f;private MenuBar bar;//菜单栏private Menu fileMenu;//菜单private MenuItem openItem,saveItem,closeItem;//子菜单private FileDialog openDia,saveDia;//打开,保存private TextArea ta;//文本区域 MyMenuTest{init;}public void init{f = new Frame;f.setBounds;//f.setLayout; bar = new MenuBar;fileMenu = new Menu;closeItem = new MenuItem;openItem = new MenuItem;saveItem = new MenuItem;ta = new TextArea; f.setMenuBar;//添加菜单bar.add;//添加"文件"fileMenu.add;fileMenu.add;fileMenu.add;f.add;//文本区域 openDia = new FileDialog;saveDia = new FileDialog; myEvent;f.setVisible;}public void myEvent{//打开的事件openItem.addActionListener{openDia.setVisible;//显示String dirPath = openDia.getDirectory;//路径String fileName = openDia.getFile;//名字//System.out.println;if//如果有一个为空的话,那么就返回return ;ta.setText;//添加下个文件之前先清空文本区域File file = new File;try{BufferedReader bufr = new BufferedReader);String line = null;while!=null){ta.append;}bufr.close;}catch{throw new RuntimeException;}}});//保存的事件saveItem.addActionListener{saveDia.setVisible;}}); //f的窗口事件f.addWindowListener{System.exit;}});closeItem.addActionListener{System.exit;}});}public static void main{new MyMenuTest;}}22-13GUI-保存文件package test11;//练习-打开文件import java.awt.*;import java.awt.event.*;import java.io.*;class MyMenuTest {private Frame f;private MenuBar bar;//菜单栏private Menu fileMenu;//菜单private MenuItem openItem,saveItem,closeItem;//子菜单private FileDialog openDia,saveDia;//打开,保存private TextArea ta;//文本区域private File file; MyMenuTest{init;}public void init{f = new Frame;f.setBounds;//f.setLayout; bar = new MenuBar;fileMenu = new Menu;closeItem = new MenuItem;openItem = new MenuItem;saveItem = new MenuItem;ta = new TextArea; f.setMenuBar;//添加菜单bar.add;//添加"文件"fileMenu.add;fileMenu.add;fileMenu.add;f.add;//文本区域 openDia = new FileDialog;saveDia = new FileDialog; myEvent;f.setVisible;}public void myEvent{//保存的事件saveItem.addActionListener{//弹与不弹就看文件存不存在..if{ //弹出saveDia.setVisible; String dirPath = saveDia.getDirectory;//路径String fileName = saveDia.getFile;//名字if//如果有一个为空的话,那么就返回return ;file = new File;}try{BufferedWriter bufw = new BufferedWriter); String text = ta.getText;bufw.write;bufw.close; }catch{throw new RuntimeException;}}}); //打开的事件openItem.addActionListener{openDia.setVisible;//显示String dirPath = openDia.getDirectory;//路径String fileName = openDia.getFile;//名字System.out.println;if//如果有一个为空的话,那么就返回return ;ta.setText;//添加下个文件之前先清空文本区域file = new File;try{BufferedReader bufr = new BufferedReader);String line = null;while!=null){ta.append;}bufr.close;}catch{throw new RuntimeException;}}}); //f的窗口事件f.addWindowListener{System.exit;}});closeItem.addActionListener{System.exit;}});}public static void main{new MyMenuTest;}}22-14GUI-jar包双击执行jar -cvf my.jar mymenu1,创建一个文档,内容如下Main-Class: 包名.类名"回车"例如:Main-Class: mymenu.MyMenuTest2,执行命令如下:jar -cvfm 自定义.jar 配置文件名 包名jar -cvfm my.jar 1.txt mymenu3,必须要注册到本地才能用23-01网络编程 !!!!!!!!!!1,找到对方 IP2,数据要发送到对方指定的应用程序上,为了标示这些应用程序,所以就给这些网络应用程序都用数字进行了标示为了方便称呼这个数字,叫做"端口",逻辑端口3,定义通信规则,这个通讯规则称为协议国际组织定义了通用协议.TCP/IP还有一个常用协议:UDP也有的公司为了安全,自己公司内部定义了自己的协议,其他人就连接不到了.23-02网络编程127.0.0.1//本机回环地址常见默认端口:web:80tomcat:8080mySql:330623-03网络编程-网络模型OSI参考模型,---------ICP/IP参考模型| 应用层 | /||数 表示层 | 应用层 ||据 会话层| |数|封 传输层|_______传输层____TCP,UDP |据|包 网络层|_______网际层____IP |拆| 数据链路层 | |包 |/ 物理层 | 主机至网络层 |23-04网络编程-IP地址IP地址:InetAddress网络中的设备标示不易记忆,可用主机名本地回环地址:127.0.0.1 主机名:localhost//演示IP地址import java.net.*;class IPDemo {public static void mainthrows Exception{// InetAddress i = InetAddress.getLocalHost;// System.out.println;// System.out.println;//获取地址// System.out.println;//获取主机名称 //重点,获取主机地址InetAddress ia =InetAddress.getByName;System.out.println;System.out.println; //打印Google主机所有地址InetAddress inet = InetAddress.getAllByName;forSystem.out.println;}}23-05端口号用于标示进程的逻辑地址,不同进程的标示有效端口:0~65535,其中0~1024系统使用或保留端口23-05网络编程-TCP和UDP !!!!!!!!!!传输协议通讯的规则,常见的协议:TCP和UDPUDP将数据及源和目的封装成数据包,不需要建立连接每个数据包的大小限制在64K内因无连接,是不可靠协议.不需要建立连接,速度快简而言之:1,面向无连接;2,数据会被封包,64K以内;3,不可靠;4,速度快举例子:飞Q聊天,视频会议,桌面共享TCP建立连接,形成传输数据的通道;在连接中进行大数据量传输通过三次握手完成连接,是可靠协议必须建立连接,效率会稍低简而言之:1,面向连接2,数据不用封包,可以大数据传输3,可靠4,速度稍慢23-06网络编程-SocketSocket就是为网络服务提供的一种机制.通信的两端都有Socket网络通信其实就是Socket间的通信.数据在两个Socket间通过IO传输.23-07网络传输-UDP_发送端UDP传输DatagramSocket与DataGramPacket建立发送端,接收端建立数据包.调用Socket的发送接收方法关闭Socket注:发送端与接收端是两个独立的运行程序import java.net.*;/*需求:通过udp传输方式,将一段文字发送出去.* 1,建立udpsocket服务.* 2,提供数据,并将数据封装到数据包中* 3,通过socket服务的发送功能,将数据包发送出去* 4,关闭资源*/class UdpDemo {public static void mainthrows Exception{//1,创建udp服务,通过DatagramSocket对象.DatagramSocket ds = new DatagramSocket; //2,确定数据,并封装成数据包DatagramPacketbyte buf = "udp gemen lai la".getBytes;DatagramPacket dp = new DatagramPacket,1000); //3,通过socket服务,将以后的数据包发送出去,通过send方法ds.send; //4,关闭资源ds.close;}}23-08网络传输-UDP_接收端/*需求:* 定义一个应用程序,用于接收udp协议传输并处理数据的.* * 思路:* 1,定义udpsocket服务,通常会监听一个端口,其实就是给这个接受网络应用程序程序定义数字标示.* 方便与明确哪些数据过来改应用程序可以处理* 2,定义一个数据包,因为要存储接收到的字节数据,因为数据包对象中有更多功能,可以提取字节数据中的不同数据信息.* 3,通过socket服务中的receive方法将接收到的数据存入一定一号的数据包中.* 4,通过数据包对象的特有功能,将这些不同的数据去除,打印在控制台上* 5,关闭资源* */import java.net.DatagramPacket;import java.net.DatagramSocket;class UdpRece {public static void mainthrows Exception{//1,创建udp socket,建立端点DatagramSocket ds = new DatagramSocket; //2,定义数据包,用于存储数据byte buf = new byte;DatagramPacket dp = new DatagramPacket; //3,通过服务的receive方法将接受到数据存入数据包中.ds.receive; //4,通过数据包的方法获取其中的数据String ip = dp.getAddress.getHostAddress;//获取地址 String data= new String;//获取内容 int port = dp.getPort;//获取端口 System.out.println; //5,关闭资源ds.close;}}23-09UDP-键盘录入方式数据package demo;import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;class UdpSend2 {public static void mainthrows Exception{DatagramSocket ds = new DatagramSocket;BufferedReader bufr = new BufferedReader); String line = null;while!=null){if)break; byte buf = line.getBytes; DatagramPacket dp = new DatagramPacket,10001); ds.send;}ds.close; }}class UdpRece2 {public static void mainthrows Exception{DatagramSocket ds = new DatagramSocket; while{byte buf = new byte;DatagramPacket dp = new DatagramPacket; ds.receive; String ip = dp.getAddress.getHostAddress;String data = new String; System.out.println;}}}23-10UDP-聊天package demo10;import java.io.BufferedReader;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;/*** 编写一个聊天程序.* 有收数据的部分,和发数据的部分.* 这两部分需要同时执行,* 那就需要用到多线程技术.* 一个线程控制收,一个线程控制发**因为收和发动作是不一致的,所以要定义两个 run方法,而且这两个方法要封装到不同的类中**/class Send implements Runnable{private DatagramSocket ds;public Send{this.ds = ds;}public void run{try{BufferedReader bufr = new BufferedReader); String line = null; while!=null){if)break; byte buf = line.getBytes; DatagramPacket dp = new DatagramPacket,10002); ds.send;}}catch{throw new RuntimeException;}}}class Rece implements Runnable{private DatagramSocket ds;public Rece{this.ds = ds;}public void run{try{while{byte buf = new byte; DatagramPacket dp = new DatagramPacket; ds.receive;String ip = dp.getAddress.getHostAddress; String data = new String; System.out.println;}}catch{throw new RuntimeException;}}}class ChatDemo {public static void mainthrows Exception{DatagramSocket sendSocket = new DatagramSocket;DatagramSocket receSocket = new DatagramSocket; new Thread).start;new Thread).start;}}23-11TCP传输1,tcp分客户端和服务端2,客户端对应的对象是Socket服务端对应的对象是ServerSocket/*客户端:* 通过查阅socket对象,发现在该对象建立时,就可以去连接指定主机.* 因为tcp是面向连接的.所以在建立socket服务时,* 就要有服务端存在,并连接成功.形成通路后,在该通道进行数据的传输 步骤:1,创建Socket服务,并指定要连接的主机和端口.*//*服务端:步骤:1,建立服务端的Socket服务,通过ServerSocket并监听一个端口2,获取连接过来的客户端对象通过ServerSocket的accept方法.没有连接就会等,所以这个方法是阻塞式的.3,客户端如果发过来数据,那么服务端要使用对应的客户端对象.并获取到该客户端对象的读取流,来读取发过来的数据并打印在控制台4,关闭服务端* */package demo11;/*** 演示Tcp传输 * @author Chen_zyan**/import java.io.*;import java.net.*;//需求:给服务端发送一个文本数据.//客户端class TcpClient{public static void mainthrows Exception{//创建客户端的Socket服务,指定目的主机和端口Socket s = new Socket; //为了发送数据,应该获取Socket流中的输出流.OutputStream out = s.getOutputStream; out.write; s.close;}}//需求:定义端点接收数据,并打印在控制台上.class TcpServer{public static void mainthrows Exception{//建立服务端的socket服务,并监听一个端口.ServerSocket ss = new ServerSocket; //通过accept方法获取连接过来的对象.Socket s = ss.accept; String ip = ss.getInetAddress.getHostAddress; System.out.println;//获取客户端发送过来的数据,那么要使用客户端对象的读取流对象方法来读取数据InputStream in = s.getInputStream; byte buf = new byte;int len = in.read; System.out.println); s.close;//关闭客户端}}23-12TCP传输2package demo12;import java.net.*;import java.io.*;/*** 演示:tcp的传输的客户端和服务端的互访.* * 需求:客户端给服务端发送数据,服务端收到后,给客户端反馈信息.* @author Chen_zyan**//*客户端:* 1,建立socket服务,指定要连接主机和端口.* 2,获取socket流中的输出流.将数据写到该流中.通过网络发送给服务端.* 3,获取socket流中的输入流.将服务端反馈的数据获取到并打印.* 4,关闭客户端资源.* */class TcpClient2{public static void mainthrows Exception{Socket s = new Socket; OutputStream out = s.getOutputStream;out.write; //服务端读的动作InputStream in = s.getInputStream;byte buf = new byte;int len = in.read;System.out.println); s.close; }}//服务端class TcpServer2{public static void mainthrows Exception{ServerSocket ss = new ServerSocket; Socket s = ss.accept; String ip = s.getInetAddress.getHostAddress;System.out.println;InputStream in = s.getInputStream; byte buf = new byte; int len = in.read; System.out.println); OutputStream out = s.getOutputStream; out.write; s.close; ss.close;}}23-13TCP练习package demo13;/**需求:建立一个文本转换服务器* 客户端给服务端发送文本,服务端会把文本转换成大写,再返回给客户端.* 而且客户端可以不断的进行文本转换.当客户端输入over时,转换结束* * 分析:* 客户端:* 既然是操作设备上的数据,那么就可以使用io技术,并按照io的操作规律来思考.* 源:键盘录入* 目的:网络设备,网络输出流* 而且操作的是文本数据.可以选择字符流* * 步骤* 1,建立服务* 2,获取键盘录入.* 3,将数据发给服务端.* 4,获取服务端返回的大写数据.* 5,结束,关闭资源* * 都是文本数据,可以使用字符流进行操作,同时提高效率,加入缓冲* * @author Chen_zyan**/import java.io.*;import java.net.*;public class TramsTextDemo {public static void mainthrows Exception{ Socket s = new Socket;//建立网络连接//建立键盘录入源BufferedReader bufr = new BufferedReader);//目的,将数据写入到socket输出流,发给服务端// BufferedWriter bufwOut = // new BufferedWriter);//简化PrintWriter out = new PrintWriter; //定义一个socket读取流,读取服务端返回的大写信息BufferedReader bufIn = new BufferedReader); String line = null;while!=null)//读的键盘{if)break;out.println;// bufwOut.write;// //结束标记// bufwOut.newLine;// bufwOut.flush; String str = bufIn.readLine;//读的服务端System.out.println;}bufr.close;s.close;}}//服务端/*源:socket读取流* 目的:socket输出流.* 都是文本,装饰*/class TransServer{public static void mainthrows Exception{//建立端点ServerSocket ss = new ServerSocket;//拿到客户端对象Socket s = ss.accept;String ip = s.getInetAddress.getHostAddress;System.out.println;//读取socket读取流中的数据BufferedReader bufIn = new BufferedReader);//先包装一下 //目的,socket输出流,将大写数据写入到socket输出流,并发送给客户端.// BufferedWriter bufOut=// new BufferedWriter);//简化PrintWriter out = new PrintWriter; String line = null;while!=null){out.println; //发出去// bufOut.write;// //结束标记// bufOut.newLine;// bufOut.flush;}s.close;ss.close;}}/** 该例子出现的问题.* 现象:客户端和服务端都在莫名的等待.为什么呢?* 因为客户端和服务端都有阻塞式的方法.这些方法没有读到结束标记,就会一直等* 而导致两端都在等待.*/23-14TCP复制文件package demo14;/**复制文件* * @author Chen_zyan**/import java.io.*;import java.net.*;//客户端class TestClient{public static void mainthrows IOException{Socket s = new Socket;//就这句话就要单独try一下 BufferedReader bufr = new BufferedReader); PrintWriter out = new PrintWriter; //结束标记,时间戳// DataOutputStream dos = new DataOutputStream;// long time = System.currentTimeMillis; // dos.writeLong;// out.println; String line = null;while!=null){out.println;}s.shutdownOutput;//关闭客户端的输出流.相当于给流中加入一个结束标记 //dos.writeLong;//out.println;//结束标记 BufferedReader bufIn = new BufferedReader); String str = bufIn.readLine;System.out.println; bufr.close;s.close;}}//服务端class TextServer {public static void mainthrows Exception{ServerSocket ss = new ServerSocket;Socket s = ss.accept;String ip = s.getInetAddress.getHostAddress;System.out.println;//读取时间戳// DataInputStream dis = new DataInputStream;// long l =dis.readLong; BufferedReader bufIn = new BufferedReader); PrintWriter out = new PrintWriter,true); String line = null;while!=null){//判断结束标记//if)// break;out.println;}PrintWriter pw = new PrintWriter; pw.println; out.close;s.close;ss.close;}}23-01TCP上传图片package demo;//需求:上传图片//客户端/*1,服务端点*2,读取客户端已有的图片数据*3,通过socket输出流,将数据发给服务端*4,读取服务端反馈信息*5,关闭*/import java.io.*;import java.net.*;class PicClient{public static void mainthrows Exception{Socket s = new Socket;FileInputStream fis = new FileInputStream; OutputStream out = s.getOutputStream; byte buf = new byte; int len = 0; while)!=-1){out.write;}//告诉服务端数据已写完s.shutdownInput; //读一下服务端发送的信息InputStream in = s.getInputStream; byte bufIn = new byte; int num = in.read; System.out.println); fis.close;s.close;}}//服务端class PicServer{public static void mainthrows Exception{ServerSocket ss = new ServerSocket; Socket s = ss.accept;//拿到客户端对象 InputStream in = s.getInputStream; FileOutputStream fos = new FileOutputStream; byte buf = new byte; int len = 0;while)!=-1){fos.write;}//返回信息OutputStream out = s.getOutputStream; out.write; fos.close;s.close;ss.close;}}23-02TCP-客户端并发上传图片package demo2;//需求:上传图片//客户端/*1,服务端点*2,读取客户端已有的图片数据*3,通过socket输出流,将数据发给服务端*4,读取服务端反馈信息*5,关闭*/import java.io.*;import java.net.*;//运行的时候://java PicClient c:1.jpgclass PicClient{public static void mainthrows Exception{if//判断传入的是图片{System.out.println;return;}File file = new File;if){System.out.println;} if){System.out.println;return ;}if{System.out.println;return ;} Socket s = new Socket;FileInputStream fis = new FileInputStream;//文件的路径 OutputStream out = s.getOutputStream; byte buf = new byte; int len = 0; while)!=-1){out.write;}//告诉服务端数据已写完s.shutdownInput; //读一下服务端发送的信息InputStream in = s.getInputStream; byte bufIn = new byte; int num = in.read; System.out.println); fis.close;s.close;}}//服务端/*这个服务端有个局限性,当A客户端连接上以后,被服务端获取.服务端执行具体流程* 这时B客户端连接,只有等待.* 因为服务端还没有处理完A客户端的请求.还没有循环回来,执行下一次accept方法,* 所以暂时获取不到B客户端对象.* 那么为了可以让多个客户端同时并发访问服务端.* 那么服务端最好就是将每个客户端封装到一个单独的线程中.这样就可以同时处理多个客户端请求.* * * 如何定义线程呢?* 只要明确了每一个客户端要在服务端执行的代码即可.将改代码存入run方法中*///定义线程!!!,很重要class PicThread implements Runnable{private Socket s;PicThread{this.s = s;}public void run{ String ip = s.getInetAddress.getHostAddress;try{System.out.println; InputStream in = s.getInputStream; //为了不覆盖1,定义一个计数器int count= 1; //为了不覆盖2,用ip地址命名 File file = new File+")"+".jpg"); while//如果file存在{file = new File+")"+".jpg");} FileOutputStream fos = new FileOutputStream; byte buf = new byte; int len = 0;while)!=-1){fos.write;}//返回信息OutputStream out = s.getOutputStream; out.write; fos.close;s.close;}catch{throw new RuntimeException;}}}class PicServer{public static void mainthrows Exception{@SuppressWarningsServerSocket ss = new ServerSocket; while{Socket s = ss.accept;//拿到客户端对象//开启线程new Thread).start;}}}23-03TCP客户端并发登陆package demo3;/*** TCP客户端并发登陆*//*客户端通过键盘录入用户名.* 服务端对这个用户名进行校检.* * 如果用户存在,在服务端显示XXX,已登录.* 并在客户端显示XXX,欢迎光临* * 如果用户不存在,在服务端显示XXX,尝试登陆.* 并在客户端显示XXX,用户已登录.* * * */import java.io.*;import java.net.*;//客户端class LoginChlient {public static void mainthrows Exception{Socket s = new Socket; //键盘录入BufferedReader bufr = new BufferedReader);//数据发送PrintWriter out = new PrintWriter; //读取服务端反馈信息BufferedReader bufIn = new BufferedReader); for//限定3次{String line = bufr.readLine; //判断,如果输入的信息为空,那么就跳出去if{break;}out.println; String info = bufIn.readLine; System.out.println; //如果返回的信息包含欢迎,那么就跳出去if){break;}}//关掉键盘录入,关掉连接bufr.close;s.close;}}//客户端class LoginServer {public static void mainthrows Exception{@SuppressWarningsServerSocket ss = new ServerSocket; while{Socket s = ss.accept; new Thread).start;} }}//线程class UserThread implements Runnable{private Socket s;UserThread{this.s = s;}public void run{String ip = s.getInetAddress.getHostAddress;System.out.println; try{for{//获取用户端发过来的用户流BufferedReader bufIn = new BufferedReader); String name = bufIn.readLine;if//如果读取的为空,那么就蹦出去^_^{break;} //校验用户名的文件@SuppressWarningsBufferedReader bufr = new BufferedReader); //对外的流PrintWriter out = new PrintWriter; String line = null;//定义一个标记,判断是否存在boolean flag = false;while!=null){if)//我有,我就给flag赋值为真.{flag = true;break;}}if{System.out.println;out.println;break;//这里调用的是3次循环跳出}else{System.out.println;out.println;}}s.close;}catch{throw new RuntimeException;}}}23-04浏览器客户端-自定义客户端package demo4;/** 演示客户端和服务端* 1,* 客户端:浏览器* 服务端:自定义 */import java.io.*;import java.net.*;/*建立服务端* */class ServerDemo {public static void mainthrows Exception{ServerSocket ss = new ServerSocket; Socket s = ss.accept;//打印ipSystem.out.println; PrintWriter out = new PrintWriter; out.println; s.close;ss.close; }}//在浏览器当中输入//http://192.168.1.100:11000///也可这样,在dos中输入,这个是远程登录的工具,可以进行命令方式的配置//telnet 192.168.1.254 1100023-05浏览器客户端-Tomcat服务端在Tomcat目录的webapps目录下创建一个myweb目录创建一个demo.html在demo.html里面创建 这是我的主页
欢迎光临想做一首诗0.0想做一首诗0.0想做一首诗0.0打开tomcat目录下bin目录下的startup.bat然后在浏览器中输入http://127.0.0.1:8080/myweb/demo.html23-06自定义浏览器-Tomcat服务端我输入http://127.0.0.1:11000/myweb/demo.html 浏览器给服务端发送的消息:127.0.0.1GET /myweb/demo.html HTTP/1.1Accept: text/html, application/xhtml+xml, */*Accept-Language: zh-CNUser-Agent: Mozilla/5.0 Accept-Encoding: gzip, deflateHost: 127.0.0.1:11000Connection: Keep-Alive请求消息体....以上是Http请求的消息头GET是 获取请求的目标路径/目标文件 协议Accept:浏览器支持的格式Accept-language:建立中文版Accept-Encoding:支持压缩格式User-Agent:用户的一些信息Host:IP地址以及端口Connection:连接以下是Http应答消息头HTTP/1.1 200 OKServer: Apache-Coyote/1.1Accept-Ranges: bytesETag: W/"193-1367051592334"Last-Modified: Sat, 27 Apr 2013 08:33:12 GMTContent-Type: text/htmlContent-Length: 193Date: Sat, 27 Apr 2013 09:11:08 GMTConnection: close消息体......----HTTP/1.1 200 OK其中200代表的是响应状态码,并且成功Last-Modified:修改时间Content-Type:文本格式Content-Length:大小是193字节Date:事件Connection:连接关闭package demo6;/*哇哈哈哈,山寨版IE*/import java.io.*;import java.net.*;class MyIE {public static void mainthrows Exception{Socket s = new Socket;PrintWriter out = new PrintWriter; out.println;out.println;out.println;out.println;// out.println;out.println; out.println;//注意一定要写空行//一下写再请求体 //读一下BufferedReader bufr = new BufferedReader); String line = null;while!=null){//注意也有可能到这里等待,因为没有结束标记System.out.println;}s.close;}}/*127.0.0.1GET /myweb/demo.html HTTP/1.1Accept: text/html, application/xhtml+xml, Accept-Language: zh-CNUser-Agent: Mozilla/5.0 Accept-Encoding: gzip, deflateHost: 127.0.0.1:11000Connection: Keep-Alive*/23-07自定义图形界面浏览器-Tomcat服务端package demo7;/*图形化界面的IE* */import java.awt.*;import java.awt.event.*;import java.io.*;import java.net.*;class MyIEByGUI{private Frame f;private TextField tf;private Button but;private TextArea ta; private Dialog d;private Label lab;private Button okBut;MyIEByGUI{init;}public void init{f = new Frame;f.setBounds;f.setLayout;tf = new TextField;but = new Button;ta = new TextArea;d = new Dialog;d.setBounds;d.setLayout;lab = new Label;okBut = new Button;d.add;d.add;f.add;f.add;f.add;myEvent;f.setVisible;}private void myEvent{okBut.addActionListener{d.setVisible;}});d.addWindowListener{d.setVisible;}});tf.addKeyListener{try{ifshowDir;}catch {} }});but.addActionListener{try{showDir;}catch {} }});f.addWindowListener{System.exit; }});}private void showDirthrows Exception{ta.setText;String url = tf.getText;//http://127.0.0.1:8080/myweb/demo.html int index1 = url.indexOf+2;int index2 = url.indexOf;String str = url.substring;String arr = str.split;String host = arr;int port = Integer.parseInt;String path = url.substring;//ta.setText;Socket s = new Socket; PrintWriter out = new PrintWriter;out.println;out.println;out.println;out.println;out.println;out.println;out.println;BufferedReader bufr = new BufferedReader);String line = null;while!=null){ta.append;}s.close;}public static void main {new MyIEByGUI;}}23-08URL-URLConnectionjava.net.URL统一资源定位符String getFile 获取此 URL 的文件名。 String getHost 获取此 URL 的主机名。 String getPath 获取此 URL 的路径部分。 int getPort 获取此 URL 的端口号。 String getProtocol 获取此 URL 的协议名称。 String getQuery 获取此 URL 的查询部分。 //演示URL对象import java.net.*;class URLDemo {public static void mainthrows Exception{//创建URL对象URL url = new URL;sop; //获取此 URL 的协议名称。sop;//获取此 URL 的文件名。sop; //获取此 URL 的端口号。sop;//获取此 URL 的路径部分sop;//获取URL文件名称sop; //获取此 URL 的查询部分。//当没有端口的时候,返回的值是-1,所以要添加一个这样子的判断//int port = url.getPort;//if//port=80; }public static void sop{System.out.println;}}!!!!!!URLConnection openConnection //返回一个URL连接对象,也就说只要调用这个方法,就会去连接主机,获取主机的连接对象返回一个 URLConnection 对象,它表示到 URL 所引用的远程对象的连接。 import java.net.*;import java.io.*;class URLConnectionDemo {public static void mainthrows Exception{URL url = new URL; URLConnection conn = url.openConnection;// System.out.println; InputStream in = conn.getInputStream;//应用层的协议byte buf = new byte; int len = in.read;System.out.println);}}package demo8;/*图形化界面的IE* */import java.awt.*;import java.awt.event.*;import java.io.*;import java.net.*;class MyIEByGUI2{private Frame f;private TextField tf;private Button but;private TextArea ta; private Dialog d;private Label lab;private Button okBut;MyIEByGUI2{init;}public void init{f = new Frame;f.setBounds;f.setLayout;tf = new TextField;but = new Button;ta = new TextArea;d = new Dialog;d.setBounds;d.setLayout;lab = new Label;okBut = new Button;d.add;d.add;f.add;f.add;f.add;myEvent;f.setVisible;}private void myEvent{okBut.addActionListener{d.setVisible;}});d.addWindowListener{d.setVisible;}});tf.addKeyListener{try{ifshowDir;}catch {} }});but.addActionListener{try{showDir;}catch {} }});f.addWindowListener{System.exit; }});}private void showDirthrows Exception{ta.setText;String urlpath = tf.getText;URL url = new URL; URLConnection conn = url.openConnection; InputStream in = conn.getInputStream;//应用层的协议byte buf = new byte; int len = in.read;ta.setText);}public static void main {new MyIEByGUI2;}}23-09网络编程-Socket与ServerSoc小知识点先说一下Socket比较特殊的部分在进行Socket建立的时候有一个空参数的构造函数会有一个connect方法进行连接SocketAddress//网络地址,与InetAddress的区别在于InetAddress封装的是地址//SocketAddress是抽象类,说一下他的子类InetSocketAddress封装的是地址+端口号再说一下ServerSocket比较特殊的部分ServerSocket;//代表的是能连接到服务器最大客户端服务个数,一般是50,可以设置23-10网络编程-域名解析!!!!www.sina.com.cn//想要将主机名翻译成ip地址需要域名解析,需要一个dns域名解析服务器0,在找之前先去找本地c:windowssystemsdriversexthost有没有映射1,客户端首先去找一台DNS域名解析服务器,服务器记录的是sina的主机对应的ip地址的记录表2,DNS将域名地址返回给客户端3,客户端再次向ip的8080端口上其实127和localhost的映射关系就在本机上c:windowssystemsdriversexthost有个小应用,可以把那种已经在本地准注册的软件,将去网络注册的网络ip映射写入到c:windowssystemsdriversexthost当中,这样子可以走你指定的地址. ……结果你懂的..第二个应用,可以把一些垃圾网站,有木马的网站都映射到这个地方.屏蔽网站但是如果直接写ip的话,就走ip不走网络映射