java基础知识总结

eclipse:网址下载:www.eclipse.org
eclipse快捷键:
补全代码:   alt+/
换行:    shift+(enter)回车符
导入当前类使用的包:  ctrl+shift+o
单行注释: ctrl+/或者ctrl+7
多行注释: ctrl+shift+/
取消多行注释: ctrl+shift+\
格式化代码: ctrl+shift+F
缩进: ctrl+i
快速修正: ctrl+1
复制行: ctrl+alt+(windows菜单)+上键或者下键
移动行: alt+上键或者下键
删除行: alt+d
单词大写: ctrl+shift+(windows菜单)+x
单词小写: ctrl+shift+(windows菜单)+y
窗体大小切换: ctrl+m
显示所有快捷键: ctrl+shift+l
保存: ctrl+s
全部保存 ctrl+shift+s
删除一个单词: ctrl+delete(删除键)
新建 alt+shift+n
java语言基础概论
什么是软件?
软件:一系列按照特点顺序组织的计算机数据和指令的集合








软件的出现实现了人与计算机更好的交互
交互方式分为:图形化界面和命令行方式
图形化界面:这种方式简单直观。使用者易于接受,容易上手操作。例如:360杀毒软件。
命令行方式:需要有一个控制台,输入特定的指令,让计算机完成一些操作。较为麻烦,需要记住一些命令。
命令行基本操作:
dir:列出当前目录下的文件及文件夹
md:创建目录
rd:删除目录
cd :进入指定目录
cd..:退回到上一级目录
cd/:退回到根目录
del:删除文件。
exit:退出dos命令。
cls:清空dos命令。
echo:创建文件。例如:echo haha>1.txt
早期的电脑常常使用dos命令,因为要记住很多命令,不利于普及。
后期发展成了图形化界面,通过点击里面的图形,就可以完成操作。其实就是把这些命令都封装到了图形里面。


计算机语言:人与计算机交流的方式
1.如果人要与计算机交流,那么就要学习计算机语言,我们主要学习的语言是java。
计算机语言:计算机语言是直接用二进制代码指令来表示的机器语言,指令使用0和1组成的一串代码,
他们有一定的位数,并分成若干段,各段的编码表示不同的含义。


java语言概述:
1.java之父是詹姆斯.戈斯林,java是SUN斯坦福大学网络公司在1995年推出的一门高级编程语言。
是一种面向Internet的编程语言。
随着java技术在web方面不断成熟,已经成为web应用程序的首先开发语言。
是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。




java语言的三种技术架构:
J2EE企业版
是为了开发企业环境下的应用程序提供的一套解决方案。该技术体系包含的技术Servlet JSP等,主要针对web应用程序的开发。
J2SE标准版
是为了开发普通桌面和商务应用程序提供的解决方案,该技术体系是其他两者的基础,可以完成一些桌面应用程序的开发。
J2ME小型版
是为了开发电子消费类产品和嵌入式设备提供的解决方案,该技术体系主要应用于小型电子消费类产品,如手机中的应用程序等。
JAVA1.5版本后,更名为javaEE,javaSE,javaME


java语言的特点:跨平台性。
java代码是开源的。
通过java语言编写的应用程序在不同的系统上都可以运行。
跨平台原理:只需要在运行java应用程序的操作系统上,先安装一个java虚拟机即可,由JVM来负责Java程序运行。
因为有了JVM,所以同一个java程序在三个不同的操作系统中都可以执行。这样就实现了java程序的跨平台性,也称为java具有良好的可移植性。
JVM、JRE和JDK的区别?
1.jvm是java虚拟机,用于保证java的跨平台性。注释:java语言是跨平台的,JVM不是跨平台的。
如果想要运行一个开发好的java程序,计算机只需要安装JRE即可。
2.JRE是java的运行环境,JRE包括java的虚拟机和java的核心类库。
3.JDK是java的开发工具,JDK包括java的JRE和开发工具包。
简单而言:用JDK开发完的java程序,交给JRE去运行。


为什么JDK中包含JRE呢?
1.开发完的程序,要运行一下看看效果。
2.也是最重要的JDK中开发工具其实是java语言编写的应用程序,为了方便使用才打包成exe文件,如果没有JRE那么这些工具是运行不了的。


JDK的下载安装及卸载。
java的官方网址:www.oracle.com            老版网址:www.sun.com
安装JDK:傻瓜式安装,下一步即可。建议:安装路径不要用中文或者特殊符号或者空格等。当提示安装jre时,可以选择不安装。


环境变量path和classpath的作用有什么不同?
1.path是配置可执行文件的路径搜索, set path:是在配置临时的文件路径。
2.classpath是用于给类文件配置路径的。
两者的区别:path是给可执行文件配置路径的。
 classpath是给类文件配置路径的。
 这两个环境变量有什么区别?
set classpath=c:\
只在指定的目录下查找类文件,不会再当前目录下查找,就是有,也不会运行。
set classpath=c:\;
现在指定的目录下查找类文件,如果没有,会在当前目录下查找一次。
临时配置,dos命令行的这种环境变量的配置,只在当前窗口有效。
set :设置 例如:set path=haha;
java工具路径配置:set path=d:\jdk\1.6.0_24\bin
建议:配置classpath环境变量时,值得结尾处不要加;如果需要访问当前目录可以用.表示。例如:set classpath=.;c:\;d:\
在原有值的基础上添加新值:set path=新值;%path%
start在原有的dos命令行窗口的基础上打开一个dos命令行,打开的窗口会沿袭以前的命令。


环境变量path的配置:
我的电脑---》属性----》高级系统设置------》环境变量
如果配置classpath环境,jvm在classpath环境变量值的目录中查找要运行的类文件。
编辑path环境变量,在变量值开始处添加java工具所在的路径,和后面的值用;分开即可。
打来dos命令行,,在任意目录下敲入javac命令,如果出现了javac的参数信息,配置成功。
配置path的好处,这种配置一劳永逸。
设置动态的环境变量:%变量名%
查找的类文件的顺:如果没有classpath环境变量,jvm只在当前目录下查找要运行的类文件。jdk1.5版本后classpath可以不用设置。


JRE:JVM+类库
JDK:JRE+JAVA的开发工具


标识符:
1.就是给类变量、方法起名字。
2.组成规则:
由数字0-9,英文字母大小写,$以及_组成。
3.注意事项:
1.只能有组成规则规定的内容组成。
2.不能以数字开头。
3.不能是java的关键字。
4.严重区分大小写。
1.包(文件夹,用于区分同名类)包名全部小写,如果多级包,用.分开。
举例:com是一级包              itheima.interview二级包


2.类和接口:
如果一个单词,单词首字母大写。例如Demo,Test,Student.
如果多个单词,每个单词的首字母大写。例如:HelloWorld,Student.
3.变量和方法:
如果是一个单词,首字母小写。例如:main();name.age.show().method()
如果是多个单词,从第二个单词开始每个单词的首字母大写。例如:showName(),studentName()
4.常量:
全部大写,如果是多个单词组成,用_连接。例如:JAVA_HEMO.
注释:就是对程序的解释性文字(注释不会被jvm编译,只是为了在代码上添加一些程序员看的懂的文字)。
对于单行注释和多行注释,被注释的文字,不会被java的虚拟机解析。对于文档注释,是Java特有的功能,
其中注释内容可以被jdk提供的工具javadoc工具所解析。生成一套网页文件的程序说明书。


注释是一个程序员必须具备的良好的编程习惯。
初学者编写程序要养成习惯:先写注释在写代码。将自己的思想通过注释先整理出思路,在用代码去体现。
因为代码仅仅是思想的一种体现形式。
注释的作用:1.注解说明。2.调试程序。
注释的格式:单行注释://   多行注释:/*  */     文档注释:/**   */
建议:书写代码要写需求,思路,步骤,养成良好的习惯,以后思想一旦确定,代码就如行云流水。
java程序开发体验------------------Hello World
将java代码编写到扩展名为.java的文件中。
1.通过javac命令对该java文件进行编译。
2.通过java命令对生成的.class文件运行。
3具体操作流程
/*
需求:编写一个hello 黑马程序!!!!的小程序。
思路:
1.通过java关键字class定义一个类。
2.通过java特殊字main定义一个主函数,
3.定义打印输出语句。hello 黑马程序员。
步骤:
1.定义一个类class Demo1
2.定义一个主函数的入口:public static void main(String[]args)
3.定义一个输出语句:System.out.println("hello 黑马程序员");
*/
class Demo1
{
public static void main(String[]args)
{
System.out.println("hello 黑马程序员");
System.out.println("人生就要勇于攀登高峰");
}
}


关键字:
关键字被JAVA语言赋予了特殊的含义的单词。
关键字中的字母都小写。
进制转换:
1.二级制,有0,1组成。
2.八进制,由0-7组成。
3.十进制,由0-9组成,默认就是十进制。
4.十六进制,由0-9,A-F,以0x开头。
(3)进制转换:
十进制---------/2--------二进制
System.out.println(Integer.toBinaryString(6));//我就想知道6的二进制是多少?
例如:6的二进制110  原理对十进制的数进行除2运算。  能被整除的用零表示,不能整除的用1表示
三个二进制代表一个十进制


二进制-------*2-----十进制   原理二级制乘以2的过程。  110的十进制   0*2(0)+1*2(1)+1*2(2)=6
                                                           0   +  2     +4    =6
                                                           
 1 1 0 1 0 0 1 0
128 64  32  16  8   4   2   1
 5+4=9
     101
    +100
-----------
    1001=9


其他进制转换
转成十六进制  四个二进制就是一个十六进制位
90=0x5a      
 010-1010
  5    (10)用A代替表示




转成八进制 三个二进制代表一个八进制位。
001 011 010
1     3   2
负数的二进制表现形式 负数的最高位是1.正数的最高位是0
6=110
-6:其实就是6的二进制取反+1
取反:将二进制的1变成0,0变成1。
  6=0000-0000  0000-0000  0000-0000  0000-0110
取反=1111-1111  1111-1111  1111-1111  1111-1001
+   0000-0000  0000-0000  0000-0000  0000-0001
---------------------------------------------------
    1111-1111  1111-1111  1111-1111  1111-1010=-6
   
   常量:表示在程序执行的过程中不能改变的量为常量。
   变量:就是在程序运行过程中可以改变的量为变量。(就是将不确定的数据进行存储,也就是需要在内存中开辟一个空间)
   (1)在程序的运行过程中,在指定范围内发生改变的量、
   格式1:数据类型  变量名=初始化值;例如:byte b=10;
  格式2:变量名=初始化值;byte b; b=10;
  变量:变量就是在刚开始设计程序的时候不清楚的情况下就用变量来表示。
  
  数据类型:
  java语言是强类型语言,对于每一种数据都定义了明确的数据类型,在内存中分配了不同的内存空间。
   数据类型:4类8种。
   整数类型:Byte(1量)short(2量)int(4量)long(8量)
   布尔类型:boolean 不确定,可以认为是1个字节。boolean只有两种结果,一个是true,另一个是false.
  字符串类型:char(2量)
  浮点类型:float(单精度 4量)double(8量)
  注意:整数默认int类型,long类型需要加L或者l后缀。
  浮点类型默认double类型,float类型需要加F或者f后缀。
  1.boolean 类型不参与转换。因为boolean的值是个常量。要么是true 要么false。
2.隐式的转换(从小到大) 
(byte,short,char)-->int-->long-->float-->double
3.强制转换(从大到小)
int b ;b=(byte)(b+2)
 格式:
数据类型
表达式的数据类型自动提升。
隐式的类型转换
byte 、short、char----->int
byte、short、int 、char----->long
byte、short 、char、int 、 long----------->float
byte、short、char、int 、long、float------->double
显示类型转换
当把高精度的变量的值赋给低精度的变量时,必须使用显示类型转运算(又称强制类型转换);
说明:当把整数赋给一个byte、short、int、long类型变量时,不可以超出这些变量的取值范围,否则必须进行强制类型转换。


所有的byte型、short型和char类型的值都将被提升到int型。
如果一个long类型的,计算结果就是long类型。
如果一个数值是float型,计算结果就是float型。
如果一个数值是double类型,计算结果就是double型。
Char类型是可以参与运算的。
变量什么时候定义?
当数据不确定时,需要对数据进行存储时,就定义一个变量来完成存储动作。
转义字符:
\n\r在windows系统里面是换行。
\b是退格
\t制表符。
\\:反斜杠字符
 运算符:
1.就是把常量和变量用符号连接起来,一般参与运算使用。
2.算数运算符:+,-,/,*,%,++,--
+)正号:加法,字符串连接符
System.out.println(“5+5=”+5+5);//5+5=55
System.out.println(5+5+“=5+5”);//10=5+5
%)
左边如果大于右边,结果是余数。
左边如果小于右边,结果是左边。
左边如果等于右边,结果是0.
正负号跟左边一致。
++与--:
++其实相当于把数值+1
--其实相当于把数值-1
参与运算:
如果在数据的后边,数据先操作,在++/--,Byte b=3,y; y=b++ 表示b先出去给y赋值,在回来b+1.y=3,b=4同理
如果在数据的前边,数据先++/--,在操作。Byte b=3,y; y=++b 表示b+1在出去给y赋值,在回家.y=4,b=4同理
赋值运算符=,+=,-=,*=,/=,%=
Int a=10;
把10赋值给int类型的变量a.
a+=20;//a=30
把左右两边的和赋值和a.
因为+=这种运算符,内含有强制类型转换。
比如:
short s1=2;
S1+=3;
相当于s1=(short)(s1+3);
关系运算符:==,!=,(大于)>,>=,(小于)<,<=
特点:关系运算符的结构都是boolean 类型
逻辑运算符:
&:与运算符,|:或运算符,!:非运算符,&&:短路与运算符,||:短路或运算符
&:符号的运算特点: 
true  &  true    =  true;  真  & 真  = 真
true  &  false   =  false;  真  & 假 = 假
false &  true    =  false;  假  & 真 = 假
false &  false   =  false;  假  & 假 = 假
&:与运算规律: 
&:与运算符的两边只要有一个是false,结果肯定是false。 
只有两边都为true,结果才是true。 
|:或符号的运算特点:              
true  |  true    =  true; 全为真,则为真
true  | false   =  true; 一真一假,则为真
false |  true    =  true; 
false |  false   =  false; 全为假,则为假
|:或运算规律: 
|:或运算的两边只要有一个是true,结果肯定是true。 
只有两边都为false。结果是false。 
^:异或 :和或有点不一样。 
^:运算特点。 
true  ^ true  = false; 全为真,则为假
true  ^ false = true; 一真一假,则为真
false ^ true  = true; 
false ^ false = false; 全为假,则为假
^异或的运算规律: 
如果两边结果相同,结果是 false。 
两边的结果不同,结果是true。 
  !:非运算符,判断事物的另一面。 
!true =false 
!false=true; 
!!true=true; 
面试题: 
&&和&运算的结果是一样的。但是运算过程有点小区别。 
&:无论左边的运算结果是什么,右边都参与运算。 
&&:当左边为false时,右边不参与运 
||和|运算的结果是一样的。但是运算过程有点小区别。 
|:无论左边的运算结果是什么,右边都参与运算。 
||:当左边为true时,右边不参与运算的。                                                      
位运算符是直接对二进制进行运算
<<左移运算   >>右移运算   >>>无符号右移运算   &与运算  |或运算    ^异或运算   ~反码运算 


<<左移几位其实就是该数据乘以2的几次方。左移:可以完成2的次幂运算 
>>右移几位其实就是该数据除以2的几次幂。右移:对于高位出现的空位,原来高位是什么就用什么补这个空位。 
>>>:无符号右移:数据进行右移时,高位出现的空位,无论原高位是什么,空位都用0补。 
^一个数异或同一个数两次,结果还是这个数。 
 
练习: 
对两个整数变量的值进行互换(不需要第三方变量) 
开发时,
第一种:使用第三方变量的形式,因为阅读性强。 
int a = 3,b = 5;
Int  temp   ;
Temp=a;
a=b;
b=temp;
Sytem.out.println("a="+a+",b="+b);输出前a=3;b=5建立第三方变量后输出a=5;b=3
第二种方法:
这种方式不要用,如果两个整数的数值过大,会超出int范围,会强制转换。数据会丢失精度。 
a= a + b;//a = 3 + 5;a = 8; 
b= a - b;//3+5-5 = 3;b = 3; 
a= a - b;//3+5-3 = 5;a = 5; 
第三种:技巧法
面试的时候用。 
a= a ^ b;//a = 3 ^ 5; 
b= a ^ b;//b = (3^5)^5; b = 3; 
a= a ^ b;//a = (3^5)^3; a = 5; 
三元运算符 
格式:(条件表达式)?表达式1:表达式2 ; 
如果条件为true,运算后的结果是表达式1, 
如果条件为flase,运算后的结果是表达式2 
三元运算符必须有结果。
示例:获取两个数中大数。 
int x = 3, y = 4, z; 
z = (x>y) ? x:y;  //z变量存储的就是两个数的大数。 
演示1:三元运算符
要求:1.我想知道60的最低四位是多少,通过三元运算符怎样代码
1.我还想知道60右移四位是多少
步骤:
1.获取60的最低四位,通过&15,
2.获取下一个四位,将60右移四位,通过无符号右移
Class opera.




teDemo1
{
   Public static void main(String[] args)
      {
       int  num=60;
       n1=num&15;
     System.out. println(n1>9?(char)(n1-10+‘A’):n1);//输出结果是67.
      //需要获取下一组四位,将60右移4位。
      Int  temp=60>>>4;
     // 对temp的值进行最低四位的获取。
int  n1=temp&15;
System.out. println(n2>9?(char)(n1-10+‘A’):n2);输出结果3
     }
 Short  s;    这两个表达式有什么区别
S+=2;
S=s+2
S+=2;编译通过因为+=运算符在给s赋值时,自动完成了强制转换操作。
S=s+2;编译失败,因为s会被提升为int类型。运算结果还int类型。无法赋值给short类型。
            
                         Java基础语法知识
1.基础语法知识:
三元运算符:
格式:(条件表达式)?表达式1:表达式2;
如果条件为true,运算后的结果是表达式1,
如果条件为false,运算获得结果是表达式2.
式列:获取两个数中的最大数。
三元运算符必须有结果。
 int x=3,z;
 z=(x>2)?100:200;
  System.out.println("z="+z);//z=100
1)判断结构
if:语句用于做判断使用的。常见与对于某一范围进行判断,或者几个变量进行判断,用boolean表达式的判断。
判断语句三种格式:
1.if(条件表达式)
{
执行语句;
}
执行流程:如果如果条件表达式为true,就执行语句,否则什么都不会执行。2. if(条件表达式)
{
      执行语句体;
}
else
{
执行语句体;
}
执行流程:如果if条件表达式为true,就if的语句执行体,否则,就执行else语句执行体;
3. if(条件表达式)
{
      执行语句体;
}
else if(条件表达式)
{
 执行语句体;
}
   else
{
执行语句体;
}


执行流程:
如果if(条件表达式):为true,就执行if的执行语句体。
如果else if(条件表达式):为true,就执行else if执行语句体。
否则,就执行else执行语句体。


注意事项:
什么时候用if语句?
第一种格式在判断条件为一种情况下使用。
第二种格式在判断条件为两种情况下使用。
第三种格式在判断条件多的情况下使用。
作用域:
所有变量的定义只在它所属的大括号内有效。如果if或者else里面控制语句体只有一条,可以省略大括号。
但是控制语句多时,就必须写大括号。
    程序流程控制
  1.判断结构
 3中格式:
 1.if(条件表达式){执行语句体;}
 2.if(条件表达式){执行语句体}else{执行语句体}//如果....否则
 3.if(条件表达式){执行语句体}else if(条件表达式){执行语句体} else{执行语句体}
 if else 结构  简写格式 : 变量=(条件表达式)?表达式1:表达式2;
 三元运算符:
               好处  :可以简化if else代码。
              弊端  :因为是一个运算符,所以运算完必须有一个结果。
  2.选择结构
  switch语句
  switch(变量)
  {
  case取值1;
  break;
  case取值2;
  break;
  case取值3;
  case取值4;
  break;
  default:
  执行语句;
  break;
  }
  if和switch语句很像。
  具体什么场景下,应用那个语句呢?
 如果判断的具体数值不多,而是符合byte,short,int,char这四种类型。
 虽然两个语句都可以使用,建议使用switch语句,因为效率稍高。
 其他情况:区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。
  
  3.循环结构
  while语句格式:
 1. while(条件表达式){执行语句;}
 2.do while语句格式:
 do{执行语句;}while(条件表达式);
 do while特点是条件无论是否满足,循环体至少被执行一次。
 for循环语句格式;
 for(初始化表达式;循环条件表达式;循环后的操作表达式){执行语句}
 
 1.变量含有字节的作用域,对于for来讲:如果将用于控制循环的增量定义在for语句中,那么该变量只在for语句内有效。
  for语句执行完毕,该变量在内存中被释放。
 2.for和while可以进行互换。如果需要定义循环增量。用for更合适。
 
 总结:什么时候使用循环结构?
 当要对默写语句执行很多次时,就使用循环结构。
 
 无限循环的最简单表现形式;
 for(;;){}
 while(true){}
  
  其实这就是累加思想。
  原理:通过变量记录住循环操作后的结果。
  
  循环嵌套
  for(){
  for(){}}
 其他流程控制语句
 break:(跳出) 语句:应用范围:选择结构和循环结构。
 continue(继续)语句:应用于循环结构。continue语句是结束本次循环继续下次循环。
 这两句离开应用范围,存在没有意义。
 这两个语句单独存在下面都不可以有语句,因为执行不到。
 标号的出现,可以让两个语句作用于指定范围。
选择结构:
switch 语句
  用于做选择使用的,一般用于几个常量的判断。
switch 语句会把几个常量值直接加载到内存中,在判断效率要比if语句高。所以就几个常量的判断,一般选择switch语句。
Switch(变量)   
{
Case取值1:
  执行语句;
Case取值 2:
  执行语句;
   Break;
.......
default:
  执行的语句;
  Break;
 }
格式的解释:
Switch:表示这里是的是switch语句,后面的是选项。
Switch语句一般和byte,short,int,char在一起使用。
Case:表示这里就是选项的值,后面的值将和表达式的值进行匹配。
Case后面的值不能够重复。
Break是switch语句执行结束的标记。
default:当所有的case和表达式都不匹配是,就走default的内容。
它相当于if....else语句,一般建议不要使用省略号。
执行流程:
进入switch语句后,就会根据表达式的值去找对应的case值。
如果没有找到,那么就会执行default的内容。




注意事项:
default可以放到执行语句的前面吗?
可以,但是不建议这样做。
Switch语句遇到break或者执行到程序的大括号就结束。


If和switch的特点:
If语句的特点:
1.对具体的值进行判断。
2.对区间判断。
3.运算结果是boolean类型的表达式进行判断。
Switch语句的特点:
1.对机体的值进行判断,
2.值的个数通常是固定的。
对几个固定的值判断,建议使用switch语句,因为switch语句会将具体的答案都加载进内存中。效率相对较高。
3.switch只能对基本数据类型进行操作,byte,short,int,char.
3)循环结构:
循环语句:while,do while ,for
如果我们发现有很多重复的内容的时候,就该使用循环改进代码。让代码看起来更简洁。
While循环语句的格式:
While(条件表达式)
{
循环执行体;
}


do  while循环语句格式:
do
{
循环执行体;
}
While(条件表达式)


While特点:条件如果不满足,不会走循环体。
注意事项:while是先判断在循环。
do while特点:条件无论是否满足,循环体至少执行一次。
注意事项:do while 先执行一次在回来判断。
for循环语句格式:
for(初始化表达式;循环体表达式;循环后的操作表达式)
{
执行语句;(循环体)
}
无限循环的最简单的表现形式:
for (; ; )
{
}
while (true)
{
}
循环注意:一定要注意哪些语句需要参与循环,哪些不需要参与。
变量有自己的作用域,对于for来讲:如果用于控制循环体的增量定义在for语句中,那么该变量只在for语句内有效。
总结:什么时候用循环语句?
当要对某些语句执行很多次时,就使用循环结构。。
什么情况用for,什么情况用while呢?
for和while可以互换,如果用于定义循环增量,用for更合适,因为节省内存。
建议使用for循环,节约内存。
循环嵌套:
简单的说就是循环体里面还有循环体。
就是大圈套小圈原理。
for(初始化表达式;条件表达式,循环后的操作表达式)
{
 for(初始化表达式;条件表达式;循环后表达式)
{
循环执行语句体。
}
}
总结:嵌套循环是外循环条件执行一次,内循环必须执行到条不满足才结束。
(1)累加思想:
原理:


通过变量的记录住每一次变化的结构,通过循环的形式,进行累加的动作。
(2)计数器思想:
原理:通过一个变量记录住数据的状态变化,也通过循环完成。
(3)大圈套小圈:
原理:尖朝上改变条件,尖朝下改变初始化值。
While 和for的区别:for是为循环而定义变量在循环结束就在内存中释放。
而while循环使用的变量在循环结束后还可以使用。比较浪费内存资源。
break和continue
break(跳出),continue(继续)
break语句;应用范围:选择结构和循环结构。
continue语句:应用于循环结构。
这两句话离开应用范围,存在是没有意义的。
2. 函数:
1.函数的概念:函数就是定义在类中具有特定功能的一段小程序。函数也称为方法。
2.函数的格式:
修饰符  返回值类型  函数名(参数类型 形式参数1,参数类型 形式参数2....)
{
执行语句;
return返回值;
}
返回值类型:函数运行后的结果的数据类型。
参数类型:是形式参数的数据类型。
形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数。
实际参数:传递形式为参数的具体数值。
return:用于结束函数。
返回值类型:该值会返回给调用者。
如何定义一个函数呢?
1.既然函数是一个独立的功能,那么该功能的运算结果是先明确的。
2.在明确在定义该功能的过程中是否需要未知内容参与运算。




函数的特点:
1.定义函数可以将功能代码进行封装,便于对该功能进行调用。
2.函数只用被调用才会被执行。
3.函数的出现提供了代码的复用性。
4.对于函数没有具体的返回值的情况,返回值类型用关键字void表示,那么该函数中的return语句如果在最后一行可以省略不写。
5.函数中只用调用函数,不可以在函数内部定义函数。
6.定义函数时,函数的结果谁调用返给谁。交由调用者处理。
7.可以自定义访问权限。
定义函数时需要注意:
1.功能只定义所需内容,不是该功能所需的内容不要定义。
2.如果非要定义,也是单独的定义一个功能来体现,以后开发时,尽量把函数定义成功能来体现。
3.不要将代码都定义在主函数中。
4.主函数的作用:对已有的功能进行调用。
5.函数名就是一个自己定义的标识符。函数名的定义,要尽量体现这个函数的功能。是为了增强该函数的阅读性。方便调用者使用,所以函数名一定要起得有意义。
6.静态方法只能调用静态方法。主函数是静态的。
7.返回类型和参数类型没有关系。
定义函数需要两个明确: -
1.这个函数的结果是什么,也就是返回值类型就是什么。
2.有没有未知数据参与运算。
2.函数的重载:
1.重载的概念:在同一个类中,允许存在一个以上的同名函数,只要它们的参数个数和参数类型不同即可。
2.重载的特点:与返回值类型无关,只看参数列表。
3.重载的好处:方便阅读,优化了程序的设计。
函数重载什么时候使用?
重载:当定义的功能相同,但参与运算的未知内容不同,那么,这时就定义一个函数名称以表示其功能,方便阅读。而通过参数列表的不同来区分多个同名函数。
3.数组:
1.数组的概述:
(1).概念:同一种类型数据的集合.其实就是一个容器。
(2)好处:可以自动给数组中的元素从0开始编号 ,方便操作这些元素。
(3)对数组的基本操作就是存和取。就是对角标的操作。
(4)既可以存储基础数据类型又可存储引用类型,基础数据类型的长度是固定的。数组的长度是固定的。集合是可变长度的,用于存储引用数据类型。






数组的定义:
1.元素类型[]数组名=new 元素类型[元素个数或者数组长度];
2.元素类型[]数组名={1,2,3,5,8}可以给数组一起赋值,也可以分别赋值。
3.元素类型[]数组名;
数组名=new 元素类型[元素个数或者数组长度];
数组的特点:
1.数组定义时:必须明确数组的长度(就是数组中可以存储的元素个数)因为数组的长度是固定的。
2.必须明确数组元素的类型。
4.数组的内存结构:
Java内存区域的划分:寄存器,本地方法区,方法区,栈内存,堆内存。
因为每一个内存区域对数据的处理方式不同。
栈内存的特点:存储的都是局部变量,一旦使用完就在栈内存中自动释放。节省内存。
堆内存的特点:存储的是实体。
1.堆内存中的实体都有内存地址值。
2.堆内存中的变量都有默认的初始化值。
3.对于没有任何的指向的数组实体,会视为垃圾,会在不定时的垃圾回收机制所收回。
(数组和对象,只要是new的 都会在堆内存中新建一个数组实体。)
5.操作数组常见的问题:
1.数组角标越界异常(ArraylndexoutofboundsExceoption):操作数组时,访问当了数组中不存在的角标。
2.空指针异常(NullPointerException):当引用没有任何指向值为null的情况,该引用还在操作数组实体。
6.对数组的常见操作:1.获取数组中的元素2.获取最值3.排序(冒泡排序)4.查找(折半查找)5.插入。
数组中的数组
二维数组[][]
格式1:int[][]arr=new int[3][2];
定义了名称为arr的二维数组。
二维数组中有3个一维数组。
每一个一维数组中有2个元素;
一维数组的名称分别为arr[0],arr[1],arr[2]
给第一个一维数组1角标位赋值为78写法是:arr[0][1]=78;
格式2:int[][] arr=new int[3][];
二维数组中有三个一维数组
每一个一维数组都是初始值为null.
可以对这个三个一维数组分别进行初始化
Arr[0]=new int [3];
Arr[1]=new int [1];
Arr[2]=new int [2];
可以通过打印二维数组中的元素,明确二维数组的元素初始化特点。            
 




Java 面向对象
1.面向对象的概念
?面向对象是相对面向过程而言,面向对象和面向过程都是一种思想
?面向过程是强调功能的行为。
?面向对象:将功能封装进对象,调用对象的功能。
?面向对象是基于面向过程的。
(1)面向对象的特点:
1.它符合现代人们的思考的一种方式。
2.它让复杂的事情简单化
3.让我们从曾经的执行者变成了现在的指挥者。
老师给我们讲了一个面向对象的例子:
其实面试官你本身就在用面向对象的方式思考问题。因为以面试官您的能力而言,来了一个软件项目的话,
您从需求分析到设计再到开发到测试,都可以完成
但是这样特别耗费时间,所以您为了提高效率,就需要去找一些具备专业编程经验的人来完成这些项目,
我正好就是那个具备专业编程经验的对象,你只要指挥我这个对象去做事就可以了,我会给你一个非常满意的结果,
至于过程您就不用管了。所以面试官您就是在用面向对象的方式思考问题,来提高公司的效率,而我就是具备专业编程经验的人。
我自己总结的面向对象的小故事:
我想洗衣服,我可以自己洗,但是很浪费时间。我可以调用洗衣机的功能,去帮我完成洗衣服的事情,我不需要知道他是怎么运行的,
怎么供电和怎么脱水的。他洗完了我知道洗干净就行。
其他我什么都不需要知道。只要调用它功能帮我完成这件事就行。
面向对象三个特征:封装,继承,多态
以后的开发过程:其实就是找对象用,没有对象,就创建一个对象。
找对象,建对象,使用对象,并维护对象的关系。
类和对象的关系:
类:就是现实生活中事物的描述。
对象:就是这类事物,实实在在存在的个体。
先要描述:提取对象中共性的内容。对具体的抽象。
映射到java中描述就是class定义的类。
具体对象就是java在堆内存中用new建立实体。
属性对应的是类中的变量,行为对应的是类中的函数(方法)
其实定义类,就是在描述事物,就是在定义属性和行为。属性和行为共同成为类中的成员(成员变量和成员方法)。
类中不必有主函数,不必保证独立运行,只有一个主函数入口调用就行。
成员变量和局部变量:
作用范围:
成员变量作用于整个类中。
局部变量作用于函数中,或者语句中。
在内存中的位置:
成员变量:在堆内存中,因为对象的存在,才在内存中存在。
局部变量:存在于栈内存中。
匿名对象:
匿名对象是对象的简化形式。
匿名对象两种使用情况:
1.当对象的方法只调用一次时,可以用匿名对象来完成,这样写比较简化。
如果一个对象对多个成员进行调用,必须给这个对象起个名字。
2.可以将匿名对象作为实际参数进行传递。
成员变量和局部变量的区别:
成员变量定义在类中,作用于整个类中。
局部变量定义在函数,语句,局部代码块中,只在所属的大括号区域有效。
成员变量在堆内存的对象中。局部变量在栈内存的方法中。
成员变量随着对象的消失而消失。局部变量随着所属区域的执行而存在,随着所属区域的结束而释放。
成员变量都有默认的初始值。局部变量没有默认的初始值。
面向对象的封装
封装:是指隐藏对象的属性和实现细节,仅对外提供公用的访问方式。
好处:
将变化隔离。
便于使用。
提高复用性。
提高安全性。
封装的原则:
将不需要对外提供的内容都隐藏起来。
把属性都隐藏,提供公共的方法对其访问。
Private:私有,权限修饰符。用于修饰类中的成员(成员变量,成员函数)。私有只在本类中有效。是最小权限。
注意:私有仅仅是封装的一种表现形式。
之所以对外提供访问方式,就是因为可以在访问方式中加入逻辑判断等语句。
对访问的数据进行操作。提高代码的健壮性。
构造函数特点:
1.函数名于类名相同
2.不用定义返回值类型。
3.不可以写return语句。
2.多个构造函数是以重载的形式存在的。
对象一建立就会调用与之对应的构造函数。
构造函数的作用:可以给对象进行初始化。
构造函数的小细节:
当一个函数没有定义构造函数时,那么系统会默认给该类加入一个空参数的构造函数。
当在类中自定义了构造函数后,默认的构造函数就没有了。
构造函数和一般函数在写法上有不同。
在运行上也有不同。
构造函数是在对象一建立就运行,给对象初始化。
而一般方法是对象调用才执行,是给对象添加对象具体的功能。
一个是对象一建立,构造函数就只运行一次。
而一般方法是只有被对象调用才执行,可以调用多次。
多个构造函数是以重载 的形式存在的。
什么时候定义构造函数呢?
当分析事物时,该事物存在具备一些特性或者行为,那么将这些内容定义在构造函数中。
构造代码块:
作用:给对象进行初始化。
对象一建立就运行,而且优先于构造函数执行。
构造代码块和构造函数的区别:
构造代码块是给所有对象进行初始化。
而构造函数是给对应的对象进行初始化。
构造代码块中定义的是不同对象共性的初始化内容。
2.this关键字
this:看上去,是用于区分局部变量和成员变量同名情况。
this为什么可以解决这个问题呢?
this到底代表的是什么呢?
this:就是代表本类的对象,到底代表哪一个呢?
this代表它所在函数所属对象的应用。
简单说:哪个对象在调用this所在的函数,this就代表那个对象。
this的应用:当定义类中功能时,该函数内部要使用到调用该函数的对象时,这时用this来表示这个类。
3.static关键字
静态:static.
用法:是一个修饰符,用于修饰成员(成员变量,成员函数)。
当成员被静态修饰后,就多了一个调用方式,除了可以被对象调用外,
还可以直接被类名调用。类名.静态成员。
static特点:随着类的加载而加载。也就说:静态会随着类的消失而消失。说明它的生命周期最长。
优先于对象存在。
明确一点:静态是先存在。对象是后存在的。
被所有对象所共享。
可以直接被类名调用。
实例变量和类变量的区别:
存放位置。
类变量随着类的加载而存在于方法区中。
实例变量随着对象的建立而存在于堆内存中。
生命周期:
类变量生命周期最长,随着类的消失而消失。
实例变量生命周期随着对象的消失而消失。
静态使用注意事项:
静态方法只能访问静态成员。
非静态方法即可以访问静也可以访问非静态。
静态方法中不可以定义this,super关键字。
因为静态优先于对象存在。所以静态方法中不可以出现this.
静态有利有弊
利处:对对象的共享数据进行单独空间的存储,节省空间。没有必要每一个对象中都存储一份。
可以直接被类名调用。
弊端:生命周期过长。
访问出现局限行。(静态虽好,只能访问静态)
public static void main(String[]args)
主函数:是一个特殊的函数。作为成函数的入口,可以被jvm调用。
主函数的定义:
public:代表着该函数访问权限最大。
static:代表着主函数随着类的加载就已经存在了,随着类的消失而消失。
void: 没有具体的返回值类型。
main: 不是关键字,但是是一个特殊的单词,可以被jvm识别。
(String[] args):函数的参数,参数类型是一个数组。该数组中的元素是字符串。字符串类型的数组。
主函数是固定格式:jvm识别。
什么时候使用静态?
要从两方面下手:
因为静态修饰的内容有成员变量和函数。
什么时候定义静态变量(类变量)呢?
当对象中出现共享数据时,该数据被静态所修饰。
对象中的特有数据要定义成非静态存在于堆内存中。
什么时候定义静态函数呢?
当功能内部没有访问到非静态数据(对象的特有数据)那么该功能可以定义成静态的
静态的应用。
每个应用程序中都有共性的功能。
可以将这些功能进行抽取,独立封装。
以便复用,
虽然可以通过建立ArrayTool的对象使用这些工具方法,对数据进行操作。
发现了问题:
1.对象是用于封装数据的,可是ArrayTool对象并未封装特有数据。
2.操作数组的每一个方法都没有用到ArrayTool对象的特有数据。
这时就考虑,让程序更严谨,是不需要建立对象的。
可以将ArrayTool中的方法都定义成static的,直接通过类名调用即可。
将方法都静态后,可以方便于使用,但是该类还是可以被其他程序建立对象的。
为了更为严谨,强制让该类不能建立对象。
可以通过将构造函数私有化完成。
接下来,将ArrayTool文件发送给其他人,其他人只要将该文件设置到classpath路径下,就可以使用该工具类。
但是,很遗憾,该类中到底定义了多少个方法,对方却不清楚。因为该类没有使用说明书。
开始制作程序的说明书。java的说明书通过文档注释来完成。
/**
这是一个可以对数组进行操作的工具类,该类提供了,获取最值,排序等功能。
@author  张三
@version   v1.8




*/
 public class   ArrayTool
{
/**
空参数构造函数。
*/
private ArrayTool(){}
/**
获取一个整形数组中的最大值。
@param  arr 接收一个int类型的数组。
@return  会返回一个该数组中的最大值。
*/
public static int getMax(int[] arr) 
{
int max = 0;
for (int x=1;x {
if (arr[x]>arr[max])
    max = x;
}
return arr[max];
}/**
获取一个整形数组中的最小值。
@param  arr 接收一个int类型的数组。
@return  会返回一个该数组中的最小值。
*/


  public static int getMin(int[] arr) 
{
int min = 0;
for (int x=1;x {
if (arr[x]    min = x;
}
return  arr[min];
}
/**
给int数组进行选择排序。
    @param  arr 接收一个int类型的数组。
*/
public static void selectsort(int[] arr)
{
for (int x=0;x {
for (int y=x+1;y {
if (arr[x]>arr[y])
{
swap(arr,x,y);
}
}
}
}
/**
给int数组进行冒泡排序。
    @param  arr 接收一个int类型的数组。
*/


public static  void bubblesor(int[] arr)
{
for (int x=0;x {
for (int y=0;y {
if (arr[y]>arr[y+1])
{
swap(arr,y,y+1);
}
}
}
    
}


/**
给数组中元素进行位置的置换。
    @param  arr 接收一个int类型的数组。
@param  a  要置换的位置。
    @param  b  要置换的位置。
*/
private static void swap(int[] arr,int a,int b)
{
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
/**
用于打印数组中的元素。打印形式是:[elemet1, element2, ...]
*/
private static void printArray(int[] arr)
{
System.out.print("[");
for (int x=0;x {
if (x!=arr.length-1)
System.out.print(arr[x]+",");
else
System.out.println(arr[x]+"]");
}
}


}
/*
一个类中默认会有一个空参数的构造函数。
这个默认的构造函数的权限和所属类一致。
如果类被public修饰,那么默认的构造函数也带public修饰符。
如果类没有被public修饰,那么默认的构造函数,也没有public 修饰。
默认构造函数的权限是随着类的变化而变化的。
*/
静态代码块: 
格式: 
Static{ 静态代码块中的执行语句 } 
特点:随着类的加载而执行,只执行一次,并优先于主函数 
对象初始化的顺序: 
静态代码块——>静态主函数——>构造代码块——>构造函数 
例子: 
class person
{
private int age;
public void setAge(int a)
{
  if (a>0 && a<130)
  {
 age = a;
  speak();
  }
  else
  System.out.println("非法年龄");


}
void speak()
{
System.out.println("age="+age);
}
}






class  personDemo
{
public static void main(String[] args) 
{
person p = new person();
//p.setAge (-20);
//p.speak();
}
}
class Person {
private?String name;
private?int age;
private?static?String country ="cn";
{
System.out.println("cry...");
}
public int getAge()
{
returnage;
}
public void setAge(intage)
{
this.age = age;
}
Person(){}
Person(String name,int age)
{
this.name = name;
this.age = age;
}
// 进行name显示初始化值,等同于设置name
public void?setName(String name)
{
this.name = name;
}
public?String getName()
{
return name;
}
public?void speak()
{
System.out.println("name=" + name +"..age=" + age);
show();// 打印当前对象的country,this也被省略
}
public static void show()
{
System.out.println("country=" + country);
}
}
class PersonTest
{
public static void?main(String[] args)
{
Person p =new Person(“李四”,19);
p.setName("张三");
p.setAge(20);
p.speak();
}


}
Person p =?new?Person("张三",19);
这句话都做了什么? 
1,因为new用到了Person.class,所以会先找到Person.class文件并加载到内存中 
2,执行该类中的static代码块,如果有的话,给Person.class类进行初始化 
3,在堆内存中开辟空间,分配内存地址值。
4。在堆内存中建立对象的特有属性,并进行默认初始化(name=null age=0 country=null) 
5。对属性进行显示初始化(也就是属性初始化,如果没有赋值就是默认初始化的值 name=null age=0 country="cn") 
6。对对象进行构造代码块初始化 
7。对对象进行对应的构造函数初始化 
8。将内存地址赋给栈内存中的p变量 


4.单列设计模式
设计模式: 
解决某一类问题最行之有效的方法,Java中23种设计模式。 
单例设计模式:解决一个类在内存中只存在一个对象 
比如对于多个程序使用同一个配置信息对象时,就需要保证该对象的唯一性。 
想要保证对象唯一: 
为了避免其他程序过多建立该类对象,先禁止其他程序建立该类对象; 
还为了让其他程序可以访问到该类对象,只好在本类中自定义一个对象; 
为了方便其他程序对自定义对象的访问, 可以对外提供一些访问方式; 
单例设计模式之饿汉式 
Single类一进内存,就已经创建好了对象。 
思路: 
将构造函数私有化; 
在类中创建一个本类对象; 
提供一个公共的访问方法,可以获取到该类对象; 
步骤: 
//将构造函数私有化
private Single(){} 
//在类中创建一个本类对象(final关键字是最终的意思,被final修饰的变量会成为全局常量)
private static  finla  Single  s  =new Single(); 
//提供一个公共的访问方法,可以获取到该类对象
public static?Single getInstance(){ 
return?s; 

单例设计模式之懒汉式 
对象是方法被调用时才初始化,也叫对象的延时加载 
Single类进内存,对象还没有存在,只有调用了getInstance方法时,才建立对象。 
步骤: 
private?Single(){} 
private?static Single single =null; 
public static?Single getInstance()

if(single==null)

synchronized(Single.class)

if(single==null) 
single  s=new Single(); 


return s; 

为什么有饿汉式和有懒汉式呢? 
原因是面试中会考到,因为面试考的都是懒汉式,懒汉式中会出现很多的安全隐患。这里面涵盖了很多的知识点。


实际开发中用饿汉式,因为在考虑多线程时会比较安全,懒汉式的存在安全问题,解决安全问题时,
双重判断,加入锁或同步代码块。 
总结: 
饿汉式:一开始对象就初始化。 因为饿汉式在考虑多线程时比较安全。较为浪费内存空间,但这是合理的浪费。
懒汉式:对象调用方法时,才初始化,也叫做对象的延时加载。 比较节省内存,因为只有调用才占内存。
养成良好的节约内存习惯固然好,但是我们在多线程开发的中,要选择饿汉式,较为安全。这种浪费资源是合理的。




Java的继承
1.继承的概述
继承:
1.提高了代码的复用性。
2.让类与类之间产生了关系。有了这个关系,才有了多态的特性。
注意:千万不要为了获取其他类的功能,简化代码而继承。
必须是类与类之间有所属关系才可以继承。所以关系is a.
java 语言中:java只支持单继承,不支持多继承。
当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个。
因为多继承容易带来安全隐患。
但是java保留了这种机制。并用另一种体现形式来完成表现。多实现。
java支持多层继承。也就是一个继承体系
如何使用一个继承体系中的功能呢?
想要使用体系,先查询体系父类的描述。因为父类中定义的是该体系中共性的功能。
通过了解共性功能,就可以知道该体系的基本功能。
那么这个体系已经可以基本使用了。




那么在具体实现时,要创建子类的对象,为什么呢?
一是因为有可能父类不能创建对象。
二是创建子类对象可以使用更多的功能,包括基本的也包括特有的。
简单一句话:查阅父类功能,创建子类对象使用功能。
大家记住:java中一个孩子只有一个父亲,不允许有多个父亲。
子父类出现以后,类成员的特点:
类中成员:
1.变量。
如果子类中出现非私有的同名成员变量时,
子类要访问本类中的变量,用this。
子类要访问父类中的同名变量,用super。
super的使用和this的使用几乎一致。
super代表的是父类对象的引用。
2.子父类中函数。
当子类出现和父类一模一样的函数时,
当子类调用该函数,会运行子类函数的内容。
这种情况是函数的另一个特性:重写(覆盖)。


当子类继承了父类,沿袭了父类的功能,到子类中,
但是子类虽具备该功能,但是功能内容却和父类不一致,
这时,没有必要定义新功能,而是使用覆盖的特性,
保留父类的功能定义,并重写功能内容。
覆盖:
1.子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败。
2.静态只能覆盖静态。
记住大家:
重载:只看同名函数的参数列表。
重写:子父类方法要一模一样。包括返回值类型。
3.子父类中构造函数。
3.子父类中的构造函数。
在对子类对象进行初始化时,父类的构造函数也会运行。
那是因为子类的构造函数默认的第一行有一条隐式的语句 super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();
为什么子类一定要访问父类中的构造函数。
因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。
所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
注意:super语句一定定义在子类构造函数的第一行。
子类的实例化过程.
结论:
子类的所有的构造函数,默认都会访问父类中空参数的构造函数。
因为子类每一个构造函数内的第一行都有一句隐式super();
当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定访问父类中的构造函数。
当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。
为什么super构造函数 和this构造函数不能同时定义在一行?
 答:因为他们都必须写在第一行。
为什么要写第一行?
因为初始化动作要做。
final关键字
final关键字
final :最终。作为一个修饰符。
1.final可以修饰类,方法,变量。
2.final修饰的类不可以被继承。为了避免被继承,被子类复写功能。
3.被final修饰的方法不可以被复写。
4.被final修饰的变量是一个常量。只能被赋值一次。既可以修饰成员变量。又可以修饰局部变量。
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值其个名字。方便阅读。
而这个值不需要改变,所以加上final修饰。作为常量:常量的书写规范所以字母都大写,如果有多个单词组成。
单词间通过_连接。
5.内部类定义在类中的局部位置上,只能访问局部被final修饰的局部变量。


抽象类
当多个类中出现相同功能,但是功能主体不同。
这时可以进行向上抽取。这时,只抽取功能定义,而不抽取功能主体。
抽象:看不懂
抽象类的特点:
1.抽象方法一定在抽象类中。
2.抽象方法和抽象类都必须被abstract关键字修饰。
3.抽象类不可以用new创建对象。因为调用抽象方法没有意义。
4.抽象类中的抽象方法要被使用,必须有子类复写其所有的抽象方法后,建立子类对象调用。
如果子类覆盖部分抽象方法,那么该子类还是一个抽象类。
抽象类和一般类没有太大的不同。
该如何描述事物,就如何描述事物只不过,该事物出现了一些看不懂的东西。
这些不确定的东西,也就是该事物的功能,需要明确出现,但是无法定义主体。
通过抽象方法来表示。
抽象类比一般类多了抽象函数。就是在类中可以定义抽象方法。
抽象类不可以实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
模板设计方式:
需求:获取一段程序运行的时间。
原理后期程序开始和结束的时间并相减即可。
获取时间:system.currentTimeMills();   current卡润特
当代码完成优化后,就可以解决这类问题。
这就是模板设计方式。
什么是模板方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分是不确定,而确定的部分在使用不确定的部分。
那么这时就将不确定的部分暴露出去。由子类去完成。
接口:
接口:初期理解,可以认为是一个特殊的抽象类。
当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
class :用于定义类
interface:用于定义接口。
接口定义时,格式特点:
1.接口中常见的定义:常量,抽象方法。
2.接口中的成员都有固定修饰符。
常量:public static final
方法: public abstract
记住:接口中的成员都是public修饰的。
接口:是不可以创建对象的,因为有抽象方法。
需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类可以实例化。
否则子类是一个抽象类。
接口可以被类多实现,,也是对多继承不支持的转换形式。java支持多实现。
implements 实现。 
接口的特点:
1.接口是对外暴露的规则。
2.接口是程序功能扩展。
3.接口可以用来多实现。
4.类与接口直接是实现关系,而且类可以继承一个类的同时实现多个接口。
5.接口与接口直接可以是继承的关系。
降低偶合性。
多态
多态:可以理解为事物存在的多种体现形态。
1.多态的体现:
父类的引用指向自己的子类对象。
父类的引用可以接收自己的子类对象。
instanceof:实例 关键字


2.多态的前提:
必须是类与类之间有关系。要么继承,要么实现。通常还有一个前提:存在覆盖。
3.多态的好处:
多态的出现大大提高程序的扩展性。
通常还有一个前提:存在覆盖。
4.多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员。
5.多态的应用:
Animal a=new Cat();//类型提升,向上转型。把猫提升为了动物。
//如果想要调用猫的特有方法是,如何操作?
//强制将父类的引用转成子类类型,向下转型。
Cat c = (cat)a;
c.catchMouse();
/*
千万不要出现这样的操作,就是将父类的对象转成子类对象。
我们能转换的是父类的引用指向了自己的子类对象时,该引用可以被提升,也可以被强制转换。
多态自始至终都是子类对象在做着变化。
//Animal a = new Animal();这样做是错误的,千万不要出现这样的操作,就是将父类的对象转成子类对象。
//Cat c = (cat)a;
*/
6.多态的出现代码中的特点(多态使用的注意事项)
在多态中成员函数的特点(父类引用指向自己的子类):
在编译时期:参阅引用类型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。
Object:是所有对象的直接或者间接父类,传说中的上帝。
该类中定义的肯定是所有对象都具备的功能。
Object类中已经提供了对对象是否相同的比较方法。equals:比较对象的地址值。
如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己的特有比较内容即可。这就是覆盖。
内部类:
1.内部类可以直接访问外部类中的成员,包括私有。
之所以可以直接访问外部类中的成员,是因为内部类中持有一个外部类的引用,格式:外部类名.this
2.外部类要访问内部类,必须建立内部类对象。
类能不能被私有修饰?
答:可以,内部类可以被私有修饰。当内部类在外部类的成员位置时,可以。
访问格式:
1.当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。
可以直接建立内部类对象。
格式 :外部类名.内部类名  变量名 =  外部类对象.内部类对象;
Outer.Inner in =new Outer().new Inner();
2.当内部类在成员位置上,就可以被成员修饰符所修饰。
比如,private:将内部类在外部类中进行封装。
static:内部类就是具备static的特性。
当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
     new Outer.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员呢?
       Outer.Inner.funtion();

注意:当内部类中定义了静态成员,该内部类必须是static的。
当外部类中的静态方法访问内部类时,内部类也必须是static的。
当描述事物时,事物的内部还有事物,该事物用内部类来描述。
因为内部事物在使用外部事物的内容。
内部类定义在局部时,
1.不可以被成员修饰符修饰。
2.可以直接访问外部类中的成员,因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。
匿名内部类:
1.匿名内部类其实就是内部类的简写格式。
2.定义匿名颞部类的前提:
内部类必须是继承一个类或者实现接口。
3.匿名内部类的格式: new 父类或者接口(){定义子类的内容}
4.其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。
5.匿名内部类中定义的方法最好不要超过3个。
异常处理机制
异常:就是程序在运行时出现不正常情况。
java在设计异常体系时,将容易出现情况都封装成了对象。
异常的由来:问题也是现实生活中一个具体的事物,也是通过java的类的形式进行描述。并封装成对象。
其实就是java对不正常情况进行描述后的对象体现。
对于严重的,java通过Error类进行描述。
对于Error一般不编写针对性的代码对其进行处理。
对与非严重的,java同Exception类进行描述。
对与Exception可以使用针对性的处理方式进行处理。
无论Error或者Exception都具有一些共性内容。
比如不正常的情况信息,引发原因等。
Throwable
      |------Error


 |------Exception
2.异常的处理:
一般处理:
try
{
需要被检测的代码
}
catch(异常类 变量)
{
处理异常的代码;(处理方式)
}
finally
{
一定执行的语句;
}
3.对捕获的异常对象进行常见方法的操作。
String getmessage():获取异常信息.
在函数上声明异常。
便于提高安全性,让调用者进行处理。不处理编译失败。
对异常的处理:
1.声明异常时,建议声明更为具体的异常,这样处理的可以更具体。
2.对方声明了几个异常,就对应有几个catch块。不要定义多余的catch块。
如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。
建立在进行catch处理时,catch中一定要定义具体处理方式。
不要简单定义一句e.printStackTrace().
也不要简单的就书写一条输出语句。
因为项目中会出现特有的问题,
而这些问题并未被java所描述并封装对象。
所以对于这些特有的问题可以按照java对问题封装的思想。
将特有问题,进行自定义的异常封装。
自定义异常:
需求:在本程序中,对于除数是-1,也视为是错误的是无法进行运算的。
那么需要对这个问题进行自定义的描述。
当在函数内部出现了throw抛出异常对象,那么就必须要给出对应的处理动作。
要么在内部try catch处理。
要么在函数上声明让调用者处理。
一般情况下,函数出现异常,函数上需要声明出来。
发现打印出的结果中只有异常的名称,却没有异常的信息。
因为自定义的异常并未定义信息。


如何定义异常信息呢?
因为父类中已经把异常信息的操作都完成了。
所以子类只要在构造时,将异常信息传递给父类通过super语句。
那么就可以直接同getMessage方法获取自定义的异常信息。
自定义异常:
必须是自定义类继承Exception.
继承Exception原因:
异常体系有一个特点:因为异常类和异常对象都被抛出。
他们都具可抛性。这个可抛性是Throwable这给体系中独有的特性。
只有这个体系的类和对象才可以被throws 和throw 操作。
只有这个体系中的类和对象才可以被throws和throw操作。
throws和throw的区别
throws使用在函数上。
throw使用在函数内。
throws后面跟的异常类。可以是多个。用逗号隔开。
throw后面跟的是异常对象。
Exception中有一个特殊的子类异常RuntimeException运行时异常。
如果在函数内部抛出该异常,函数上可以不声明,编译一样通过。
如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过。
之所以不用在函数声明,是因为不需要让调用者处理。
当该异常发生,希望程序停止。因为在运行时,出现了无法继续运行的情况,希望停止程序后,对代码进行修正。
自定义异常时:如果该异常的发生,无法再继续进行运算。
就让自定义异常继承RuntimeExcepton.
对于异常分两种:
1.编译时被检测的异常。(编译时异常。Exception以及他的子类必须在函数上声明。是可以处理的异常。
2.要么抛异常,要么try catch处理)
2.编译时不被检测的异常(运行时异常。RuntimeException以及其子类)
3.finally代码块:定义一定执行的代码。
4.通常用于关闭资源。
第一个格式:
try{} catch(){} 
  第二个格式:
try{} catch(){} finally{}
第三个格式:
try{] finally{}
记住一点:catch是用于处理异常。如果没有catch就代表异常没有被处理过,
如果该异常时检测是异常。那么必须声明。
异常在子父类覆盖中的体现。
1.子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者改异常的子类。
2.如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3.如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。
如果子类方法发生异常,就必须进行try处理。绝对不能抛。
----------------------------------------------
异常:
异常是什么?是对问题的描述。将问题进行对象的封装。
异常体系:
    Throwable
   |---Error
|---Exception
    |----RuntimeException
异常体系的特点:异常体系中所有类以及建立的对象都具备可抛性。
也就是说可以被throw和throws关键字所操作。
只有异常体系具备这个特点。
throw 和 throws 的用法:
throw 定义在函数内,用于抛出异常对象。
throws 定义在函数上,用于抛出异常类,用逗号隔开。
当函数内容有 throw 抛出异常对象,并未进行try处理,必须要在函数上什么,都在编译失败。
注意: RuntimeException 除外。也就是说,函数内如果抛出异常 RuntimeException 异常,函数上可以不用声明。
如果函数声明了异常,调用者需要进行处理。处理方式可以 throws 和try。
-----------------------------------------
异常有两种:
编译时被检测异常:
该异常在编译时,如果没有处理(没有抛出也没有try),编译失败。
该异常被标识,代表这可以被处理。
运行时异常(编译时不检测)
在编译时,不需要处理,编译器不检查。
该异常的发生,建议不处理,让程序停止。需要对代码进行修正。
异常处理语句:
try
{
需要被检测的代码;
}
catch ()
{
处理异常的代码;
}
   finally
   {
  一定会处理的代码;
   }
有三个结合格式:
第一种格式:           第二种格式                      第三种格式
try                     try                               try
{                        {                                 {

} }                                 }
catch ()               finally                           catch()
{                        {                                 {
}                        }                                 }
                                                         finally
                                                           }
                                                          {
                                              
注意;                  {
1.finally 中定义的通常是关闭资源代码, 因为资源必须被释放。
2.finally 只有一种情况不会执行。当执行到 System.exit(0); finally 不会执行。
----------------------------------------------------------
自定义异常:
定义继承 Exception 或者 RuntimeException
1.为了让自定义类具备可抛性。
2.让该类具备操作异常的共性方法。
当要定义异常的信息是,可以使用父类已经定义好的功能。
自定义异常信息传递给父类的构造函数。
class MyException extends Exception
{
MyException(String message)
{
super(message);
}
}
自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。
-----------------------------------------
异常的好处:
1.将问题进行封装。
    2.将正常流程代码和问题代码相分离,方便于阅读。
异常的处理原则:
1.处理方式有两种 try 或者 throws.
2.调用到抛出异常的功能时,抛出几个,就处理几个。
一个 try 对应 多个catch.
3.多个 catch ,父类的 catch 放到最下面。
4.catch 内,需要第一针对性的处理方式。不要简单定义printStackTrace 输出语句。
也不要不写。
当捕获到的异常,本功能处理不了时,可以继续在 catch 中抛出。
try
{
throw new AExcrption();
}
catch (AException e)
{
throw e;
}
如果该异常处理不了,但是不属于该功能出现的异常。
  可以将异常转换后,在抛出和该功能相关的异常。
  或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去。
当调用者知道。并处理。也可以将不会异常处理后,转换新的异常。
try
{
throw new AException();
}
catch (AEexception e)
{
//对AException处理。
throw  new  BException();
}
比如,汇款的例子。
  异常的注意事项:
在子父类覆盖时:
1.子类抛出的异常必须是父类的异常的子类或者子集。
2.如果父类后者接口没有异常抛出是,子类覆盖出现异常,只能 try 不能抛。

参阅:
ExceptionTest.java 老师用电脑上课。
ExceptionTest.java 图像面积。

包(package) 
1、对类文件进行分类管理 
2、给类提供多层命名空间 
3、写在程序的第一行 
4、类名的全称是 包名.类名 
5、包也是一种封装形式 
6、Javac -d . 类名.Java???? 




                        Java的 多线程
进程:是一个正在执行中的程序。
每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
线程:就会死进程中的一个独立的控制单元。线程在控制着进程的执行。
一个进程至少有一个线程。
Java  jvm启动的时候会有一个java.exe
该进程中至少有一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中。
该线程称之为主线程。
扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收机制的线程。
1.如何在自定义的代码中,自定义一个线程呢?
2.通过对API的查询,java已经提高了对线程这类事物的描述,就是Thread类。
创建线程的第一种方式:继承Thread类。
步骤:
1.定义类继承Thread.
2.复写Thread类中的run方法。
目的:将自定义代码存储在run方法。让线程运行。
3.调用线程的start方法。
该方法两个作用:启动线程,调用run方法。
发现运行结果每一次都不同。因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行。
名义一点,在某一时刻,只能有一个程序运行。(多个线程除外
cpu在做社快速的切换,一达到看上去是一个线程在运行的效果。我们可以形象把多线程的运行行视为在互相抢夺cpu的执行权。
这就是多线程的一个特点:随机性。谁抢夺谁执行,至于执行多长,cpu说了算。
为什么要覆盖run方法呢?
Thread类用于描述线程。
该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法。
也就是说Thread类中的run方法,用于存储线程要运行的代码。
创建线程方式一
1.子类覆盖父类中的run方法,将线程运行的代码存放在run中。
2.建立子类对象的同时线程也被创建。
3.通过调用start方法开启线程。


原来线程都有自己默认的名称。Thread-编号 该编号从0开始.
static Thread currentThread():获取当前线程对象。
getName():获取线程名称。
设置线程名称:setName或者构造函数。
例题:
需求;简单的买票程序。
多个窗口卖票
创建线程的第二种方式:实现Runnale接口
1.定义类实现Runnable接口。
2.覆盖Runnable接口中的run方法。将线程要运行的代码存放在该类run方法中。
3.通过Thread类建立线程对象。
4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将Runnable接口的子类对象是Thread的构造函数。
因为自定义run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法。
就必须明确该run方法所属的对象。
5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
实现方法和继承方法有什么区别呢?
实现方式的好处:避免了单继承的局限性。
在定义线程会时,建立使用实现方式。
两种方式区别:
继承Thread:线程代码存放在Thread子类run方法中。
实现Runable :线程代码存放在接口的子类的run方法中。
通过分析,发现,打印出0,-1,-2等错票
多线程的运行出了安全问题。
问题的原因:
当多条语句在操作同一个线程共享的数据时,一个线程对多条语句只执行了一部分还没有执行完,另一个线程参与进来执行。
导致共享属性的错误。
解决办法:
对多条操作共享数据的语句,值能让一个线程执行完,在执行的过程中,其他线程不可以参与执行。
java对于多线程的安全问题提供了专业的解决方式。
就是同步代码块
synchronized(对象)
{
需要同步的代码
}
对象如同锁。持有锁的线程可以在同步中执行。没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁。
同步的前提:
1.必须要有两个或者两个以上的线程。
2.必须是多个线程使用同一个锁。
必须保证同步中只有一个线程在运行。
好处:解决了多个线程的安全问题。
弊端;多个线程需要判断锁,较为消耗资源。
同步函数用的是哪一个锁呢?
函数需要被对象调用}。那么函数都有一个所属对象引用。就是this。
所以同步函数使用的锁是this.
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现不在是this。因为静态方法中不可以定义this.
静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是class
静态的同步方法,使用的锁是该方法锁在的字节码文件对象。类名.class
/*
单例设计模式
 饿汉式
 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()
{
if(s==null)
 {
synchronized(single.class)
{
if(s==null)
s= new single();

   }  
}
return s;
}
}
线程间通信
例程
思考1:wait( ),notify( ),notifyAll( ),
都使用在同步中,因为对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法都定义在object类中呢?
因为这些方法在操作同步中线程时,都必须是标识它们所操作线程只有锁。
只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒。
也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。
思考2:wait(),释放资源,释放锁。
Sleep();:释放资源,不释放锁。
对于多个生产者和消费者。
为什么定义while判断标记。
原因:让被唤醒的线程在一次判断标记。
为什么定义notifyAll();
因为需要唤醒对方线程。因为只有notify,容易唤醒本方线程的情况。导致程序中的所有线程都等待。
JDK1.5中提供了多线程升级解决方案。将同步synchronized替换成现实Lock操作。
将Object中的wait,notify,notifyAll替换成了Condition对象。
该对象可以Lock锁,进行获取。
该式列中,实现了本方值唤醒对方操作。
停止线程
Stop方法已经过时。
如何停止线程?
只有一种,run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住了循环,就可以让run方法结束,也就是线程结束。
特殊情况:
当线程处于了冻结状。
就不会读取标记,那么线程就不会结束。
当没有指定的方式让冻结的线程恢复到运行状态来,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
Thread类提供该方法 interrupt();
join:
当A线程执行到了B线程的。join()方法时,A就会等待。等B线程都执行完,A才执行。
join可以来临时加入线程执行。
是跟cpu要执行权。
String类
字符串是一个特殊的对象。字符串一旦初始化就不可以被改变、
String str=“abc”;//str是一个类类型变量,“abc”是一个对象。
字符串最大特点:一旦被初始化就不可以被改变。
String str=“abc”;String str1=new String(“abc”);这两个表达式有什么区别?
Str在内存中有一个对象。Str1在内存中有两个对象。
String类适用于描述字符串事物。
那么他就提供了多个方法对字符串进行操作。
常见的操作有哪些?
"abcd"
1.获取
1.1字符串中的包含的字符数,也就是字符串的长度。
int length():获取长度。
1.2根据位置获取位置上某个字符。
char charAt(int index):
1.3根据字符获取该字符在字符串中位置。
int indexOf(int ch):返回的是ch在字符串中第一次出现的位置。
int indexOf(int ch,int fromIndex):从fromIndex指定位置开始,获取ch在字符串中出现的位置。


int indexOf(String str):返回的是str在字符串中第一次出现的位置。
int indexOf(String str,int fromIndex):从fromIndex指定位置开始,获取str在字符串中出现的位置






2.判断
2.1 字符串中是否包含某一个子串
      boolean contains(str):
特殊之处:indexOf(str):可以索引str第一持出现的位置,如果返回-1,表示该str不在字符串中存在。
所以,也可以用于对指定判断是否包含。
if(str.indexOf("aa")!=-1)
而且该方法既可以判断,有可以获取出现的位置。
2.2字符中的是否有内容
    boolean isEmpty():原理就是判断长度是否为。
2.3 字符串是否是指定内容开头。
     boolean StartsWith(str);
2.4字符串是否是以指定内容结尾
    boolean endsWith(str);
2.5 判断字符串内容是否相同,复写object类总的equals方法
    boolean equals(str);
2.6 判断内容是否相同,并忽略大小写。
     boolean equalsIgnoreCase();


3.转换
3.1将字符数组转成字符串。
构造函数:String(char[])
String(char[],offest,cont);将字符数组中的一部分转成字符串。
静态方法:
        static String copyValueOf(char[]):
        static String copyValueOf(char[] data,int offest,int count)
        static String ValueOf(char[]):


3.2将字符串转成字符数组。**


  char[] toCharArray() 


3.3将字节数组转成字符串。
  String(byte[])
String(byte[],offest,cont);将字节数组中的一部转成字符串
3.4将字符串转成字节数组。
 byte[] getBytes();
3.5将基本数据类型转成字符串。
static String ValueOf(int)
static String ValueOf(double)
//3+"";//String.valueOf(3);


特殊:字符串和字节数组在转换过程中,是可以指定编码表的。


4.替换
  String replace(oldchar,newchar);
 5.切割
 String[] split(regex);
6子串,获取字符串中的一部分。
String substring(begin,end);
7.转换,去除空格,比较
7.1 将字符串转成大写或者小写。
    String toUpperCase();
String toLowerCase();
7.2将字符串两端的多个空格去除。
String trim();
7.3对两个字符串进行自然顺序的比较
 int compareTo(string);


StringBufer
字符串的组成原理就是通过该类实现的。
StringBuffer可以对字符串内容进行增删。
StringBuffer是个容器。
很多方法与string相同。
StringBuffer是字符串缓冲区。
是一个容器。
特点:
1.长度是可变化的
2.可以字节操作多个数据类型。
3.最终会通过tosString方法变成字符串。
C create  U update R read D delete
1.存储
StringBuffer   append():将指定数据作为参数添加到已有数据结尾处。
StringBuffer   insert(index,数据):可以将数插入指定index位置。
2.删除
StringBuffer delete(start,end):删除韩城去中的数据,包含start,不包含end.
StringBuffer  deletecharAt(index):删除指定位置的字符。
3.获取
char CharAt(int index);
int intdexOf(String str)
int lastindexOf(String str)
int length()
String substring(int start,int end)
4.修改
StringBuffer replace(start,end,string);
void setCharAt(int index,char ch);
5.反转
StringBuffer reverse();


6.
将缓冲区中指定数据存储到指定字符数组中。
void getChars(int srcBegin,int srcEnd,char[] dst,int dstBegin)


JDK1.5版本后出现了StringBuilder.
StringBuffer 是线程同步。
StringBuilder是线程不同步。
以后开发,建议使用StringBuilder
升级三个因素:
1.提供效率
2.简化书写
3.提高安全性。








进步数据类型对象包装类。
基本数据类型       引用数据类型
byte                   Byte
short                  Short
int                    Integer
long                   Long
    boolean                Boolean
float                  Float
double                 Double
char                   Character


基本数据类型对象包装类的最常见作用,就是用于基本数据类型和字符串类型之间做转换。
基本事件类型转成字符串:
基本数据类型+""
基本数据类型.toString(基本数据类型值);
如:Integer.toString(34);//将34变成"34";


字符串转成基本数据类型。
xxx a = Xxx.parseInt(String);
int a = Integer.parseInt("123");
double b = Double.parseDouble("12.23");
boolean b = Boolean.parseBoolean("true"); =
int num = i.intValue();


十进制转成其他进制。
toBinaryString();
toHexString();
toOctalString();


其他进制转成十进制。
parseInt(String,radix);


/*
JDK1.5版本以后出现的新特性。
*/
class IntegerDemo1 
{
public static void main(String[] args)
{
//Integer x = new Integer(4);
Integer x = 4;//自动装箱。//new Integer(4);
x=x/*x.intVaule()*/+2;//x=2:x 进行自动拆箱。变成int类型,和2进行加法运算。再将和进行装箱赋给x




Integer m = 128;
Integer n =  128;
sop("m==n:"+(m==n));
Integer a = 127;
Integer b = 127;
sop("a==b"+(a==b));//结果为true.因为a和b指向了同一个Integer对象。
        //因为当值在byte范围内容,对于新特性,如果该数值已经存在,则不会再开辟新的空间






                                                                   Java的集合类
为什么出现了集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
数组和集合同时容器,不何不同?
数组虽然也是存储对象,但长度是固定的;集合长度是可变的。
数组汇总可以存储基本数据类型,集合只能存储对象。
集合类的特点:集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象


集合框架:Collection


 |--------List元素是有序的,元素可以重复。因为该集合体系有索引。
        |-----ArrayList
             |-----LinkedList
             |-----Vector
      |----------Set元素是无序的,元素不可以重复。
         |----HashSet
     |----TreeSet
为什么会出现这么多的容器呢?
因为每一个容器对数据的存储方式不同。
这个存储方式称为:数据结构
1.add方法的参数类型是Object.以便于接收任意类型对象。
2.集合存储的都是对象的引用(地址)
3.retainAll是取交集用的;也可以认为是对集合的改变
4.removeAll删除相同的部分。
Iterator是迭代器接口
什么是迭代器呢?
其实就是集合的去除元素的方式。
就把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素。
那些取出方式就被定义成了内部类。
而且每个容器的数据结构不同,所以取出的多种细节也不一样。但是都有共性内容判断和取出。
那么可以将共性部分抽取。那么这些内类都符合一个规则。该规则是Iterator.
如何集合的去除对象呢?
通过一个对外提供的方法。iterator();
Collection
   |---List:元素是有序的,元素可以重复。因为该集合体系有索引。
       |----ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快,但是增删稍慢。线程不同步。数组是可变长度。
       |----LinkedList:底层使用的是链表数据结构。特点:增删速度很快,查询稍慢。
       |----Vector:底层是数组数据结构。线程时同步。被ArrayList替代。有枚举。


   |---Set :元素是无序的,运算不可以重复。


   List:
   特有方法。凡是可以操作角标的方法都是该体系特有的方法。
   增
add(index,element);在指定位置添加元素
addAll(index,collection);在指定位置添加一堆元素
   删
remove(index);删除指定位置的元素
   改
set(index,element);修改元素
   查
get(index);通过角标获取元素
subList(from,to);
listIterator();


List集合特有的迭代器。ListIterator是Iterator的子类接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。
因为会发生并发操作异常ConcurrentModificationException异常。
所有,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的。
值能对元素进行判断,取出,删除的操作。
如果想要其他的操作如添加,修改等,就需要使用其子类接口,ListIterator
该接口只能通过List集合的listIterator方法获取
枚举
枚举就是Vector特有的取出方式。发现枚举和迭代器很像。
其实枚举和迭代器是一样的。因为枚举的名称以及方法的名称都过长。
所以被迭代器取代了。枚举郁郁而终了。
LinkedList;链表数据结构。
Set:无序,不可以重复元素,
 |----HashSet:数据结构是哈希表。线程是非同步的。
            保证元素唯一性的原理:判断元素的hashCode值是否相同。
             如果相同,还会继续判断元素的equals方法。是否为true.
 |------TreeSet:可以对Set集合中的元素进行排序。
底层数据结构二叉树。
保证元素唯一性的依据。
compareTo方法的return 0;
TreeSet排序的第一种方式:
让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方法也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需的。这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较性。
定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
定义比较器:定义一个类,实现Comparator接口,覆盖compareTo方法。
泛型:
JDk1.5版本以后出现的新特性。用于解决安全问题。是一个类型安全机制。
泛型的好处:
1.将运行时期出现问题ClassCastException,转移到了编译时期。
方便于程序员解决问题。让运行时的问题减少,安全。
2.避免了强制转换的麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢?
同过集合框架中的很常见,只要见到<>就要定义泛型。
其实<>就是用来解释类型的。
当使用集合时,将集合中药存储的数据类型作为参数传递当<>中即可。
泛型类
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候。
早期定义Object来完成扩展。
现在定义泛型来完成扩展。
泛型类定义的泛型,在整个类中有效,如果累方法使用。
那么泛型类的对象明确要操作的具体类型后,所以要操作的类型就就已经固定有了。
为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。
特殊之处:
静态方法不可以访问类上定义的泛型。
如果静态方法操作的引用数据类型不确定。可以将泛型定义在方法上。
? 通配符。也可以理解为占位符。
泛型限定:
?extends E:可以接收E类型或者E的子类型。上限。
?super E : 可以接收E类型或者E的父类型。下限。
泛型限定用于泛型扩展用的。
Map集合;该集合存储键值对,一对一对往里存。而且要保证键的唯一性。
1.添加:(K key,V vaule) 添加键和值
put();添加元素
2.删除      void    clear()
 remove(Object key)根据键删除值。
3.判断
boolean containsValue(Object value) 判断值
boolean containsKey(Object Key)    判断键
boolean isEmpty()   如果次映射未包含键 值映射关系,则返回true.
4.获取。
get(Object Key)
             返回指定键所映射的值,如果此映射不包含该键的映射关系,则返回null.
int size() 返回此映射中的键-值关系,长度。
values() 获取值


entrySet()
keySet()
 
Map
|------Hashtable:底层是哈希表数据结构,不可以存入null键null值,该集合是线程同步的。jdk1.0效率低
|------HashMap:底层是哈希表数据结构,允许使用null值和null键,该集合不同步的。jdk1.2 效率高
|------TreeMap:底层是二叉树数据结构,线程不同步。可以用于给map集合中的键进行排序。


和Set很像。
其实大家,Set底层就是使用了Map集合。
map集合的两种取出方式。
1.Set keySet:将map中所有的键存入到Set集合。因为Set具备迭代器。
 所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值


Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
2.Set> entrySet:将map集合的映射关系存入到了set集合中,
而这个关系的数据类型就是Map.Entry.
将map集合中的映射关系取出。这个关系就是Map.Entry类型,
那么关系对象Map.Entry获取到后,就可以通过Map.Entry中的getKey和getValue方法获取关系中的键和值。
使用集合的技巧:?
看到Array就是数组结构,有角标,查询速度很快。?
看到link就是链表结构:
增删速度快,而且有特有方法。
addFirst;?addLast;?removeFirst();?removeLast();?getFirst();getLast();?
看到hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。?
看到tree就是二叉树,就要想到排序,就想要用到比较。?
比较的两种方式:?
一个是Comparable:覆盖compareTo方法;?
一个是Comparator:覆盖compare方法。
?LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
?集合什么时候用??
当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。?
保证唯一,就用Set。不保证唯一,就用List。?
Collections.sort(list);//list集合进行元素的自然顺序排序。?
Collections.sort(list,new?ComparatorByLen());///按指定的比较器方法排序。
int?index?=?Collections.binarySearch(list,"zz");//二分查找,返回角标。
Collections.reverseOrder();//逆向反转排序。?
Collections.shuffle(list);//随机对list中的元素进行位置的置换。
Collections.fill();全部替换元素
原理:定义一个类,将集合所有的方法加同一把锁后返回。?
Collection?和?Collections的区别:?
Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
?Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,
提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。
Arrays:用于操作数组的工具类。里面都是静态方法。
asList:将数组变成list集合。


把数组变成list集合有什么好处?
可以使用集合的思想和方法来操作数组中的元素。
注意:将数组变成集合,不可以使用集合的增删方法。
因为数组的长度是固定的。
contains
get
indexOf()
subList();
如果你增删。那么会发生UnsupportedOperationException.不支持的操作异常。
如果数组中的元素都是对象。那么变成集合时,数组中的元素就是直接转成集合中的元素。如果数组中的元素都是基本数据类型,
那么会将该数组作为集合中的元素存在。
1.指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于集合的size,那么该方法内部会创建一个新数组。长度为集合的size。当指定类型的数组长度大于了集合的size,
就不会新创建了数组,而是使用传递进来的数组。
所以创建一个刚刚还的数组最优。
2.为什么要将集合变数组?
为了限制对元素的操作。不需要进行增删了。
高级for循环
格式:
for(数据ForEachDemo类型 变量名:被遍历的集合(Collection)或者数组)
{


}
对集合进行遍历。
只能获取集合元素,但是不能对集合进行操作。


迭代器除了遍历,还可以进行remove集合中的元素的动作。如果是用ListIterator,还可以在遍历过程中对集合进行增删改查的动作。
传统for和高级for有什么区别呢?
高级for有一个局限性。必须被遍历的目标。建议在遍历数组的时候,还希望是用传统for,因为传统for可以定义角标。
Jdk1.5版本出现的新特性。
方法的可变参数一定要定义在参数列表的最后面。可变参数。其实就是上一种数组参数的简化形式。不用每一次都手动建立数组对象只要将要操作的元素作为参数传递即可。
隐式将这些参数封装成了数组。


  集合框架(常用对象API)
为什么出现集合类?
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象常用的一种方式。
数组和集合类同是容器,有和不同?
   数组虽然也可以存储对象,但是长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。










面向对象 




集合体系 




Collection(单列)






List(有序,可重复) 




ArrayList:  底层数据结构是数组,查询快,增删慢。线程不同步,效率高。   








LinkedList:底层数据结构是链表,查询慢,增删快。线程不同步,效率高。 








Vector:      底层数据结构是数组,查询快,增删慢。线程同步,效率低。 


Set(无序,唯一) 


HashSet:底层数据结构是哈希表。线程不同步,效率高。 怎么保证唯一性的呢?它依赖两个方法:hashCode()和equals()顺序:首先判断hashCode()值是否相同。同:继续走equals(),看返回值如果true:就不添加到集合。如果false:就添加到集合。不同:就添加到集合。 




TreeSet:底层数据结构是二叉树。 线程不同步,效率高。 怎么保证唯一性的呢?是根据返回是否是0。 


怎么保证排序的呢?两种方式  


一、自然排序(元素具备比较性) 实现Comparable接口  


二、比较器排序(集合具备比较性) 实现Comparator接口 




Map(双列 底层结构是针对键有效,跟值无关)






HashMap:底层数据结构是哈希表。线程不同步,效率高。 


怎么保证唯一性的呢? 


它依赖两个方法:hashCode()和equals()顺序:首先判断hashCode()值是否相同。同:继续走equals(),看返回值如果true:就不添加到集合。如果false:就添加到集合。不同:就添加到集合。 








Hashtable:底层数据结构是哈希表。线程安全,效率低。 


怎么保证唯一性的呢? 


它依赖两个方法:hashCode()和equals()顺序:首先判断hashCode()值是否相同。同:继续走equals(),看返回值如果true:就不添加到集合。如果false:就添加到集合。不同:就添加到集合。 








TreeMap:底层数据结构是二叉树。线程不同步,效率高。 


怎么保证唯一性的呢?是根据返回是否是0。 


怎么保证排序的呢?两种方式自然排序(元素具备比较性)实现Comparable接口比较器排序(集合具备比较性)实现Comparator接口 


集合常见应用功能 


(添加功能,判断功能,删除功能,获取功能,长度功能) 


Collection接口


布尔型  add(E e)  
布尔型  remove(Object o)  
布尔型  contains(Object o)  
迭代器  iterator()  
整数  size()   




|--List接口 
布尔型  add(E e)  




 E


 get(int index)  




无返回值  add(int index,E element)  


 E


 remove(int index)  




 E


 
set(int index, E element) 
            




|--Set接口 


布尔型  add(E e)   




添加时如果集合有相同元素,则存储失败。 


|--Map接口 


 V  
put(K key,V value)  




 V  
remove(Object key)  
布尔型  containsKey(Object key)  




布尔型  containsValue(Object value)  
整数  size()         




 V
 
get(Object key)   




Set  keySet()  


Collection  values()  








遍历方式


List Set迭代器 
Iterator 


ListIterator 


Map迭代器 


有俩种选择一种去用即可。 


(妻子找丈夫)键和值 


(结婚证找妻子丈夫)键和值映射关系 


Map的两种典型遍历方式:




entrySet() 与 keySet()。entrySet的遍历方式要比keySet()高许多,因为欲取得同样的key-value对,keySet()相当于遍历了两次Map。 






集合那么多什么时候该用谁?


是否键值对? 


是:Map 


是否对键排序? 


是:TreeMap 


否:HashMap 


不懂的情况下,使用HashMap。 


否:Collection 


是否唯一? 


是:Set 


是否对元素进行排序? 


是:TreeSet 


是否需要有序? 


是:LinkedSet 


否:HashSet 


不懂的情况下,使用HashSet 


否:List 


是否要安全? 


是:Vector(真正开发中也不用) 


否:ArrayList,LinkedList 


注意:查询多:ArrayList 


增删多:LinkedList 


不懂的情况下,使用ArrayList 




面向对象 


集合框架的工具类。 


Collections:集合框架的工具类。里面定义的都是静态方法。(相信Java的新手们都知道,如果一个类全都是静态方法的话,那么这个类肯定不能创建对象,也不需要给你提供对象的获取方法,因为静态都是优先于对象存在的) 


Collections和Collection有什么区别?




Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。 


它有两个常用的子接口, 


List:对元素都有定义索引。有序的。可以重复元素。 


Set:不可以重复元素。无序。 








Collections是集合框架中的一个工具类。该类中的方法都是静态的。
提供的方法中有可以对List集合进行排序,二分查找等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。




Collections:静态方法


static
void  
 sort(List list)
          根据元素的自然顺序 对指定列表按升序进行排序。  








 /* 


一个学校,每个学校都有学科,班级的名字就是对应的学科。 


对每门学科进行自然排序。 


*/ 


import java.util.List; 


import java.util.ArrayList; 


import java.util.Collections; 


import java.util.Iterator; 


public class Test{ 




public static void main(String[] args){ 




List list =new ArrayList(); 


list.add("黑马程序员"); 


list.add("黑马程序员——云计算"); 


list.add("黑马程序员——android"); 


list.add("黑马程序员——.Net"); 


list.add("黑马程序员——iso"); 


for(Iterator it = list.iterator();it.hasNext();){




sop(it.next()); 





Collections.sort(list); 


for(Iterator iter = list.iterator();iter.hasNext();){




sop(iter.next()); 












public static void sop(Object obj){ 




System.out.println(obj); 












Collections:静态方法 


static int  
 binarySearch(List> list, T key)
          使用二分搜索法搜索指定列表,以获得指定对象。  
static int  
 binarySearch(List list, T key,Comparator c)
          使用二分搜索法搜索指定列表,以获得指定对象。  


一个是按照Java指定的比较器进来二分查找,一个是自己指定比较器对集合进行二分查找。 


这种思想跟我们之前学数组的时候是一样的,二分查找,所以了解了数组的二分查找,再去看看Java的Src源代码,就基本了解了二分查找的算法,建议使用Java默认的二分查找,因为我们写的不一定比它的效率高。 


Collections:静态方法 (排序)(自动反转比较器)(自定义反转比较器) 


static void  
 sort(List list,Comparator c)
          根据指定比较器产生的顺序对指定列表进行排序。  






static void  
 sort(List list,Comparator c)
          根据指定比较器产生的顺序对指定列表进行排序。  
static Comparator  
 reverseOrder()
          返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。  
static Comparator  
 reverseOrder(Comparator cmp)
          返回一个比较器,它强行逆转指定比较器的顺序。  






 /* 


一个学校,每个学校都有学科,班级的名字就是对应的学科。 


对每门学科进行长度排序。从短到长,从长到短。 


这时候就可以使用Collections里面的sort方法,并指定比较器进去。 


也可以在构造器里面直接比较器进行反转。 


*/ 


import java.util.List; 


import java.util.ArrayList; 


import java.util.Collections; 


import java.util.Iterator; 


import java.util.Comparator; 


public class Test{






public static void main(String[] args){ 




List list = new ArrayList(); 


list.add("黑马程序员"); 


list.add("黑马程序员——云计算"); 


list.add("黑马程序员——android"); 


list.add("黑马程序员——.Net"); 


list.add("黑马程序员——iso"); 


sop("原集合"); 


for(Iterator it = list.iterator();it.hasNext();){




sop(it.next()); 





sop("排序后的集合"); 


Collections.sort(list,new Comparator(){ 


public int compare(Object obj1,Object obj2){ 


String s1 =  (String)obj1; 


String s2 =  (String)obj2; 


int len = s1.length()-s2.length(); 


if(len==0) 


return s1.compareTo(s2); 


return len; 





}); 


for(Iterator iter = list.iterator();iter.hasNext();){




sop(iter.next()); 





sop("排序后再逆转的集合"); 
Collections.sort(list,Collections.reverseOrder(new Comparator(){ 


public int compare(Object obj1,Object obj2){ 


String s1 =  (String)obj1; 


String s2 =  (String)obj2; 


int len = s1.length()-s2.length(); 


if(len==0) 


return s1.compareTo(s2); 


return len; 





})); 


for(Iterator iter = list.iterator();iter.hasNext();){




sop(iter.next()); 












public static void sop(Object obj){ 




System.out.println(obj); 












Collections:静态方法


static void  swap(List list, int i, int j)
          在指定列表的指定位置处交换元素。  




/* 


对List集合的俩个元素进行互换。 


并获取集合中元素的最值。 


*/ 


import java.util.List; 


import java.util.ArrayList; 


import java.util.Collections; 


public class Test{ 


public static void main(String[] args){ 


Listlist = new ArrayList(); 


list.add(7); 


list.add(1); 


list.add(8); 


list.add(5); 


//打印原集合。 


sop(list); 


Collections.swap(list,list.indexOf(5),list.indexOf(7)); 


//打印新集合。 


sop(list); 


sop("最大值:"+Collections.max(list)); 


sop("最小值:"+Collections.min(list)); 





public static void sop(Object obj){ 


System.out.println(obj); 








Collections:静态方法


static void  
 fill(List list, T obj)
          使用指定元素替换指定列表中的所有元素。  








static void  reverse(List list)
          反转指定列表中元素的顺序。  
static boolean  
 replaceAll(List list, T oldVal, T newVal)
          使用另一个值替换列表中出现的所有某一指定值。  




static void  shuffle(List list) 
          使用默认随机源对指定列表进行置换。  
static void  shuffle(List list, Random rnd) 
          使用指定的随机源对指定列表进行置换。  
















注意:此方法是替换集合所有元素的值。 


import java.util.List; 


import java.util.ArrayList; 


import java.util.Collections; 


public class Test{ 


public static void main(String[] args){ 


Listlist = new ArrayList(); 


list.add(7); 


list.add(1); 


list.add(8); 


list.add(5); 


sop("原集合:"+list);




Collections.shuffle(list); 


sop("随机集合:"+list); 




Collections.reverse(list); 


sop("反转后的集合"+list); 




Collections.replaceAll(list,1,2); 


//打印出现值被替换后的集合




sop("替换出现值的集合:"+list); 




Collections.fill(list,0); 


//打印新集合。 


sop("统一集合值的集合:"+list); 





public static void sop(Object obj){ 


System.out.println(obj); 














同步集合:貌似同步Set集合和同步Map还可以对集合进行有序的排序。 


static Collection  
 synchronizedCollection(Collection c)
          返回指定 collection 支持的同步(线程安全的)collection。  
static List  
 synchronizedList(List list)
          返回指定列表支持的同步(线程安全的)列表。  
static Map  
 synchronizedMap(Map m)
          返回由指定映射支持的同步(线程安全的)映射。  
static Set  
 synchronizedSet(Set s)
          返回指定 set 支持的同步(线程安全的)set。  
static SortedMap  
 synchronizedSortedMap(SortedMap m)
          返回指定有序映射支持的同步(线程安全的)有序映射。  
static SortedSet  
 synchronizedSortedSet(SortedSet s)
          返回指定有序 set 支持的同步(线程安全的)有序 set。  




Arrays:用于操作数组的工具类,里面都是静态方法。 


static List  
 asList(T... a)
          返回一个受指定数组支持的固定大小的列表。  
static int  binarySearch(byte[] a, byte key)
          使用二分搜索法来搜索指定的 byte 型数组,以获得指定的值。  
static boolean[]  copyOf(boolean[] original, int newLength)
          复制指定的数组,截取或用 false 填充(如有必要),以使副本具有指定的长度。  
static boolean[]  copyOfRange(boolean[] original, int from, int to)
          将指定数组的指定范围复制到一个新数组。  
static void  sort(byte[] a)
          对指定的 byte 型数组按数字升序进行排序。  
static String  toString(boolean[] a)
          返回指定数组内容的字符串表示形式。  




数组变成集合(Arrays)




import java.util.Arrays; 


import java.util.List; 


public class Test{ 


public static void main(String[] args){ 


String str [] = {"黑马程序员","CSDN","黑马论坛"}; 


Listlist =Arrays.asList(str); 


sop(list); 


//list.add("新长城");会发生异常。 


int arr[] = {1,2,3,4}; 


List list =Arrays.asList(arr); 


sop(list);//打印的是哈希值,因为集合把数组中基本数据类型的元素都是当成一个数组存在。 





public static void sop(Object obj){ 


System.out.println(obj); 










将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定的,如果你增删了,会发生不支持操作异常。 


如果数组中的元素,都是都像,变成集合时,数组中的元素就直接转换成集合中的元素
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。 






集合变成数组 


当我们不希望调用者对我们的集合进行操作时,这时候就要把集合变成数组,让操作者不能对其进行基本的操作,但是数组的功能还是可以使用的,比如获取。 


 Object[]  toArray()
          返回包含此 collection 中所有元素的数组。  
T[]  
 toArray(T[] a)
          返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。  




import java.util.List; 


import java.util.ArrayList; 


public class Test{ 


public static void main(String[] args){ 


Listlist =new ArrayList(); 


list.add("黑马程序员"); 


list.add("CSDN"); 


list.add("黑马论坛"); 


Object[] arr = list.toArray(); 


for(int x=0;x

System.out.print(arr[x]); 











指定类型的数组到底要定义多长呢? 


当指定类型的数组长度小于了集合的size,那么该方法内部都会创建一个新的数组,长度为集合的size 


当指定类型的数组长度大于了集合的size,就不会新创建数组,而是使用传递进来的数组, 


所以应该创建一个刚刚好的。 


 String[] arr = list.toArray(new String[al.size()]); 


为什么要将集合变数组? 
为了限定对元素的操作。不需要进行增删。 
集合(增强for循环)




1.5JDK的新特性 




高级 for 循环(简化书写)
格式:
for(数据类型 变量名 : 被变量的集合(Collection)或者数组){ 







对集合进行遍历,只能获取集合元素,但是不能对集合进行操作。 


迭代器出了遍历,还可以进行remove集合中元素的动作。




如若果使用ListIterator,还可以在遍历过程中对集合进行增删改查动作。




传统for和高级for有什么区别呢?


高级for有一个局限性,必须有便利的目标 
建议在遍历数组的时候,还是希望使用传统for,因为传统for可以定义脚标。 


import java.util.List; 


import java.util.ArrayList; 


import java.util.HashMap; 


import java.util.Map; 


import java.util.Set; 


public class Test{ 


public static void main(String[] args){ 


Listlist = new ArrayList(); 


list.add("黑马程序员"); 


list.add("CSDN"); 


list.add("黑马论坛"); 


sop("高级for循环遍历list"); 


for(String s:list){ 


sop(s); 





Mapmap = new HashMap(); 


map.put(1,"黑马程序员——张三"); 


map.put(2,"黑马程序员——李四");




map.put(3,"黑马程序员——王五");




map.put(4,"黑马程序员——赵六"); 


SetkeySet = map.keySet(); 
sop("高级for循环遍历第一种获取方式map获取键,用键获取map值"); 


for(Integer i :keySet){ 


sop(i+","+map.get(i)); 





Set>entrySet = map.entrySet(); 


sop("高级for循环遍历第二种获取方式map的键和值");




for(Map.Entry me : entrySet){ 


sop(me.getKey()+","+me.getValue()); 








public static void sop(Object obj){ 


System.out.println(obj); 








集合(可变参数) 


JDK 1.5 版本出现的新特性
方法的可变参数(简化书写)
注意:可变参数一定要定义在函数参数的末尾,另外是三个点不是二个。




比如要调用一个函数,传入的参数格式类型,一样,但是个数不一样,普通方式是重载,很麻烦。




所以应该传入一个数组,但是自己定义一个数组也麻烦,所以Java有了这种函数参数定义方法接收。




public class Test{ 


public static void main(String... args){ 


int sum = method(1,2,3,4,5); 


int num = method(1,2,3,4,5,6,7,8,9,10); 


System.out.println(sum); 


System.out.println(num);







public static int method(int ...arr){ 


int sum =0; 


for(int i : arr) 


sum+=i; 


return sum; 






可变数组,其实就是上一种数组参数的简写形式。 


不用每一次都手动的建立数组对象,只要将操作的元素作为参数传递即可, 


隐式将这些参数封装成数组,可以传入空参数,0长度数组。 


集合(静态导入) 


JDK 1.5 版本出现的新特性
StaticImport  集合(静态导入) (简化书写) 


当类名重名时,需要指定具体的包名。
当方法重名是,指定具备所属的对象或者类。




import static java.util.Arrays.*;//导入Arrays类中的所有静态成员。 


public class Test{ 


public static void main(String... args){ 


int []arr = {1,7,3,5,2}; 


for(int i:arr){ 


System.out.print(i); 





System.out.println(); 


sort(arr);//由于该方法是静态的,而Arrays里面的静态成员全部导入进来了,就可以省略类名.调用。 


for(int i:arr){ 


System.out.print(i); 











面向对象 


System类 


其他对象(System):类中的方法和属性都是静态的。




1、in:标准输入。默认是键盘。 


2、out:标准输出。默认是控制台。 


描述系统属性信息。




 获取系统属性信息: 


静态方法: 


Properties  getProperties()
          确定当前的系统属性。  






import java.util.Properties;
import java.util.Map;
import java.util.Set;
public class Test{ 






public static void main(String...agrs){ 






Properties p = System.getProperties(); 






/*因为Properties是Hashtable的子类,也就是Map集合的一个类的对象。 






那么可以通过Map的方法获取出该集合中的元素。 


该集合中存储都是字符串,没有泛型定义








*/ 


Set> entrySet = p.entrySet(); 


for(Map.Entry me:entrySet){ 






sop(me.getKey()+"::"+me.getValue()); 



















/*如何在系统中自定义一些特有信息呢?*/




System.setProperty("黑马程序员","Xcc"); 


p.setProperty("黑马程序员","新长城"); 






//如果设置的键相同,那么后面的新值会替换前面原有的值。 








//可不可以在jvm启动时,动态加载一些属性信息呢 
//命令行   java -D键=值 类 
//获取指定属性信息 


String value =System.getProperty("黑马程序员"); 


System.out.println("value="+value); 





public static void sop(Object obj){ 






System.out.println(obj); 














Runtime类 


其他对象(Runtime) 


Runtime对象 


该类并没有提供构造函数, 


说明不可以new对象。那么会直接想发到该类中的方法都是静态的 


但是,该类中还有非静态方法。 


说明该类肯定会提供了方法获取本类的对象。而且该方法是静态的,并且返回类型是本类类型。 


获取本类对象静态方法: 


Runtime  getRuntime()
          返回与当前 Java 应用程序相关的运行时对象。  




public class Test{ 


public static void main(String...args) throws Exception{ 


Runtime r = Runtime.getRuntime(); 


Process p1 = r.exec("E:\\Program Files\\KuGou2012\\KuGou.exe"); 


Thread.sleep(4000); 


p1.destroy(); 


Process p2 = r.exec("notepad.exe G:\\1.txt"); 


Thread.sleep(4000); 


p2.destroy(); 








Date类


其他对象(Date)日期类 


import java.util.Date; 


import java.text.SimpleDateFormat;




public class Test{ 


public static void main(String...args) { 


Date d =newDate(); 


//sop(d);//打印时间看不懂,希望有些格式,而Date方法都已经过时。 


 //将模式封装到 SimpleDateFormate对象中




SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh:mm:ss");




 //调用 format方法让模式格式化指定的date对象




String time = sdf.format(d); 


sop(time); 





public static void sop(Objectobj){ 


System.out.println(obj); 








Calendar类


其他对象(Calendar) 


import java.util.Calendar; 


public class Test{ 
public static void main(String... args) { 
Calendar c =Calendar.getInstance(); 
c.set(2014,2,24);  //指定时间 记住时间是从0开始算的 除年份外 
//c.add(Calendar.MONTH,4);//增加时间 
c.add(Calendar.MONTH,-1); 


String[] months = {"一","二","三","四","五","六","七","八","九","十","十一","十二"}; 
String[] weeks = {"日","一","二","三","四","五","六"}; 
sop(c.get(Calendar.YEAR)+"年"+months[c.get(Calendar.MONTH)]+"月"+ 


c.get(Calendar.DAY_OF_MONTH)+"日 星期"+weeks[c.get(Calendar.DAY_OF_WEEK)-1]); 



public static void sop(Object obj){ 
System.out.println(obj); 




Math类 


其他对象(Math-Random) 


import static java.lang.Math.*; 


importjava.util.Random; 


public class Test{ 


public static void main(String args[]) { 




Double d1 =  ceil(2.5);//最小值
sop(d1);
Double d2 = floor(2.5);//最大值
sop(d2);
Double d3 = pow(2,3);//2的3次幂
sop(d3);
Long l = round(5.4);//四舍五入


sop(l); 


for(intx=1;x<=10;x++){ 


sop((int)(Math.random()*9+1));//生成随机数,1~9之间 


sop(new Random().nextInt(9)+1);//生成随机数,1~10之间 








public static void sop(Object obj){ 


System.out.println(obj); 










面向对象 


1、IO流用来处理设备之间的数据传输。 


2、Java对数据的操作是通过流的方式。 


3、Java用于操作流的对象都封装在IO包中。 


4、流按操作数据分为两种:字节流与字符流。 


5、流按流向分为:输入流,输出流。




IO 


字符流的抽象基类 


 Reader,Writer 


字节流的抽象基类 


 InputStrea,OutputStream 


注意:由这四个类派生出来的子类名称都是以其父类名作为子类明的后缀。 


既然IO流是用于操作数据的, 
那么数据的最常见体现形式是:文件。 
那么先以操作文件为主来演示。 


IO流(文本写入) 


writer抽象类 
abstract  void  close()
          关闭此流,但要先刷新它。  
abstract  void  flush()
          刷新该流的缓冲。  
 void  write(char[] cbuf)
          写入字符数组。  
abstract  void  write(char[] cbuf, int off, int len)
          写入字符数组的某一部分。  
 void  write(int c)
          写入单个字符。  
 void  write(String str)
          写入字符串。  
 void  write(String str, int off, int len)
          写入字符串的某一部分。  




FileWriter类 


构造方法摘要  






FileWriter(String fileName)
          根据给定的文件名构造一个 FileWriter 对象。  






/*




需求:在硬盘上,创建一个文件并写入一些文字数据。 


找到一个专门用于操作文件的Writer子类对象。FileWriter。  后缀名是父类名。 前缀名是该流对象的功能。 


*/ 




import java.io.Writer; 


import java.io.FileWriter; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args)throws IOException{ 


/*创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件. 


而且该文件会被创建到指定目录下,如果该目录下已有同名的文件,将被覆盖。 


其实该步就是明确数据要存放的目的地*/ 


Writer w = new FileWriter("1.Java"); 


/*调用writer方法,将字符串写入到流中,会抛IO异常.*/




w.write("黑马程序员——新长城"); 


/*刷新该流的缓冲。将数据刷新到文件中*/




//w.flush(); 


/*关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。   


将数据刷到目的地中。  
和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。*/  


w.close(); 








IO流(IO异常处理方式) 


import java.io.Writer; 


import java.io.FileWriter; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args){ 


Writer w = null; 


try{ 


w =new FileWriter("1.Java"); 


w.write("黑马程序员——新长城");







catch(IOException e){ 


System.out.println("写入失败"+e); 





finally{ 


if(w!=null){ 


w.close(); 


















文件的续写 


FileWriter类 


构造方法摘要  




FileWriter(String fileName, boolean append)
          根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。  


/* 


Windows中,换行是 \r\n。 


Linux 是\n。 


*/ 


import java.io.Writer; 


import java.io.FileWriter; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args){ 


Writer w = null; 


try{ 


//为true表示不覆盖已有文件,并且续写




w = new FileWriter("1.Java",true); 


w.write("黑马程序员——新长城");




fw.write("\r\n换行");







catch(IOException e){ 


System.out.println(e); 





finally{ 


if(w!=null){ 


try{ 


w.close(); 





catch(IOException e){ 


System.out.println(e); 

















IO流(文本文件读取方式一) 


Reader抽象类 


 int  read()
          读取单个字符。  




abstract  void  close()
          关闭该流并释放与之关联的所有资源。  




构造方法摘要  




FileReader(String fileName)
          在给定从中读取数据的文件名的情况下创建一个新 FileReader。  










import java.io.Reader; 


import java.io.FileReader; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args) throws IOException{ 


/* 


创建一个文件读取流对象,和指定名称的文件相关联。 


要保证该文件是已经存在的,如果不存在,会发生异常 FileNotFoundException




*/




Reader r = new FileReader("C:\\1.Java"); 


int ch =0; 


while((ch=r.read())!=-1){ 


System.out.print((char)ch); 











IO流(文本文件读取方式二) 


Reader抽象类 


 int  read(char[] cbuf)
          将字符读入数组。  




import java.io.Reader; 


import java.io.FileReader; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args) throws IOException{ 


Reader r = new FileReader("C:\\1.Java"); 


char[]buf = new char[1024]; 


int len =0; 


while((len=r.read(buf))!=-1){ 


sop(new String(buf,0,len)); 








public static void sop(Object obj){ 


System.out.println(obj); 








IO流(文本文件读取练习) 


import java.io.Reader; 


import java.io.FileReader; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args) throws IOException{ 


Reader r = new FileReader("1.Java"); 


char []buf = new char[1024];




for(int len =0;(len=r.read(buf))!=-1;){ 


sop(new String(buf,0,len)); 








public static void sop(Object obj){ 


System.out.println(obj); 








IO流(文本文件写入练习)




import java.io.Writer; 




import java.io.FileWriter; 


import java.io.IOException; 


public class Test{


public static void main(String...args) throws IOException{ 


Writer r = new FileWriter("1.Java"); 


for(int x=1;x<=5;x++){ 


r.write("CSDN社区"+x+"\r\n"); 


r.flush(); 





r.close(); 








IO流(拷贝文本文件) 


复制的原理,其实就是将一个文件的数据存储到另一个文件中 


/* 


1、在C盘创建一个文件,用于存储C盘文件中的数据 


2、定义读取流和C盘文件关联 


3、通过不断的读写完成数据存储 


4、关闭资源 


*/ 


import java.io.IOException; 


import java.io.Writer; 


import java.io.Reader; 


import java.io.FileWriter; 


import java.io.FileReader; 


public class Test{ 


public static void main(String... args){ 


Reader r =null; 


Writer w =null; 


try{ 


r  = new FileReader("C:\\1.Java"); 


w =new FileWriter("C:\\2.Java"); 


char[] buf =new char[1024]; 


for(int len=0;(len=r.read(buf))!=-1;){ 




w.write(new String(buf,0,len)); 








catch(IOException e){ 


System.out.println(e); 





finally{ 








try{ 


if(r!=null) 


r.close(); 



catch(IOException e){ 


System.out.println(e); 





finally{ 


try{ 


if(w!=null) 


w.close(); 





catch(IOException e){ 


System.out.println(e); 

















面向对象 


字符流的缓冲区




1、缓冲区的出现提高了对数据的读写效率。 


2、对应类。 


(1)、BufferedWriter 


(2)、BufferedReader 


3、缓冲区要结合流才可以使用。


4、在流的基础上对流的功能进行了增强。 


BufferWriter 


 void  newLine()
          写入一个行分隔符。  






/* 


缓冲区的出现是为了提高流的操作效率而出现的 


所以在创建缓冲区之前,必须要先有流对象。 
*/ 


import java.io.IOException; 


import java.io.Writer; 


import java.io.FileWriter; 


import java.io.BufferedWriter; 


public class Test{ 


public static void main(String...args) throws IOException{ 


Writer w = new FileWriter("C:\\1.Java"); 


/* 


为了提高字符写入流的效率,加入了缓冲技术,只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可




*/ 


BufferedWriter bw = new BufferedWriter(w); 


bw.write("黑马程序员"); 


/* 


当然如果要刷新的话,当然是要刷新缓存区的flush, 


因为数据写到缓冲区里面去了。 


如果刷新流对象是刷不出来东西的。关闭也一样 


*/ 


bw.newLine(); 


bw.write("我来了"); 


bw.flush(); 




//bw.close(); 




/*其实这个流可以不用关闭也行。因为缓存区必须有流,而流对象关闭了。 




缓存区对象也就自动释放了*/ 


w.close(); 








IO流(BufferedReader) 


BufferedReader 


 String  readLine()
          读取一个文本行。  






readLine() 读取一个文本行。返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null ,所有要手动写入换行. 
 /*
字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine ,方便于对文本数据的获取
当返回 null 时,表示读到文件的末尾
readLine() 方法返回的时候只返回回车符之前的数据内容,并不返回回车符
*/




import java.io.Reader; 


import java.io.FileReader; 


import java.io.IOException; 


import java.io.BufferedReader; 


public class Test{ 


public static void main(String...args) throws IOException{ 


Reader r = new FileReader("C:\\1.Java"); 


/* 


为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数




*/ 


BufferedReader br =  new BufferedReader(r); 


for(String line = null;(line=br.readLine())!=null;){ 


System.out.print(line); 


System.out.println(); 











IO流(通过缓冲区复制文本文件)


/* 
通过缓冲区复制一个 .Java 文件 
*/ 


import java.io.IOException; 


import java.io.BufferedWriter; 


import java.io.BufferedReader; 


import java.io.FileReader; 


import java.io.FileWriter; 


public class Test{ 


public static void main(String...args){ 


BufferedReader br = null; 


BufferedWriter bw = null;




try{ 


br =new BufferedReader(new FileReader("C:\\1.Java")); 


 bw = new BufferedWriter(new FileWriter("C:\\2.Java")); 


for(String line = null;(line=br.readLine())!=null;){ 


bw.write(line); 


bw.newLine(); 


bw.flush(); 








catch(IOException e){ 


throw new RuntimeException("读写失败"); 





finally{ 


try{ 


if(br!=null) 


br.close(); 





catch(IOException e){ 


throw new RuntimeException("读取关闭失败"); 







try{ 


if(bw!=null) 


bw.close(); 



catch(IOException e){ 


throw new RuntimeException("写入关闭失败"); 
















IO流(readLine的原理)


不论是读一行,获取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是 read() 方法一次读一个的方法。 
因为跨平台性,换行符不一样,所以读取的时候缓存中不存入换行,让使用者自己输入换行。 


IO流(MyBufferedReader)




明白了BufferedReader 类中特有方法 readLine 的原理后, 


可以自定义一个类中包含一个功能和readLine一致的方法 


来模拟一下BufferedReader的readLine方法。 


import java.io.IOException; 
import java.io.BufferedWriter; 
import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.FileWriter; 
import java.io.Reader; 
public class Test{ 


public static void main(String... args) throws IOException{ 


Reader r = new FileReader("C:\\1.Java"); 


MyBufferedReader br = new MyBufferedReader(r); 


for(String line =null;(line=br.myReadLine())!=null;){ 


System.out.print(line); 


System.out.println(); 











class MyBufferedReader{ 


private Reader r; 


MyBufferedReader(Reader r){ 


this.r=r; 





public String myReadLine() throws IOException{ 


/* 


定义一个临时容器,原BufferedReader封装的是字符数组




为了方便,定义一个StringBuilder容器,因为最终还是要将数据变成字符串




*/ 


StringBuilder sb = new StringBuilder (); 


int len = 0; 


while((len = r.read())!=-1){ 


if(len=='\r') 


continue; 


if(len=='\n') 


return sb.toString(); 


else 


sb.append((char)len); 





//防止最后一行没有换行的情况




if(sb.length()!=0) 


return sb.toString(); 


else 


return null; 





public void myClose() throws IOException{ 


r.close(); 








IO流(装饰设计模式) 


1、当想要对已有对象进行功能增强时,可以定义一个类,将已有对象传入,基于已有的功能,并提供加强功能,那么该自定义类称为装饰类。
2、装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的功能,提供更强的功能。




(可以理解为打扮,比如自己如果要去面试的化,咱们要把自己打扮一下,把自己搞上点新鲜的衣服,但是最后还是一个人,只是身上多个点东西,这就是装饰) 


IO流(装饰和继承的区别) 
以前是通过继承将每一个子类都具备父类的功能。 


那么继承体系会复杂,并不利于扩展。 


现在优化思想。单独描述一下装饰类的内容。 


将需要被装饰的对象。传递进来。也就是,谁需要被装饰,谁就作为参数传递给装饰类。 


这样继承体系就变得很简单。优化了体系结构。 










装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。 


装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。 






IO流(自定义装饰类) 


abstract class Person{ 


public abstract  void  chifan();  





class Qiongren extends Person{ 


public void chifan(){ 


System.out.println("吃饭"); 








class Furen extends Person{ 


private Person p; 


Furen(Person p){ 


this.p=p; 





public void chifan(){ 


System.out.println("开胃酒"); 


p.chifan(); 


System.out.println("甜点"); 


System.out.println("来一根,当然我不好这口"); 








public class Test{ 


public static void main(String...args){ 


Qiongren q =new Qiongren(); 


Furen f =new Furen(q); 


f.chifan(); 








IO流(LineNumberReader) 


LineNumberReader 


 int  getLineNumber()
          获得当前行号。  




 void  setLineNumber(int lineNumber)
          设置当前行号。  




import java.io.BufferedReader; 


import java.io.FileReader; 


import java.io.LineNumberReader; 


import java.io.IOException; 


public class Test{ 


public static void main(String... args) throws IOException{ 


BufferedReader br = new BufferedReader(new FileReader("C:\\1.Java")); 


LineNumberReader lnr = new  LineNumberReader(br); 


lnr.setLineNumber(100); 


for(String line =null;(line=lnr.readLine())!=null;){ 


System.out.println(lnr.getLineNumber()+":"+line); 





lnr.close(); 








IO流(MyLineNumberReader) 


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;




class MyLineNumberReader{ 


private BufferedReaderbr; 


private int LineNumber; 


MyLineNumberReader(BufferedReader br){ 


this.br=br; 





public void setLineNumber(int LineNumber){ 


this.LineNumber =  LineNumber; 





public int getLineNumber(){ 


return++LineNumber; 





public String readLine()throwsIOException{ 


return br.readLine(); 





public void myClose() throws IOException{ 


br.close(); 








public class Test{ 


public static void main(String...args) throws IOException{ 


BufferedReader bfr = new BufferedReader(new FileReader("C:\\1.Java")); 


MyLineNumberReader my = new MyLineNumberReader(bfr); 


my.setLineNumber(100); 


for(String line = null;(line=my.readLine())!=null;){ 


System.out.println(my.getLineNumber()+":"+line); 





my.myClose(); 








相信大家看我的博客的时候看的很累,让我们为了我们共同的梦想努力吧。我相信只要我们坚持就会成功的。 
面向对象 


字节流基类  


InputStream 


OutputStream 


/* 


写入文件 


*/ 


import java.io.OutputStream; 


import java.io.FileOutputStream; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args)throwsIOException{ 


OutputStream os = new FileOutputStream("C:\\1.Java"); 


os.write("黑马程序员".getBytes()); 


os.close(); 














/* 


第一种读取文件的方法。 


对于操作文本文件不支持使用此做法。 


*/ 


import java.io.InputStream; 


import java.io.FileInputStream; 


import java.io.IOException; 


public classTest{ 


public static void main(String...args) throws IOException{ 


InputStream is =newFileInputStream("C:\\1.jpg"); 


for(int by = 0;(by=is.read())!=-1;){ 


System.out.print(by); 





is.close(); 










/* 


第二种读取文件的方法。


对于操作文本文件支持使用此做法。 


*/ 


import java.io.InputStream; 


import java.io.FileInputStream; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args) throws IOException{ 


InputStream is = new FileInputStream("C:\\1.Java"); 


byte []buf = new byte[1024]; 


for(int len = 0;(len=is.read(buf))!=-1;){ 


System.out.print(new String(buf,0,len)); 





is.close(); 








InputStream 


 int  available()
          返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。  










/* 


第三种方式,如果内存太大会报错。 


*/ 




import java.io.InputStream; 


import java.io.FileInputStream; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args) throws IOException{ 
InputStream is =new FileInputStream("C:\\1.Java"); 


byte[] buf =new byte[is.available()]; 


is.read(buf); 


System.out.println(new String(buf)); 


is.close(); 














IO流(拷贝图片)




/* 


思路:
1、用字节读取流对象和图片关联
2、用字节写入流对象创建一个图片文件。用于存储获取到的图片数据
3、通过循环读写,完成数据的存储
4、关闭资源




*/ 


import java.io.InputStream; 


import java.io.FileInputStream; 


import java.io.OutputStream; 


import java.io.FileOutputStream; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args){ 


InputStream is =null; 


OutputStream os =null; 


try{ 


is =newFileInputStream("C:\\1.jpg"); 


os =newFileOutputStream("D:\\1.jpg"); 


byte []buf =new byte[1024]; 


for(int len=0;(len=is.read(buf))!=-1;){ 


os.write(buf,0,len); 








catch(IOException e){ 


System.out.println("读写错误"); 





finally{ 


try{ 


if(is!=null) 


is.close(); 





catch(IOException e){ 


System.out.println("读取流关闭失败"); 





finally{ 


try{ 


if(os!=null) 


os.close(); 





catch(IOException e){ 


System.out.println("写入流关闭失败"); 

















面向对象 


字节流缓冲区 


BufferedInputStream 


BufferedOutputStream 


import java.io.BufferedInputStream; 


import java.io.BufferedOutputStream; 


import java.io.FileInputStream; 


import java.io.FileOutputStream; 


public class Test{ 


public static void main(String...args)throws IOException{ 


BufferedInputStream is = new BufferedInputStream 


 (new FileInputStream("C:\\1.mp3")); 


BufferedOutputStream os = new BufferedOutputStream 


(new FileOutputStream("D:\\1.mp3")); 


for(int by = 0;(by=is.read())!=-1;){ 


os.write(by); 





is.close(); 


os.close(); 








IO流(自定义字节流的缓冲区-read和write的特点)




import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;




class MyBufferedInputStream{




private InputStream in; 


private byte[] buf =new byte[1024]; 


private int pos; 


private int count; 


MyBufferedInputStream(InputStream in){ 


this.in=in; 





public int myRead()throws IOException{ 


if(count==0){ 


count=in.read(buf); 


if(count<0) 


return -1; 


pos=0; 


byte b = buf[pos]; 


pos++; 


count--; 


return b&255; 





else if(count>0){ 


byte b = buf[pos]; 


pos++; 


count--; 


return b&0xff; 





return -1; 





public void myClose()throws IOException{ 


in.close(); 





}






public class Test{




public static void main(String...args) throws IOException{ 


long start = System.currentTimeMillis(); 


copy(); 


long end = System.currentTimeMillis(); 


System.out.println(end-start); 





public static void copy()throws IOException{ 


MyBufferedInputStream bufis = new MyBufferedInputStream  


(new FileInputStream("C:\\1.avi")); 


BufferedOutputStream bufos = new BufferedOutputStream 


(new FileOutputStream("C:\\2.avi")); 


for(int len=0;(len=bufis.myRead())!=-1;){ 


bufos.write(len); 





bufis.myClose(); 


bufos.close(); 








IO流(读取键盘录入) 


System.out:对应的是标准输出设备:控制台 
System.in:对应的是标准输入设备 :键盘 


/*
需求,通过键盘录入数据。
当录入一行数据后,就将改行数据进行打印,如果录入数据是over,那么停止录入
*/ 


import java.io.IOException; 


import java.io.InputStream; 


public class Test{ 


public static void main(String...agrs)throws IOException{ 


InputStream in =System.in; 


StringBuilder sb = new StringBuilder(); 


while(true){ 


int ch =in.read(); 


if(ch=='\r') 


continue; 


if(ch=='\n'){ 


String s=sb.toString(); 


if("over".equals(s)) 


break; 


System.out.println(s); 



else{ 
sb.append((char)ch); 






面向对象 


IO流(读取转换流)




通过键盘录入一行数据,并打印其大写,发现其实就是读一行数据的原理,也就是readLine方法来完成键盘录入的一行数据的读取呢? 


/* 


需求,通过键盘录入数据。 


当录入一行数据后,就将该行数据进行打印,如果录入数据是over,那么停止录入 


*/ 


import java.io.InputStream; 


import java.io.InputStramReader; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args)throws IOException{ 


BufferedReader bufr =new BufferedReader(new InputStreamReader(System.in)) ; 


for(String line =null;(line=bufr.readLine())!=null;) { 


if("over".equals(line)) 


break; 


System.out.println(line); 





bufr.close(); 






IO流(写入转换流) 


/* 


需求,通过键盘录入数据。 


当录入一行数据后,就将该行数据进行打印,如果录入数据是over,那么停止录入 


*/ 


import java.io.BufferedReader; 


import java.io.BufferedWriter; 


import java.io.InputStreamReader; 


import java.io.OutputStreamWriter; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args)throws IOException{ 


BufferedReader bufr =new BufferedReader(new InputStreamReader(System.in)); 


BufferedWriter bufw =new BufferedWriter(new OutputStreamWriter(System.out)); 


for(String line = null;(line=bufr.readLine())!=null;){ 


if("over".equals(line)) 


break; 


bufw.write(line); 


bufw.newLine(); 
bufw.flush(); 





bufr.close(); 


bufw.close(); 






IO流(流操作规律) 


1、    源:键盘 
目的:控制台 
/*
需求,通过键盘录入数据。
如果录入数据是over,那么停止录入,否则就打印


*/ 


import java.io.BufferedReader; 


import java.io.BufferedWriter; 


import java.io.InputStreamReader; 


import java.io.OutputStreamWriter; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args)throws IOException{ 


BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); 


BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); 


for(String line = null;(line=bufr.readLine())!=null;){ 


if("over".equals(line)) 


break; 


bufw.write(line); 


bufw.newLine(); 
bufw.flush(); 





bufr.close(); 


bufw.close(); 














2、    源:键盘 




目的:文件 


/* 


需求:将键盘录入的数据输出到一个文本文件中, 


如果录入数据是over,那么停止录入,否则就输入到文件中




*/ 


import java.io.BufferedReader; 


import java.io.BufferedWriter; 


import java.io.InputStreamReader; 


import java.io.OutputStreamWriter; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args)throws IOException{ 


BufferedReader bufr =new BufferedReader(new InputStreamReader(System.in)); 


BufferedWriter bufw =new BufferedWriter(new OutputStreamWriter 


(new FileOutputStream("C:\\1.Java"))); 


for(String line = null;(line=bufr.readLine())!=null;){ 


if("over".equals(line)) 


break; 


bufw.write(line); 


bufw.newLine(); 
bufw.flush(); 





bufr.close(); 


bufw.close(); 






3、    源:文件 


目的:控制台 


/* 


需求:想要讲一个文件的数据打印在控制而台上 
*/ 


import java.io.BufferedReader; 
import java.io.BufferedWriter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.io.FileInputStream; 
public class Test{ 
public static void main(String...args)throws IOException{ 
BufferedReader bufr =new BufferedReader(new InputStreamReader 


(new FileInputStream("C:\\1.Java"))); 


BufferedWriter bufw =new BufferedWriter 


(new OutputStreamWriter(System.out)); 


for(String line =null;(line=bufr.readLine())!=null;){ 
bufw.write(line); 
bufw.newLine(); 
bufw.flush(); 

bufr.close(); 
bufw.close(); 




面向对象 


流操作的基本规律:最痛苦的就是流对象有很多,不知道该用那一个。




通过明确来完成。 


(1)、明确源和目的 


源:输入流InputStream Reader 


目的:输出流OutputStream Writer 


(2)、操作的数据是否是纯文本 


是:字符流 Reader Writer 


不是:字节流 InputStream OutputStream 


(3)、当体系明确后,再明确要使用那个具体的对象 


通过设备来进行区分: 


源设备:内存 硬盘 键盘 


目的设备:内存 硬盘 控制台 


/* 


需求:将一个文本文件中数据存储到另一个文件中。复制文件 


*/ 


源:因为是源,所以使用读取流。InputStream Reader




是否是纯文本文件:是,所以使用 Reader。 


接下来明确要使用该体系中的那个对象: 


明确设备,硬盘,一个文件。 


 Reader体系中可以操作文件的是,FileReader。




是否需要提高效率? 


BufferedReader 


目的:因为是目的,所以使用写入流。OutputStream Writer 


是否是纯文本文件:是,所以使用 Writer。




接下来明确要使用该体系中的那个对象:




明确目的,硬盘,一个文件。




Writer 体系中可以操作文件的是,FileWriter。 


是否需要提高效率?需要。BufferedWriter 


/* 


需求:将键盘录入的数据保存到一个文件中 


这个需求中有源和目的都存在,那么分别分析 


*/ 


源:因为是源,所以使用读取流。InputStream Reader




是否是纯文本文件:是,所以使用 Reader。




接下来明确要使用该体系中的那个对象:




明确设备,键盘。对应的对象是System.in。 


 不是选择Reader吗?System.in 对应的不是字节流吗? 


为了操作键盘的文字数据方便,字节流可以转换成字符流,按照字符串操作最方便。




既然明确了Reader 就将 System.in 转换成Reader




用到了Reader 体系中的转换流,InputSteamReader




需要提高效率吗?需要,BufferedReader 


目的:因为是目的,所以使用写入流。OutputStream Writer 


是否是纯文本文件:是,所以使用 Writer。 


接下来明确要使用该体系中的那个对象: 


明确目的,硬盘,一个文件。 


Writer 体系中可以操作文件的是,FileWriter。


是否需要提高效率?需要。BufferedWriter 


扩展


想要把录入的数据按照指定的编码表(UTF-8),将数据存到文件中,使用转换流,里面可以指定编码。 


目的:OutputStream Writer 


是否是纯文本?是,Writer 




接下来明确要使用该体系中的那个对象: 




明确目的,硬盘,一个文件。 


Writer 体系中可以操作文件的是,FileWriter。 
但是存储时,需要加入指定的编码表,而指定的编码表,只有转换流可以指定。




所以要使用的对象是OutputStreamWriter. 


而该转换流对象要接收一个字节输出流。 


而且还可以操作文件的字节输出流,FileOutputStream 


是否需要提高效率?需要。BufferedWriter




所以,记住,转化暖流什么时候使用,字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。 


IO流(改变标准输入输出设备) 


System 


static void  setIn(InputStream in)
          重新分配“标准”输入流。  
static void  setOut(PrintStream out)
          重新分配“标准”输出流。  






IO流(异常的日志信息) 


import java.util.Date;
import java.text.SimpleDateFormat;
import java.io.PrintStream;
public class Test{




public static void main(String...args) { 


try{ 


int arr[] = new int[2]; 


System.out.println(arr[3]); 


}catch(Exceptione){ 


try{ 


Date d = new Date(); 


SimpleDateFormatsdf = new SimpleDateFormat("yyyy年MM月dd日 E HH:mm:ss"); 


String date = sdf.format(d); 


PrintStream ps = new PrintStream("c:\\execption.txt"); 


ps.println(date); 


System.setOut(ps); 





catch(IOException ex){ 


throw new RuntimeException("日志文件创建失败"); 





e.printStackTrace(System.out); 








}




IO流(系统信息) 


import java.util.Properties; 


import java.io.PrintStream; 


import java.io.IOException; 


public class Test{ 


public static void main(String...args) throws IOException{ 


Properties popr = System.getProperties(); 


popr.list(new PrintStream("C:\\1.properties")); 








面向对象 


File类 


1、用来将文件或者文件夹封装成对象 


2、方便对文件与文件夹进行操作 


3、File对象可以作为参数传递给流的构造函数。 


4、了解File类中的常用方法。 


File
static String  separator
          与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。  




import java.io.File; 


public class Test{ 


public static void main(String...args){ 


/* 


将1.Java封装成 File 对象. 


可以将已有的和未出现的文件或者文件夹封装成对象。 


*/ 


File f1 = new File("C:\\1.Java"); 


File f2 = new File("C:\\","1.Java"); 


File f3 = new File("C:","1.Java"); 


File f4 = new File("C:"+File.separator+"1.Java"); 


sop(f1); 


sop(f2); 


sop(f3); 


sop(f4); 





public static void sop(Object obj){ 


System.out.println(obj); 








IO流(File对象功能-创建和删除) 


File类 


 boolean  createNewFile()
          当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。  
 boolean  mkdir()
          创建此抽象路径名指定的目录。  
 boolean  mkdirs()
          创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。  
 boolean  delete()
          删除此抽象路径名表示的文件或目录。  
 void  deleteOnExit()
          在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。  




import java.io.File; 


import java.io.IOException; 


public class Test{




public static void main(String...args) throws Exception { 


File f = new File("C:\\文件夹\\1.Java"); 


File f1 = new File("C:\\文件夹");  


//创建一个目录。




f1.mkdir(); 


//创建一个文件夹,如果传入文件名中还有文件夹,会自动创建根文件夹和子文件夹。 


f.mkdirs(); 


/* 


调用文件的创建方法,如果该文件的目录不存在,那么将报异常, 


如果该文件存在的话,就不创建文件,如果不存在就创建该文件。 


*/ 


f.createNewFile(); 


/* 


休息4秒种 


*/ 


Thread.sleep(4000); 


/* 


创建了一个文件,如果虚拟机退出,那么该文件将自动删除。 


*/ 


f.deleteOnExit(); 





public static void sop(Object obj){ 


System.out.println(obj); 





}




IO流(File对象功能-判断) 


 boolean  exists()
          测试此抽象路径名表示的文件或目录是否存在。  
 boolean  isAbsolute()
          测试此抽象路径名是否为绝对路径名。  
 boolean  isDirectory()
          测试此抽象路径名表示的文件是否是一个目录。  
 boolean  isFile()
          测试此抽象路径名表示的文件是否是一个标准文件。  
 boolean  isHidden()
          测试此抽象路径名指定的文件是否是一个隐藏文件。  




import java.io.File; 


import java.io.IOException; 


public class Test{




public static void main(String...args)throws IOException{ 


File f = new File("C:\\1.Java"); 


//是否是可执行文件 


sop(f.canExecute()); 


//文件是否存在 


sop(f.exists()); 


//是否是一个文件 


sop(f.isFile()); 


//是否是一个目录 


sop(f.isDirectory()); 


//是否是隐藏文件 


sop(f.isHidden()); 





public static void sop(Object obj){ 


System.out.println(obj); 








IO流(File对象功能-获取) 


 File  getAbsoluteFile()
          返回此抽象路径名的绝对路径名形式。  
 String  getAbsolutePath()
          返回此抽象路径名的绝对路径名字符串。  
 File  getCanonicalFile()
          返回此抽象路径名的规范形式。  
 String  getCanonicalPath()
          返回此抽象路径名的规范路径名字符串。  
 long  getFreeSpace()
          返回此抽象路径名指定的分区中未分配的字节数。  
 String  getName()
          返回由此抽象路径名表示的文件或目录的名称。  
 String  getParent()
          返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。  
 File  getParentFile()
          返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。  
 String  getPath()
          将此抽象路径名转换为一个路径名字符串。  
 boolean  renameTo(File dest)
          重新命名此抽象路径名表示的文件。  




import java.io.File; 


public classTest{ 


public static void main(String...args){ 


File f1 = new File("C:\\1.Java"); 


File f2 = new File("C:\\2.java"); 


f2.renameTo(f1); 





}




static File[]  listRoots()
          列出可用的文件系统根。  
 String[]  list()
          返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。  






import java.io.File; 


public classTest{ 


public static void main(String...args){ 


File[] file = File.listRoots(); 


for(File f : file){ 


System.out.println(f); 





File f = new File("G:\\");
String[] name = f.list();
for(String fileName : name){




System.out.println(fileName); 


}










IO流(列出目录下所有内容-递归) 


/* 


列出指定目录下文件或者文件夹,包含子目录中的内容。 


也就是列出指定目录下所有内容 


因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。 


在列出过程中出现还是目录的话,还可以在此调用本功能 


也就是函数自身调用自身, 


这种表现形式,或者编程手法,成为递归。 








递归要注意:
1、制条件
2、要注意递归次数,避免内存溢出




*/ 


import java.io.File;
public class Test{




public static void main(String...args){ 


File f =new File("C:\\"); 


dir(f); 


toBin(6); 





/* 


public static void toBin(int num){ 


while(num>0){ 


num = num/2; 


sop(num%2); 








*/ 


public static void toBin(int num){ 


if(num>0){ 


toBin(num/2); 


sop(num%2); 








public static void dir(File dir){ 


sop(dir); 


File[] files = dir.listFiles(); 


for(File f : files){ 


if(!f.isHidden()){ 


if(f.isDirectory()) 


dir(f); 


else 


sop(f); 











public static void sop(Objectobj){ 


System.out.println(obj); 





}




IO流(列出目录下所有内容-带层次) 




/*
列出指定目录下文件或者文件夹,包含子目录中的内容。
也就是列出指定目录下所有内容
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。
在列出过程中出现还是目录的话,还可以在此调用本功能
也就是函数自身调用自身,
这种表现形式,或者编程手法,成为递归 




递归要注意:
1、制条件
2、要注意递归次数,避免内存溢出
*/ 


import java.io.File; 


public class Test{ 


public static void main(String...args){ 


File dir = new File("D:\\Demo"); 


dir(dir,0); 





public static String getLevel(int level){ 


StringBuilder sb = new StringBuilder(); 


for(int x=0;x

sb.append("  "); 





return sb.toString(); 





public static void dir(File dir,int level){ 


sop(getLevel(level)+dir); 


level++; 


File[] files = dir.listFiles(); 


for(Filefile:files){ 


if(!file.isHidden()){ 


if(file.isDirectory()) 


dir(file,level); 


else 


sop(getLevel(level+1)+file); 











public static void sop(Object obj){ 


System.out.println(obj); 








IO流(删除带内容的目录) 


import java.io.File;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.List;
import java.util.ArrayList;
public class Test{




public static void main(String...args){ 


File dir = new File("G:\\Java"); 


List list = new ArrayList(); 


dir(dir,list); 


writeToFile(list,"C:\\1.Java",0); 





public static void writeToFile(List list,String fileName,int level){ 


BufferedWriter bufw = null; 


try{ 


bufw = new BufferedWriter(new FileWriter(fileName)); 


String filePath = null;




for(File file:list){ 


if(!file.isDirectory()) 


filePath = getLevel(level+1)+file.getAbsolutePath(); 


else  


filePath = getLevel(level)+file.getAbsolutePath(); 


bufw.write(getLevel(level)+filePath); 


bufw.newLine(); 


bufw.flush(); 








catch (Exception e){ 


throw new RuntimeException("写入失败") ; 





finally{ 


if(bufw!=null) 


try{ 


bufw.close(); 





catch (Exception e){ 


sop("写入关闭失败"); 











public static String getLevel(int level){ 


StringBuilder sb = new StringBuilder(); 


for(int x=0;x

sb.append(""); 





return sb.toString(); 





public static void dir(File dir,List list){ 


File[] files = dir.listFiles(); 


if(dir.exists()){ 


for(File file:files) 


if(!file.isHidden()) 


if(file.isDirectory()){ 


list.add(file); 


dir(file,list); 





else 


list.add(file); 





else  


sop("目录不存在"); 





public static void sop(Object obj){ 


System.out.println(obj); 





}




IO流(Properties简述) 


Properties 是 Hashtable 的子类 


也就是说它具备Map集合的特点,而且它里面存储的键值对都是字符串 


是集合中和IO技术相结合的集合容器 


该对象特点:可以用于键值对形式的配置文件。 


那么在加载数据时候,需要数据有固定格式:键=值 


IO流(Properties存取) 


import java.util.Properties;
import java.util.Set;
public class Test{




public static void main(String...args){ 


Propertiesprop = System.getProperties(); 


Set names = prop.stringPropertyNames(); 


for(String name : names){ 


sop(name+"::"+prop.getProperty(name)); 








public static void sop(Object obj){ 


System.out.println(obj); 





}




IO流(Properties存取配置文件) 


 String  getProperty(String key)
          用指定的键在此属性列表中搜索属性。  
 String  getProperty(String key,String defaultValue)
          用指定的键在属性列表中搜索属性。  
 void  list(PrintStream out)
          将属性列表输出到指定的输出流。  
 void  list(PrintWriter out)
          将属性列表输出到指定的输出流。  
 void  load(InputStream inStream)
          从输入流中读取属性列表(键和元素对)。  
 void  load(Reader reader)
          按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。  
 Object  setProperty(String key,String value)
          调用 Hashtable 的方法 put。  
 void  store(OutputStream out,String comments)
          以适合使用 load(InputStream) 方法加载到Properties 表中的格式,将此Properties 表中的属性列表(键和元素对)写入输出流。  
 void  store(Writer writer,String comments)
          以适合使用 load(Reader) 方法的格式,将此Properties 表中的属性列表(键和元素对)写入输出字符。  




IO流(Properties练习) 






/*
演示,如何将流中的数据存储到集合中
想要将 info.properties 中的键值对数据存到集合中进行操作。 


思路: 








1、用一个流和info.txt文件关联 








2、读取一行数据。将改行数据用"="进行切割。 








3、等号左边作为键,右边作为值,存入到Properties集合中即可 






*/ 


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class Test{


public static void main(String...args)throws IOException{ 
Properties prop = new Properties(); 
BufferedReader bufr = new BufferedReader(new FileReader("C:\\info.Properties")); 
prop.load(bufr); 


sop(prop); 


for(String line=null;(line = bufr.readLine())!=null;){ 


String[] map = line.split("="); 
prop.setProperty(map[0],map[1]); 

String one = prop.getProperty("111"); 
sop(one); 
bufr.close(); 

public static void sop(Objectobj){ 
System.out.println(obj); 




IO流(PrintWriter)




打印流 


PrintWriter 与 PrintStream。可以直接操作输入流和文件。 




/*
打印流
该流提供了打印方法,可以将各种数据烈性的数据都原样打印。 




字节打印流
PrintStream
构造函数可以接受的参数类型
1、file对象。
2、字符串路径。String
3、字节输出流 OutpuStream 




字符打印流
PrintWriter
构造函数可以接受的参数类型
1、file对象。
2、字符串路径。String
3、字节输出流 OutpuStream
4、字符输出流    Writer
*/ 


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.FileWriter;
public class Test{






public static void main(String...args)throws IOException{ 




BufferedReader bufr =new BufferedReader(new InputStreamReader(System.in));  




PrintWriter out =new PrintWriter(new FileWriter("C:\\1.Java"),true); 




for(String line = null;(line=bufr.readLine())!=null;){ 




if("over".equals(line)) 




break; 




out.println(line); 




/* 




由于PrintWriter加入一个参数,true表示自动刷新,所以这里就不用刷新。 




out.flush(); 




*/ 









bufr.close(); 




out.close(); 












IO流(合并流)






序列流、 


SequenceInputStream。对多个流进行合并 


import java.util.Vector;
import java.io.FileInputStream;
import java.io.SequenceInputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.util.Enumeration;
public class Test{








public static void main(String...args)throws IOException{ 






Vector v = new Vector(); 






v.add(new FileInputStream("C:\\1.Java")); 






v.add(new FileInputStream("C:\\2.Java")); 






v.add(new FileInputStream("C:\\3.Java")); 






Enumeration en = v.elements(); 






SequenceInputStream sis = new SequenceInputStream(en); 






FileOutputStream fos =new FileOutputStream("C:\\4.Java"); 






byte[] buf =new byte[1024]; 




int len = 0; 






while((len=sis.read(buf))!=-1){ 






fos.write(buf,0,len); 











sis.close(); 






fos.close(); 














IO流(切割文件) 


import java.io.FileInputStream; 


import java.io.FileOutputStream; 


import java.io.IOException; 


import java.util.ArrayList; 


import java.util.Iterator; 


import java.util.Enumeration; 


import java.io.SequenceInputStream; 


public class Test{ 


public static void main(String...args)throws IOException{ 


splitFile(); 


merge(); 





public static void splitFile()throws IOException{ 


FileInputStream fis =new FileInputStream("C:\\Dj - 赶着马车去北京.mp3"); 


FileOutputStream fos = null; 


byte[] buf = new byte[1024*1024]; 


int len = 0; 


int count= 1; 


while((len=fis.read(buf))!=-1){ 


fos = new FileOutputStream("D:\\Dj - 赶着马车去北京"+(count++)+".part"); 


fos.write(buf,0,len); 


fos.close(); 





fis.close(); 





public static void merge()throws IOException{ 


ArrayListal = new ArrayList(); 


for(int x=1;x<=3;x++){ 


al.add(new FileInputStream("D:\\Dj - 赶着马车去北京"+x+".part")); 





final Iteratorit = al.iterator(); 


Enumerationen =new Enumeration(){ 


public boolean hasMoreElements(){ 


return it.hasNext(); 





public FileInputStream nextElement(){ 


return it.next(); 





}; 


SequenceInputStream sis =new SequenceInputStream(en); 


FileOutputStream fos =new FileOutputStream("E:\\Dj - 赶着马车去北京.mp3"); 


byte[] buf = new byte[1024]; 


int len=0; 


while((len=sis.read(buf))!=-1){ 


fos.write(buf,0,len); 





fos.close(); 


sis.close(); 








面向对象 


IO流(Object) 






构造方法摘要  
   ObjectInputStream(InputStream in) 
          创建从指定 InputStream 读取的 ObjectInputStream。  




操作对象 


ObjectInputStream 与 ObjectOutputStream 
被操作的对象需要实现 Serializable (标记接口); 


ObjectInputStream 
Object  readObject()
          从 ObjectInputStream 读取对象。  
ObjectOutputStream
 void  writeObject(Object obj)
          将指定的对象写入 ObjectOutputStream。  






import java.io.Serializable; 


import java.io.IOException; 


import java.io.ObjectOutputStream; 


import java.io.FileOutputStream; 


import java.io.FileInputStream; 


import java.io.ObjectInputStream; 


class Person implements Serializable{ 




public static final long serialVersionUID = 42L;


private String name; 


private transient int age; 


public static String contry ="cn"; 


Person(String name,int age,String contry){ 


this.name=name; 


this.age=age; 


this.contry = contry; 





public String toString(){ 


return name+":"+age+":"contry; 








public class Test{ 


public static void main(String...args) throws Exception{ 


writeObj(); 


readObj(); 





public static void readObj() throws Exception{ 


ObjectInputStream ois = 


new ObjectInputStream(new FileInputStream("C:\\1.Java")); 


Person p = (Person)ois.readObject(); 


System.out.println(p); 


ois.close(); 





public static void writeObj() throws IOException{ 




ObjectOutputStream oos =  


new ObjectOutputStream(new FileOutputStream("C:\\1.Java")); 




oos.writeObject(new Person("黑马程序员——新长城",20,"HK")); 




oos.close(); 








注意三点: 


1)静态是不能被序列化的。 


2)如果非静态想被序列化可以加transient。 


3)想被序列化的对象要实现Serializable。 


IO流(管道流) 


PipedInputStream和PipedOutputStream 


输入输出可以直接进行连接,通过结合线程使用。




import java.io.PipedInputStream ;
import java.io.PipedOutputStream;
import java.io.IOException;
class Read implements Runnable{




private PipedInputStream in; 


Read(PipedInputStream in){ 


this.in=in; 





public void run(){ 


try{ 


byte[] buf =new byte[1024]; 


System.out.println("读取前。。没有数据阻塞"); 


int len = in.read(buf); 


System.out.println("读到数据。。阻塞结束"); 


String data =new String(buf,0,len); 


System.out.println(data); 


in.close(); 





catch (Exception e){ 


throw new RuntimeException("管道输入失败"); 











class Write implements Runnable{




private PipedOutputStream out; 


Write(PipedOutputStream out){ 


this.out=out; 





public void run(){ 


try{ 


System.out.println("开始写入数据,等待六秒"); 


Thread.sleep(6000); 


out.write("哥们来了".getBytes()); 


out.close(); 





catch (Exception e){ 


throw new RuntimeException("管道输出失败"); 











public class Test{




public static void main(String...args)throws IOException{ 


PipedInputStream pis =new PipedInputStream(); 


PipedOutputStream pos =  new PipedOutputStream(); 


pis.connect(pos); 


Read r = new Read(pis); 


Write w = new Write(pos); 


new Thread(r).start(); 


new Thread(w).start(); 








IO流(RandomAccessFile)


/* 


RandomAccessFile 该类不是算是IO体系中子类。而是直接继承自Object。 








但是它是IO包中成员。因为它具备读和写功能。 


内部封装了一个数组,而且通过指针对数组的元素进行操作。 


可以通过getFilePointer获取指针位置, 


同时可以通过seek改变指针的位置。 








其实完成读写的原理就是内部封装了字节输入流和输出流。 








通过构造函数可以看出,该类只能操作文件。 


而且操作文件还有模式:只读r,,读写rw等。 








如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。 


如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。 


*/ 


构造方法摘要  
RandomAccessFile(File file,String mode)
          创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。  




import java.io.IOException; 


import java.io.RandomAccessFile; 


public class Test{ 


public static void main(String...args)throws IOException{ 


writeFile(); 


//readFile(); 





public static void readFile()throws IOException{ 


RandomAccessFile raf =new RandomAccessFile("C:\\1.Java","r"); 


byte[] buf =new byte[20]; 


raf.seek(24*1); 


int len = raf.read(buf); 


String name  =new String(buf); 


int age = raf.readInt(); 


System.out.println("name = "+name+"\nage = "+age); 


raf.close(); 





public static void writeFile()throws IOException{ 


RandomAccessFile raf =new RandomAccessFile("C:\\1.Java","rw"); 


raf.write("黑马程序员——新长城".getBytes()); 


raf.writeInt(97); 


raf.write("黑马程序员——好男孩".getBytes()); 


raf.writeInt(99); 


raf.write("黑马程序员——坏小孩".getBytes()); 


raf.writeInt(98); 


raf.close(); 




此类还可以把数据分成一部分一部分,然后再把数据拼凑起来,跟我们下载程序是一样的,多线程。 


(IO流基本数据操作流) 


DataInputStream与DataOutputStream。 


import java.io.DataOutputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.OutputStreamWriter;
public class Test{




public static void main(String...args)throws IOException{ 


//writeData(); 


//readData(); 


//writeUTF(); 


//readUTF(); 


//defaultGBK(); 


//utf_8(); 





public static void utf_8()throws IOException{ 


OutputStreamWriter osw = 


new OutputStreamWriter(new FileOutputStream("C:\\UTF-8.Java"),"utf-8"); 


osw.write("你好"); 


osw.close(); 





public static void defaultGBK()throws IOException{ 


OutputStreamWriter osw =  


new OutputStreamWriter(new FileOutputStream("C:\\GBK.Java")); 


osw.write("你好"); 


osw.close(); 





public static void readUTF()throws IOException{ 


DataInputStream dis = 


new DataInputStream(new FileInputStream("C:\\UTF.Java")); 


String s = dis.readUTF(); 


System.out.println(s); 





public static void writeUTF()throws IOException{ 


DataOutputStream dos = 


new DataOutputStream(new FileOutputStream("C:\\UTF.Java")); 


dos.writeUTF("你好"); 


dos.close(); 





public static void readData()throws IOException{ 


DataInputStream dis =  


new DataInputStream(new FileInputStream("C:\\data.Java")); 


int i = dis.readInt(); 


boolean b = dis.readBoolean(); 


double d = dis.readDouble(); 


System.out.println(i+"..."+b+"..."+d); 


dis.close(); 





public static void writeData()throws IOException{ 


DataOutputStream dos = 


new DataOutputStream(new FileOutputStream("C:\\data.Java")); 


dos.writeInt(97); 


dos.writeBoolean(true); 


dos.writeDouble(12.56); 


dos.close(); 








主要不同之处就是UTF修改版里面,俩个汉字是8个字节而,UTF-8俩个汉字是6个字节,GBK俩个汉字是4个字节。 


(IO流字节数组操作流)


/* 


用于操作字节数组的流对象。
ByteArrayInputStream :   在构造的时候,需要接收数据源,。而且数据源是一个字节数组。


ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。 


这就是数据目的地。 


因为这两个流对象都操作的数组,并没有使用系统资源。
所以,不用进行close关闭。


在流操作规律讲解时:


源设备,
键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
控制台 System.out,硬盘FileStream,内存 ArrayStream。




用流的读写思想来操作数组。 


除了writeTo方法抛异常外,其他方法不会抛任何IOException 


*/ 


import java.io.ByteArrayInputStream; 


import java.io.ByteArrayOutputStream; 


import java.io.FileOutputStream; 


import java.io.IOException; 


import java.io.FileInputStream; 


public class Test {


public static void main(String... args)throws IOException{ 


FileInputStream fis =new FileInputStream("1.Java"); 


int len =0; 


byte[]buf =new byte[fis.available()]; 


len = fis.read(buf); 


ByteArrayInputStream bis =  


new ByteArrayInputStream(new String(buf,0,len).getBytes()); 


ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
for(int by = 0;(by=bis.read())!=-1;){ 


bos.write(by); 

System.out.println(bos.size()); 
System.out.println(bos.toString()); 
bos.writeTo(new FileOutputStream("C:\\2.Java")); 




(IO流字符数组操作流) 


CharArrayReader与CharArrayWriter跟字节数组操作流一样。 


不需要调用底层资源(也就是文件),不会抛异常,除了writeTo方法外。 


(IO流字符串操作流) 


StringReader与StringWriter跟字节数组操作流一样。 


不需要调用底层资源(也就是文件),不会抛异常。




(IO流编码表) 


编码表由来: 


计算机只能识别二进制数据,早期由来是电信号。 


为了方便应用计算机,让它可以识别各个国家的文字。 


就将各个国家的文字用数字来表示,并一一对应,形成一张表。这就是编码表。 


常见编码表: 


ASCII:美国标准信息交换码。用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表用一个字节的8位表示。
GB2312:中国的中文编码表。用两个字节来表示。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。用两个字节来表示。
Unicode:国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符。
......




(IO流转换流字符编码) 


import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class Test{




public static void main(String...args)throws IOException{ 


writeGBKText(); 


readGBKText(); 


writeUTFText(); 


readUTFText(); 





public static void readUTFText()throws IOException{ 


InputStreamReader isr =  


new InputStreamReader(new FileInputStream("C:\\UTF-8.Java"),"UTF-8"); 


char[] buf =new char[10]; 


for(int len = 0;(len=isr.read(buf))!=-1;){ 


System.out.println(new String(buf,0,len)); 





isr.close(); 





public static void readGBKText()throws IOException{ 


InputStreamReader isr = 


new InputStreamReader(new FileInputStream("C:\\GBK.Java"),"GBK"); 


char[] buf = new char[10]; 


for(int len = 0;(len=isr.read(buf))!=-1;){ 


System.out.println(new String(buf,0,len)); 





isr.close(); 





public static void writeGBKText()throws IOException{ 


OutputStreamWriter osw =  


new OutputStreamWriter(new FileOutputStream("C:\\GBK.Java"),"GBK"); 


osw.write("你好"); 


osw.close(); 





public static void writeUTFText()throws IOException{ 


OutputStreamWriter osw =  


new OutputStreamWriter(new FileOutputStream("C:\\UTF-8.Java"),"utf-8"); 


osw.write("你好"); 


osw.close(); 








(字符编码表-编码-解码) 


/* 


编码:字符串变成字节数组。String->>byte[]: str.getBytes(); 


解码:字节数组变成字符串。byte[]->>String: new String(byte[]); 


*/ 








构造方法摘要  
String(byte[] bytes,String charsetName)
          通过使用指定的 charset 解码指定的 byte 数组,构造一个新的String。  






 byte[]  getBytes(String charsetName)
          使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。  






import java.util.Arrays; 


public class Test{ 


public static void main(String...args)throws Exception{ 


String s = "哈哈"; 


//编码 


byte[]b1 = s.getBytes("Unicode"); 


System.out.println(Arrays.toString(b1)); 


//解码 


String s1 = new String(b1,"ISO8859-1"); 


System.out.println(s1); 


//编码 


byte[]b2 = s1.getBytes("ISO8859-1"); 


System.out.println(Arrays.toString(b2)); 


//解码 


String s2 =new String(b2,"Unicode"); 


System.out.println(s2); 








注意: 


ISO8859-1码表之所以能编码解码是因为ISO8859-1不涉及到汉字编码 


而UTF-8编码表涉及到了汉字编码,所以导致了数据的错乱。 


Tomcat服务器默认编码是ISO8859-1。 


(编码表特殊之处) 


public class Test{




public static void main(String...args) throws Exception{ 


String s ="联通"; 


byte[]buf = s.getBytes("GBK"); 


for(byte b :buf){ 


System.out.println(Integer.toBinaryString(b&255)); 








}




发现GBK联通的编码跟UFT-8的编码形式相同,于是记事本就去找UTF-8的编码表,导致了数据错乱,解决方法就是在联通前面加个文字就OK了,但是不能是Ascll值,因为UTF-8里面兼容了Ascll码表。 


(IO流练习) 


/*
有五个学生,每个学生有3门课的成绩,
从键盘输入以上数据(包括姓名,三门课成绩),
输入的格式:如:zhagnsan,30,40,60计算出总成绩,
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件指定文件中。


1,描述学生对象。
2,定义一个可操作学生对象的工具类。


思想:
1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2,因为学生有很多,那么就需要存储,使用到集合。因为要对学生的总分排序。
所以可以使用TreeSet。
3,将集合的信息写入到一个文件中。
*/
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.Set;
import java.util.TreeSet;
import java.io.File;
import java.util.Comparator;
import java.util.Collections;
class Student implements Comparable


private String name; 


private int cn; 


private int ma; 


private int en; 


private int sum; 


Student(String name,int cn,int ma,int en){ 


this.name=name; 


this.cn=cn; 


this.ma=ma; 


this.en=en; 


sum = (cn+ma+en); 





public int getSum(){ 


return sum; 





public String getName(){ 


return name; 





public int hashCode(){ 


return this.name.hashCode()+sum*20; 





public boolean equals(Object obj){ 


if(!(obj instanceofStudent)) 


throw newClassCastException("类型不匹配"); 


Student stu = (Student)obj; 


return this.name.equals(stu.name) &&this.sum ==stu.sum; 





public int compareTo(Student stu){ 


int num =this.sum-stu.sum; 


if(num==0) 


return this.name.compareTo(stu.name); 


return num; 





publicString toString(){ 


return "student["+"姓名:"+name+"\t语文 "+cn+"\t数学 "+ma+"\t英语 "+en+"]\t"; 





}
class StudentInfoTool{




public static Set getStudents()throws IOException{ 


returngetStudents(null); 





public static Set getStudents(Comparatorcmp)throws IOException{ 


BufferedReader bufr =  


new BufferedReader(new InputStreamReader(System.in)); 


Set stus =null; 


if(cmp ==null) 


stus = new TreeSet(); 


else 


stus =newTreeSet(cmp); 


String line =null; 


while((line=bufr.readLine())!=null){ 


if("over".equals(line)) 


break; 


String []arr = line.split(" "); 


Student stu =new Student(arr[0],Integer.parseInt(arr[1]), 


Integer.parseInt(arr[2]), 


Integer.parseInt(arr[3])); 


stus.add(stu); 





bufr.close(); 


return stus; 





public static void writeToFile(Setstus,File file)throws IOException{ 


BufferedWriter bufw  =newBufferedWriter(new FileWriter(file)); 


for(Student stu : stus){ 


bufw.write(stu.toString()); 


bufw.write("\t"+stu.getSum()); 


bufw.newLine(); 


bufw.flush(); 





bufw.close(); 








public classTest{




public static void main(String...args)throws IOException{ 


Comparator cmp =Collections.reverseOrder(); 


Set set = StudentInfoTool.getStudents(cmp); 


StudentInfoTool.writeToFile(set,new File("C:\\stu.txt")); 





}


面向对象 


类 


Reader 


|--InputStreamReader 


|--FileReader 


|--BufferedReader 


|--LineNumberReader 


|--CharArrayReader 


|--StringReader 


|--PipedReader 


Writer 


|--OutputStreamWriter 


|--FileWriter 


|--BufferedWriter 


|--CharArrayWriter 


|--StringWriter 


|--PrintWriter 


|--PipedWriter 


File


InputStream 


|--FilerInputStream 


|--LineNumberInputStream 


|--BufferedInputStream 


|--DataInputStream 


|--FileInputStream 


|--ByteArrayInputStream 


|--PipedInputStream 


|--ObjectInputStream 


|--SequenceInputStream 


OutputStream 


|--FilerOutputStream 


|--PrintOutputStream 


|--BufferedOutputStream 


|--DataOutputStream 


|--FileOutputStream 


|--ByteArrayOutputStream 


|--PipedOutputStream 


|--ObjectOutputStream 


RandomAccessFile 








接口 


Serializable 


面向对象 


GUI(图形用户界面)




GUI:Graphical User Interface(图形用户接口)。 


用图形的方式,来显示计算机操作的界面,这样更方便更直观。










CLI:Command line User Interface (命令行用户接口) 


就是常见的Dos命令行操作。需要记忆一些常用的命令,操作不直观。 


举例:


比如:创建文件夹,或者删除文件夹等
Java为GUI提供的对象都存在Java.Awt和Javax.Swing两个包中。




GUI(Awt和Swing) 


Awt与 Swing




Java.Awt:Abstract Window ToolKit (抽象窗口工具包)。 


需要调用本地系统方法实现功能,属于重量级控件。 


Javax.Swing:在AWT的基础上,建立的一套图形界面系统。 


其中提供了更多的组件,而且完全由Java实现。增强了移植性,属轻量级控件。 


继承关系 


Component 


|--Button(按钮) 


|--Label(标签) 


|--Checkbox(复选框) 


|--TextComponent(文本框) 


|--TextArea(单行文本框) 


|--TextField(多行文本框) 


|--Container(容器,特殊组件,可通过add方法添加其他组件) 


|--Panel(画板) 


|--Window(窗口) 


|--Frame(窗体) 


|--Dialog(对话框) 


|--FileDialog(文件对话框) 


布局管理器 


容器中的组件的排放方式,就是布局。




常见的布局管理器:  


FlowLayout(流式布局管理器) 


从左到右的顺序排列。(中左右)




Panel默认的布局管理器。




BorderLayout(边界布局管理器) 


东,南,西,北,中。




Frame默认的布局管理器。




GridLayout(网格布局管理器) 


规则的矩阵。




CardLayout(卡片布局管理器) 


选项卡。




GridBagLayout(网格包布局管理器) 


非规则的矩阵。 


(图形化布局基本设计) 


类 Component 


 void  setLocation(int x, int y) 
          将组件移到新位置。  
 void  setSize(int width, int height) 
          调整组件的大小,使其宽度为 width,高度为 height。  
 void  setVisible(boolean b) 
          根据参数 b 的值显示或隐藏此组件。  


类 Container 


 Component  add(Component comp)
          将指定组件追加到此容器的尾部。  


类 Frame 


构造方法摘要  
Frame()
          构造一个最初不可见的 Frame 新实例()。  
Frame(String title)
          构造一个新的、最初不可见的、具有指定标题的 Frame 对象。  




类 Button 


构造方法摘要  
Button()
          构造一个标签字符串为空的按钮。  
Button(String label)
          构造一个带指定标签的按钮。  




类 FlowLayout 


构造方法摘要  
FlowLayout()
          构造一个新的 FlowLayout,它是居中对齐的,默认的水平和垂直间隙是 5 个单位。  




import java.awt.Frame; 


import java.awt.Button; 


import java.awt.FlowLayout; 


/*
创建图形化界面:
1.创建frame窗体。
2.对窗体进行基本设置。
比如大小,位置,布局。
3.定义组件。
4.将组件通过窗体的add方法添加到窗体中。
5.让窗体显示。
*/
public class Test{


public static void main(String...args){ 
Frame f =new Frame("我的电脑"); 
f.setSize(1025,550); 
f.setLocation(0,100); 
f.setLayout(new FlowLayout()); 




Button b = new Button("360安全卫士"); 
f.add(b); 
f.setVisible(true); 
System.out.println("Hello 新长城"); 




(事件监听机制) 


事件监听机制的特点:




1,事件源。 


2,事件。 


3,监听器。 


4,事件处理。 


事件源:就是Awt包或者Swing包中的那些图形界面组件。 


事件:每一个事件源都有自己特有的对应事件和共性事件。
监听器:将可以触发某一个事件的动作(不只一个动作)都已经封装到了监听器中。


以上三者,在Java中都已经定义好了。
直接获取其对象来用就可以了。 




我们要做的事情是,就是对产生的动作进行处理。 


(自定义事件事件处理方式) 
import java.awt.Frame;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; 




类 Window 


void  addWindowListener(WindowListener l)
          添加指定的窗口侦听器,以从此窗口接收窗口事件。  


接口 WindowListener 类 WindowAdapter 


 void  windowActivated(WindowEvent e)
          将 Window 设置为活动 Window 时调用。  
 void  windowClosed(WindowEvent e)
          因对窗口调用 dispose 而将其关闭时调用。  
 void  windowClosing(WindowEvent e)
          用户试图从窗口的系统菜单中关闭窗口时调用。  
 void  windowDeactivated(WindowEvent e)
          当 Window 不再是活动 Window 时调用。  
 void  windowDeiconified(WindowEvent e)
          窗口从最小化状态变为正常状态时调用。  
 void  windowIconified(WindowEvent e)
          窗口从正常状态变为最小化状态时调用。  
 void  windowOpened(WindowEvent e)
          窗口首次变为可见时调用。  


类 WindowEvent 


public class Test{ 


public static void main(String...args){ 


Frame f =new Frame("我的电脑"); 


f.setSize(1025,550); 


f.setLocation(0,100); 


f.setLayout(new FlowLayout()); 


Button b =new Button("360安全卫士"); 


f.add(b); 


f.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){ 


System.out.println("我要退出了"); 


System.out.println(e.toString()); 


System.exit(0); 





public void windowActivated(WindowEvent e){ 


System.out.println("激活"); 


}   


public void windowOpened(WindowEvent e){ 


System.out.println("打开"); 


}  


}); 


f.setVisible(true); 


System.out.println("Hello 新长城"); 





}
/*
WinodwListener接口
abstract class WindowAdapter implements WindowListener{




void windowActivated(WindowEvent e){} 


void windowClosed(WindowEvent e){} 


void windowClosing(WindowEvent e){} 


void windowDeactivated(WindowEvent e){}  


void windowDeiconified(WindowEvent e){} 


void windowIconified(WindowEvent e){} 


void windowOpened(WindowEvent e){} 


}
*/
/*
class MyWin implements WindowListener{




覆盖7个方法。可以我只用到了关闭的动作。 


其他动作都没有用到,可是却必须复写。 





*/
/* 


因为WindowListener的子类WindowAdapter已经实现了WindowListener接口。
并覆盖了其中的所有方法。那么我只要继承自Windowadapter覆盖我需要的方法即可。 


*/ 


/*
class MyWin extends WindowAdapter{




public void windowClosing(WindowEvent e){ 


System.out.println("window closing---"+e.toString()); 


System.exit(0); 








*/ 


化难为易: 


(1)、确定事件源(容器或组件) 


(2)、通过事件源对象的addxxxListener()方法将监听器注册到该事件源上。 


(3)、该方法中接收XXXListener对象,或者XXXListener的子类XXXAdapter对象。 


(4)、一般用匿名内部类来表示。 


(5)、再覆盖方法的时候,方法的参数一般是XXXEvent类型的变量接收。 


(6)、一般XXXListener方法超过3个或者3个就一定会有一个XXXAdapter子类对象。(也称为适配器) 


(按钮触发事件) 


import java.awt.Frame;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent; 


接口 ActionListener 


方法摘要  
 void  actionPerformed(ActionEvent e)
          发生操作时调用。  




类 ActionEvent 




public class Test{


//定义该图形中所需的组件的引用。 


private Frame f ; 


private Button b ; 


Test(){ 


init(); 





public void init(){ 


f =new Frame("我的电脑"); 


//对frame进行基本设置。 


f.setSize(1025,550); 


f.setLocation(0,100); 


f.setLayout(new FlowLayout()); 


b =new Button("退出"); 


//将组件添加到frame中 


f.add(b); 


//加载一下窗体上事件。 


myEvent(); 


//显示窗体; 


f.setVisible(true); 





private void myEvent(){ 


f.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){ 


System.out.println("我要退出了"); 


System.out.println(e.toString()); 


System.exit(0); 





public void windowActivated(WindowEvent e){ 


System.out.println("激活"); 


}   


public void windowOpened(WindowEvent e){ 


System.out.println("打开"); 


}  


}); 


//让按钮具备退出程序的功能 


/* 


按钮就是事件源。 


那么选择哪个监听器呢? 


通过关闭窗体示例了解到,想要知道哪个组件具备什么样的特有监听器。 


需要查看该组件对象的功能。 


通过查阅Button的描述。发现按钮支持一个特有监听addActionListener。 


*/ 


b.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e) { 


System.out.println("退出"); 


System.exit(0); 





}); 





public static void main(String...args){ 


new Test(); 


System.out.println("Hello 新长城"); 





}




(鼠标监听事件) 
import java.awt.Frame; 
import java.awt.Button; 
import java.awt.FlowLayout; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 


类 Component 


 void  addMouseListener(MouseListener l)
          添加指定的鼠标侦听器,以接收发自此组件的鼠标事件。  




接口 MouseListener 类 MouseAdapter 


 void  mouseClicked(MouseEvent e)
          鼠标按键在组件上单击(按下并释放)时调用。  
 void  mouseEntered(MouseEvent e)
          鼠标进入到组件上时调用。  
 void  mouseExited(MouseEvent e)
          鼠标离开组件时调用。  
 void  mousePressed(MouseEvent e)
          鼠标按键在组件上按下时调用。  
 void  mouseReleased(MouseEvent e)
          鼠标按钮在组件上释放时调用。  






public class Test{ 
private Frame f ; 


private Button b ; 


Test(){ 


init(); 





public void init(){ 


f =new Frame("我的电脑"); 


f.setSize(1025,550); 


f.setLocation(0,100); 


f.setLayout(new FlowLayout()); 


b =new Button("360安全卫士"); 


f.add(b); 


myEvent(); 


f.setVisible(true); 





private void myEvent(){ 
f.addWindowListener(new WindowAdapter(){ 
public void windowClosing(WindowEvent e){ 
System.out.println("我要退出了"); 
System.exit(0); 

}); 
b.addActionListener(new ActionListener(){ 
public void actionPerformed(ActionEvent e){ 
//System.out.println("活动 action ok"); 

}); 
b.addMouseListener(new MouseAdapter(){ 
private int count = 1; 
private int clickCount =1; 
public void mouseEntered(MouseEvente){ 
//System.out.println("鼠标来了"+count++); 
//System.exit(0); 
}  
public void mouseExited(MouseEvent e) { 
//System.out.println("鼠标走了"); 

public void mouseClicked(MouseEvent e){ 
if(e.getClickCount()==2) 
System.out.println("鼠标双击"); 
//System.out.println("鼠标单击"+clickCount++); 
}  
}); 

public static void main(String...args){ 
new Test(); 


System.out.println("Hello 新长城"); 






一定要用面向对象思考问题。 


鼠标监视器应该属于所有组件所具备的,所以鼠标减速器应该定义在Component里面 


鼠标所点击的次数记录,应该定义在鼠标事件里面。 


注意: 


按钮的获得监听应该定义在按钮里面。 


按钮活动和按钮被点击是按钮点击先执行,因为按键点击更为具体。 


活动监听非得用鼠标,用键盘也是可以的。 


Event 事件 Listener 监听器 Adapter 适配器 


(键盘监听事件) 


import java.awt.Frame; 


import java.awt.Button; 


import java.awt.FlowLayout; 


import java.awt.TextField;




import java.awt.event.WindowAdapter; 


import java.awt.event.WindowEvent; 


import java.awt.event.MouseAdapter; 


import java.awt.event.MouseEvent; 


import java.awt.event.ActionListener; 


import java.awt.event.ActionEvent; 


import java.awt.event.KeyAdapter; 


import java.awt.event.KeyEvent; 


类 Component 


 void  addKeyListener(KeyListener l)
          添加指定的按键侦听器,以接收发自此组件的按键事件。  


接口 KeyListener 类 KeyAdapter 


 void  keyPressed(KeyEvent e)
          按下某个键时调用此方法。  
 void  keyReleased(KeyEvent e)
          释放某个键时调用此方法。  
 void  keyTyped(KeyEvent e)
          键入某个键时调用此方法。  


类 TextField 


构造方法摘要  
TextField()
          构造新文本字段。  




public class Test{ 


private Frame f ; 


private Button b ; 


private TextField tf; 


Test(){ 


init(); 





public void init(){ 


f =new Frame("我的电脑"); 


f.setSize(1025,550); 


f.setLocation(0,100); 






f.setLayout(new FlowLayout()); 






b =new Button("360安全卫士"); 


f.add(b); 


tf =new TextField(10); 


f.add(tf); 


myEvent(); 


f.setVisible(true); 







private void myEvent(){ 


tf.addKeyListener(new KeyAdapter(){ 


public void keyPressed(KeyEvent e){ 


int code = e.getKeyCode(); 


if(!(code>=KeyEvent.VK_0 && code<=KeyEvent.VK_9)){ 


System.out.println(code+"........非法"); 


e.consume(); 








}); 


f.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){ 


System.out.println("我要退出了"); 


System.exit(0); 





}); 


/* 


b.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e){ 


//System.out.println("action ok"); 





}); 


b.addMouseListener(new MouseAdapter(){ 


private int count = 1; 


private int clickCount =1; 


public void mouseEntered(MouseEvent e){ 


//System.out.println("鼠标来了"+count++); 


//System.exit(0); 


}  


public void mouseExited(MouseEvent e) { 


//System.out.println("鼠标走了"); 





public void mouseClicked(MouseEvent e){ 


if(e.getClickCount()==2) 


System.out.println("鼠标双击"); 


//System.out.println("鼠标单击"+clickCount++); 


}  


}); 


//给Button添加一个键盘监听 


b.addKeyListener(new KeyAdapter(){ 


public void keyPressed(KeyEvent e){ 


//if(e.getKeyText(e.getKeyCode())=="Esc") 


//if(e.getKeyCode()==27) 


//组合键 


if(e.isControlDown()&&e.getKeyCode()==KeyEvent.VK_ENTER) 


System.exit(0); 


System.out.println(KeyEvent.getKeyText(e.getKeyCode())); 


System.out.println(e.getKeyChar()+"..."+e.getKeyCode()); 





}); 


*/ 





public static void main(String...args){ 




new Test(); 






System.out.println("Hello 新长城"); 










(GUI 练习-列出指定目录内容) 


import java.awt.Frame; 


import java.awt.Button; 


import java.awt.FlowLayout; 


import java.awt.TextField; 


import java.awt.TextArea; 


import java.awt.Label; 


import java.awt.Dialog; 


import java.awt.event.WindowAdapter; 


import java.awt.event.WindowEvent; 


import java.awt.event.ActionListener; 


import java.awt.event.ActionEvent; 


import java.awt.event.KeyAdapter; 


import java.awt.event.KeyEvent; 


类 TextArea 


构造方法摘要  
TextArea()
          构造一个将空字符串作为文本的新文本区。  




类 Label 


构造方法摘要  
Label()
          构造一个空标签。  




类 Dialog 


构造方法摘要  
Dialog(Frame owner,String title, boolean modal)
          构造一个最初不可见的 Dialog,它带有指定的所有者 Frame、标题和模式。  


public class Test{




private Frame f ; 


private Button b ; 


private TextField tf; 


private TextArea ta; 


private Dialog d; 


private Label lab; 


private Button buf; 


Test(){ 


init(); 





public void init(){ 


f =new Frame("Window"); 


f.setBounds(0,100,1025,550); 


f.setLayout(new FlowLayout()); 


tf =new TextField(100); 


ta =new TextArea("Hello",28,107); 


b =new Button("转到"); 




d =new Dialog(f,"提示信息-self",true); 


d.setBounds(400,250,300,200); 


d.setLayout(new FlowLayout()); 


lab =new Label(); 


buf =new Button("确定"); 


d.add(lab); 


d.add(buf); 








f.add(tf); 


f.add(b); 


f.add(ta); 








myEvent(); 


f.setVisible(true); 





private void myEvent(){ 


tf.addKeyListener(new KeyAdapter(){ 


public void keyPressed(KeyEvent e){ 


if(e.getKeyCode()==KeyEvent.VK_ENTER) 


showDir(); 





}); 


buf.addKeyListener(new KeyAdapter(){ 


public void keyPressed(KeyEvent e){ 


if(e.getKeyCode()==KeyEvent.VK_ENTER) 


d.setVisible(false); 





}); 


buf.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e){ 


d.setVisible(false); 





}); 


d.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){  


d.setVisible(false); 





}); 


b.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e){ 


showDir(); 





}); 


f.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){  


System.exit(0); 





}); 





public void showDir(){ 


String dirPath = tf.getText(); 


File dir =new File(dirPath); 


if(dir.exists()&&dir.isDirectory()){ 


String[] names = dir.list(); 


ta.setText(""); 


for(String name : names){ 


ta.append(name+"\r\n"); 








else{ 


String info ="你输入的信息:"+dirPath+"是错误的 请重新输入"; 


lab.setText(info); 


d.setVisible(true); 








public static void main(String...args){ 


new Test(); 


System.out.println("Hello 新长城"); 





}




(GUI 练习-记事本小软件) 


import java.awt.Frame;
import java.awt.Button;
import java.awt.FlowLayout;
import java.awt.TextField;
import java.awt.TextArea;
import java.awt.Dialog;
import java.awt.MenuBar;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.FileDialog;
import java.io.File;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent; 


类 MenuBar 


构造方法摘要  
MenuBar()
          创建新的菜单栏。  


类 Menu 


构造方法摘要  
Menu(String label)
          构造具有指定标签的新菜单。  


类 MenuItem 


构造方法摘要  
MenuItem(String label)
          构造具有指定的标签且没有键盘快捷方式的新菜单项。  


类 Frame 


 void  setMenuBar(MenuBar mb)
          将此窗体的菜单栏设置为指定的菜单栏。  




package Menu; 


public class Test {




private Frame window; 


private MenuBar bar; 


private Menu file; 


private MenuItem openItem,saveItem,closeItem; 


private FileDialog openDia,saveDia; 


private TextArea ta; 


private File f; 


Test(){ 


init(); 





public void init(){ 


window =new Frame("Window"); 


window.setBounds(0,100,1025,550); 


//window.setLayout(new FlowLayout()); 








ta =new TextArea(); 


bar =new MenuBar(); 


file =new Menu("文件"); 


openItem =new MenuItem("打开"); 


saveItem =new MenuItem("保存"); 


closeItem =new MenuItem("关闭"); 








bar.add(file); 


file.add(openItem); 


file.add(saveItem); 


file.add(closeItem); 








openDia =new FileDialog(window,"打开",FileDialog.LOAD); 


saveDia =new FileDialog(window,"另存为",FileDialog.SAVE); 




window.add(ta); 


window.setMenuBar(bar); 


myEvent(); 


window.setVisible(true); 





private void myEvent(){ 


openItem.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e) { 


openDia.setVisible(true); 


String dirPath = openDia.getDirectory(); 


String fileName = openDia.getFile(); 


if(dirPath==null || fileName==null) 


return ; 


ta.setText(""); 


f =new File(dirPath,fileName); 


try{ 


printFile(f); 





catch (Exception ex){ 


throw new RuntimeException("读取失败"); 








}); 


saveItem.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e) { 


if(file!=null){ 


saveDia.setVisible(true); 


String dirPath = saveDia.getDirectory(); 


String fileName = saveDia.getFile(); 


if(dirPath==null || fileName==null) 


return ; 


f =new File(dirPath,fileName); 





try{ 


writeFile(f); 







catch (IOExceptionex){ 


throw new RuntimeException("另存为失败"); 










}); 


closeItem.addActionListener(new ActionListener(){ 
public void actionPerformed(ActionEvent e) { 


System.exit(0); 





}); 


window.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){  


System.exit(0); 





}); 





private void writeFile(File file)throws IOException{ 








BufferedWriter bufw =  


new BufferedWriter(new FileWriter(file)); 


String text = ta.getText(); 


bufw.write(text); 


bufw.close(); 





private void printFile(File file)throws IOException{ 


BufferedReader bufr =  


new BufferedReader(new FileReader(file)); 


String line =null; 


while((line=bufr.readLine())!=null){ 


ta.append(line+"\r\n"); 





bufr.close(); 





public static void main(String... args) { 


new Test(); 








制作可以双击执行的Jar包 


1,将多个类封装到了一个包(package)中。 


2,定义一个Jar包的配置信息。 


定义一个文件1.properties 。文件内容内容为:Main-Class:(空格)包名.类名(回车) 


3,将多个class文件封装到一个目录中,打成Jar包。 


Jar -cvfm my.Jar 1.properties 包名 


4,通过Win RAR程序进行验证,查看该Jar的配置文件中是否有自定义的配置信息。 


5,通过工具--文件夹选项--文件类型--Jar类型文件,通过高级,定义该Jar类型文件的打开动作的关联程序。 


JDK\Bin\Javaw.exe -Jar 


6,双击试试。 




面向对象 


(网络编程:概述) 






1、网络模型 


(1)OSI参考模型 
(2)TCP/IP参考模型 


 


2、网络通讯要素 


(1)IP地址(InetAddress已经封装成了对象) 


1、网络中设备的标识
2、不易记忆,可用主机名
3、本地IP地址:127.0.0.1 主机名:Localhost。




(2)端口号(数字标识,没有必要封装成对象) 


1、用于标识进程的逻辑地址,不同进程的标识。
2、有效端口:0~65535,其中0~1024系统使用或保留端口。




(3)传输协议




1、通讯的规则。
2、常见协议:TCP,UDP。




3、网络通讯过程 


(1)找到对方 IP。 


(2)数据要发到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行了标识。为了方便称呼这个数字,叫做端口。(逻辑端口) 


了解:Ping 127.0.0.1(LocalHost)可以查看网卡是否异常。 
(网络编程-IP地址) 


由于IP地址是一个复杂的事物,Java已经它封装成了对象,封装成了对象把复杂的事情简单化。 




类 InetAddress 


static InetAddress  getLocalHost()
          返回本地主机。  
 String  getHostAddress()
          返回 IP 地址字符串(以文本表现形式)。  
 String  getHostName()
          获取此 IP 地址的主机名。  
static InetAddress  getByName(String host)
          在给定主机名的情况下确定主机的 IP 地址。  




import java.net.InetAddress;
public class  Test{




public static void main(String... args) throws Exception{ 


InetAddress i = InetAddress.getLocalHost(); 


String ip = i.getHostAddress(); 


String hostName = i.getHostName(); 


//System.out.println("IP地址"+ip); 


//System.out.println("主机名"+hostName); 


InetAddress inetAddress = InetAddress.getByName("www.baidu.com"); 


System.out.println(inetAddress.getHostAddress()); 


System.out.println(inetAddress.getHostName()); 


/* 


InetAddress[] hosts = InetAddress.getAllByName("www.baidu.com"); 


for(InetAddress host :hosts ){ 


System.out.println(host.getHostAddress()); 


System.out.println(host.getHostName()); 





*/ 





}




(网络编程-UDP-TCP) 


UDP 特点:(面向无连接)(聊天)




1、将数据及源和目的封装成数据包中,不需要建立连接。(封包,无连接)
2、每个数据包的大小限制在64k内。(小数据)
3、因无连接,是不可靠协议。(不可靠,丢数据)
4、不需要建立连接,速度快。(速度快)




TCP 特点:(面向连接)(下载) 


1、建立连接,形成传输数据的通道。(传输,连接)
2、在连接中进行大数据量传输。(大数据)
3、通过三次捂手完成连接,是可靠协议。(可靠。在? 我在!我知道你在了)
4、必须建立连接,效率会稍低。(速度慢)




(网络编程-Socket)(Socket也称套接字) 


1、Socket就是为网络服务提供的一种机制。
2、通信的两端都有Socket。
3、网络通信其实就是Socket间的通信。
4、数据在两个Socket间通过IO传输。




注意:Socket可以理解为码头,有码头才有船可以对货(数据)进行装卸(读写)。 


但是由于船运输的方式不同,所以有了不同的服务方式。 


一个是UDP,另外一个是TCP。 


(网络编程-UDP传输)应用小程序 


import java.net.InetAddress;
import java.net.DatagramSocket;
import java.net.DatagramPacket;
/*
需求:




通过udp传输方式,将一段文字数据发送出去。 


思路:




1.建立udpSocket服务。 


2.提供数据,并将数据封装到数据包中。 


3.通过Socket服务的发送功能,将数据包发送出去。 


4.关闭资源。 


*/
class UdpSend{




public static void main(String...args)throws Exception{ 


//1.创建udp服务,通过DatagramSocket对象。 


DatagramSocket ds =new DatagramSocket (888); 








//2.确定数据,并封装成数据包。 


//DatagramPacket(byte[] buf, int length, InetAddress address, int port)  


byte[] buf ="黑马程序员——哥们来了".getBytes(); 


DatagramPacketdp =  


new DatagramPacket( 


buf, 


buf.length, 


InetAddress.getByName("192.168.9.101"), 


10000); 








//3.通过socket服务,将已有的数据包发送出去,通过Send方法。 


ds.send(dp); 








//4.关闭资源。 


ds.close(); 





}
/*
需求: 


定义一个应用程序,用于接收udp协议传输的数据并处理。 


思路:




1.建立udpSocket服务。 


2.建立一个数据包,用于存储监听到的端口的数据。 


把接收到的数据封装的数据包,就可以操作数据包对象, 


使用其更多的功能对接收到的数据进行更多的操作。 


3.通过Socket服务的监听功能, 


将接收到的数据存入到已经定义好的数据包中。 


4.通过数据包对象的特有功能,将这些不同的数据取出,打印在控制台上。 


5.关闭资源。 


*/
class UdpRece{






public static void main(String...args) throws Exception{ 


//1.创建udp的Socket服务,建立端点。 


DatagramSocket ds =new DatagramSocket(10000); 








//2.预定义数据包,用于存储接收数据。 


byte[] buf =new byte[1024]; 


DatagramPacket dp = new DatagramPacket(buf,buf.length); 










//3.通过服务的receive方法,将收到的数据存入到定义好的数据包中。 


ds.receive(dp); 








//4.通过数据包中的方法获取其中的数据。 


String ip = dp.getAddress().getHostAddress(); 


int port = dp.getPort(); 


String data = new String(dp.getData(),0,dp.getLength()); 


System.out.println("IP地址:"+ip+"..."+data+"...端口:"+port); 








//5.关闭资源。 


ds.close(); 





}




注意:receive方法有一个阻塞式方法,如果发送端没有进行数据传输,那么该线程就是等, 


如果有数据进行传输,那么就会接收发送端的数据并封装进数据包。 


send方法如果接收端没有开启,数据将会丢失,但是数据是已经发送出去了的,只是丢失了。 


(网络编程——UDP群聊小程序) 


import java.io.BufferedReader; 


import java.io.InputStreamReader; 


import java.net.InetAddress; 


import java.net.DatagramSocket; 


import java.net.DatagramPacket; 


public class Test { 
public static void main(String[] args) throws Exception{ 
DatagramSocket sendSocket = new DatagramSocket(); 
DatagramSocket receSocket = new DatagramSocket(10000); 
new Thread(new Send(sendSocket)).start(); 
new Thread(new Rece(receSocket)).start(); 


class Send implements Runnable{ 
private DatagramSocket ds ; 
public Send(DatagramSocket ds){ 
this.ds=ds; 

public void run(){ 
BufferedReader bufr = null; 
try{ 
String line =null; 
bufr =new BufferedReader(new InputStreamReader(System.in)); 
while((line=bufr.readLine())!=null){ 
if("over".equals(line)) 
break; 
byte[] buf = line.getBytes(); 
DatagramPacket dp = new DatagramPacket(buf, 
buf.length, 
InetAddress.getByName("192.168.9.255"), 
10000); 
ds.send(dp); 


catch(Exception e){ 
throw new RuntimeException("发送端失败"); 

finally{ 
if(bufr!=null){ 
try{ 
bufr.close(); 

catch (Exception e){ 
throw new RuntimeException("读取关闭失败"); 



ds.close(); 


class Rece implements Runnable{ 
private DatagramSocket ds ; 
public Rece(DatagramSocket ds){ 
this.ds=ds; 

public void run(){ 
try{ 
while(true){ 
byte[] buf =new byte[1024]; 
DatagramPacket dp =new DatagramPacket(buf,buf.length); 
ds.receive(dp); 
String ip = dp.getAddress().getHostAddress(); 
String data =new String(dp.getData(),0,dp.getLength()); 
System.out.println(ip+"::"+data); 


catch (Exception e){ 
throw new RuntimeException("接收端失败"); 





(网络编程-TCP传输)


1、Socket和ServerSocket。 
2、建立客户端和服务器端。 
3、建立连接后,通过Socket中的IO流进行数据的传输。 
4、关闭Socket。 
同样,客户端和服务器端是两个独立的应用程序 










/*
演示Tcp传输 


1、Tcp分客户端和服务端
2、客户端对应的是Socket,服务端对应的是ServerSocket
客户端 




通过查阅 Socket 对象,发现在该对象建立时,就可以去连接指定主机 




因为Tcp是面向连接的,所以在建立Socket服务时,就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输 




步骤: 




1、创建Socket服务,并制定要连接的主机和端口。 




需求:给服务端发送一个文本数据 


通过图例发现:服务端需要一直开着,或者关闭。那么服务器的资源可以关闭,也可以24小时开启。 


*/ 




import java.net.Socket;
import java.net.ServerSocket;
import java.io.InputStream;
import java.io.OutputStream;
class TcpClient{


public static void main(String...args) throws Exception{ 


//创建客户端的socket服务。指定目的主机和端口 


Socket s = new Socket("192.168.1.109",10003); 








//为了发送数据,应该获取socket流中的输出流。 


OutputStream out = s.getOutputStream(); 


out.write("Tcp 黑马程序员 哥们来了".getBytes()); 


s.close(); 





}
/*
需求:定义端点接收数据并打印在控制台上。




服务端:




1,建立服务端的socket服务。ServerSocket(); 


并监听一个端口。 


2,获取连接过来的客户端对象。 


通过ServerSokcet的 accept方法。没有连接就会等,所以这个方法阻塞式的。 


3,客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据。并打印在控制台。 








4,关闭服务端。(可选) 




*/
class  TcpServer{




public static void main(String... args) throws Exception{ 


//建立服务端socket服务。并监听一个端口。 


ServerSocket ss = new ServerSocket(10003); 


//通过accept方法获取连接过来的客户端对象。 


while(true){ 


Socket s = ss.accept(); 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip+".....连接成功"); 


//获取客户端发送过来的数据,那么要使用客户端对象的读取流来读取数据。 


InputStream in = s.getInputStream(); 


byte[] buf = new byte[1024]; 


int len = in.read(buf); 


System.out.println(new String(buf,0,len)); 


s.close();//关闭客户端.服务 





//ss.close();//关闭服务端资源,可选可不选 





}




(网络通讯——Tcp服务端客户端互动)


import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.ServerSocket;
/*
思路:




1.创建客户端服务。并指定需要连接的主机与端口。 


2.获取客户端中的输出流,将数据写入流中。 


3.获取客户端中的输入流,将服务端反馈的数据进行读取。 


4.关闭资源。 


*/
class Cilent{




public static void main(String...args) throws Exception{ 


Socket s = new Socket("127.0.0.1",10000); 


OutputStream out = s.getOutputStream(); 


out.write("服务端你好".getBytes()); 


InputStream in = s.getInputStream(); 


byte[]buf =new byte[1024]; 


int len = in.read(buf); 


System.out.println(new String(buf,0,len)); 


s.close(); 





}
/*
思路:




1.建立服务端服务。并监听一个端口。 


2.获取连接进来的客户端对象。 


3.获取客户端的读取流,读取客户端流中的数据。 


4.给客户端回馈一个信息,获取客户端中的输入流,将数据写入流中。 


5.关闭连接进来的客户端对象。 


6.关闭客户资源(必选)关闭服务端资源(可选) 


*/
class Server{




public static void main(String...args) throws Exception{ 


ServerSocket ss = new ServerSocket(10000); 


Socket s = ss.accept(); 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip+"...连接成功"); 


InputStream in = s.getInputStream(); 


byte[] buf = new byte[1024]; 


int len = in.read(buf); 


System.out.println(new String(buf,0,len)); 


OutputStream out = s.getOutputStream(); 


Thread.sleep(10000); 


out.write("客户端你也好".getBytes()); 


s.close();//必需的 


ss.close();//可选 





}




(网络编程——模拟一个翻译软件) 


其实这个还不是翻译软件,只是我觉得跟翻译软件类似,日后我们把数据发送到数据库,而数据库返回的应该就是翻译后的结果。 


/*


需求:建立一个文字转换服务器。
客户端给服务端发送文字,服务单会将文字转成大写在返回给客户端。
而且客户度可以不断的进行文字转换。当客户端输入over时,转换结束。




客户端:


1.建立客户端服务。并指定主机和端口。 
2.获取键盘录入。纯文本,用到字符流。 
3.获取客户端的输出流,将键盘录入的数据写入客户端的输出流中。 
4.定义循环结束标记,因为键盘录入无法停下。 
3.读取服务端反馈的数据。 
4.关闭客户端资源。 
*/
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.ServerSocket;
class TransClient {


public static void main(String...args)throws Exception{ 
Socket s = new Socket("127.0.0.1",10000); 




BufferedReader bufr = 
new BufferedReader(new InputStreamReader(System.in)); 
/* 


BufferedWriter bufout = 


new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 


*/ 


PrintWriter pw = new PrintWriter(s.getOutputStream(),true); 




BufferedReader bufin = 
new BufferedReader(new InputStreamReader(s.getInputStream())); 




String line = null; 
while((line=bufr.readLine())!=null){ 
if("over".equals(line)) 
break; 
pw.println(line); 








//bufout.write(line); 
//bufout.newLine(); 
//bufout.flush(); 
String str = bufin.readLine(); 
System.out.println(str); 

bufr.close(); 
s.close(); 

}
/*
服务端:


1.创建服务端服务。并监听一个端口 
2.获取客户端对象。 
3.读取客户端中的输入流,将数据读取出来。 
4.给客户端回馈信息,将客户端的数据进行大写转换。 
5.获取客户端的输出流,将数据发送给客户端。 
6.关闭客户端资源。关闭服务端资源。 
*/
class TransServer{


public static void main(String...args) throws Exception{ 
ServerSocket ss = new ServerSocket(10000); 
Socket s = ss.accept(); 
BufferedReader bufin = 
new BufferedReader(new InputStreamReader(s.getInputStream())); 
/* 


BufferedWriter bufout = 


new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); 


*/ 


PrintWriter pw = new PrintWriter(s.getOutputStream(),true); 








String line =null; 
while((line=bufin.readLine())!=null){ 
System.out.println(line); 




pw.println("Server:"+line.toUpperCase()); 
//bufout.write("server:"+line.toUpperCase()); 
//bufout.newLine(); 
//bufout.flush(); 

s.close(); 
ss.close(); 




/* 


键盘录入读取的标识是换行符。 


服务端停止的原来是客户端键盘录入结束,服务端读到了标记-1,所以结束。 


read方法是阻塞式的。 


accept方法也是阻塞式的。 


阻塞式的方法只要没有读到所属的数据就是等。 


*/ 


(网络编程——上传文本) 


/*
需求:
将客户端的一个文本文件上传到服务端去.


客户端:




1.建立客户端服务,并指定一个主机和端口。 


2.获取客户端的输出流对象,把数据写入流中。 


3.获取客户端的输入流,读取服务端的反馈信息。 


4.关闭资源。 


*/
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.Socket;
import java.net.ServerSocket;
class TextClient{




public static void main(String...args) throws Exception{ 


Socket s = new Socket("127.0.0.1",10000); 


BufferedReader bufr =  


new BufferedReader(new FileReader("C:\\1.txt")); 


PrintWriter out = new PrintWriter(s.getOutputStream(),true); 


String line =null; 


while((line=bufr.readLine())!=null){ 


out.println(line); 





s.shutdownOutput();//原理其实就是-1 


BufferedReader in =  


new BufferedReader(new InputStreamReader(s.getInputStream())); 


String len =null; 


while((len=in.readLine())!=null){ 


System.out.println(len); 





bufr.close(); 


s.close(); 





}
/*
服务端:




1.建立服务端服务,并监听一个端口。 


2.获取客户端对象。 


3.获取客户端输入流,将数据读取出来,并写入一个文件中,存入在D盘。 


4.获取客户端的输出流,给客户端回馈点信息。 


5.关闭资源。 


*/
class TextServer{




public static void main(String...args)throws Exception{ 


ServerSocket ss = new ServerSocket(10000); 


Socket s = ss.accept(); 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip+"....连接成功"); 


PrintWriter pw =new PrintWriter(new FileWriter("D:\\1.txt"),true); 


BufferedReader in = 


new BufferedReader(new InputStreamReader(s.getInputStream())); 


String line = null; 


while((line=in.readLine())!=null){ 


pw.println(line); 





PrintWriter out =new PrintWriter(s.getOutputStream(),true); 


out.println("上传成功"); 


pw.close(); 


s.close(); 


ss.close(); 





}




(网络编程——上传图片文件)


/*
需求:




将客户端的图片文件上传到服务端去。(并考虑多个用户同时操作的情况) 




客户端




1.创建客户端服务。并指定主机和端口。 


2.读硬盘上的图片文件。 


3.获取客户端的输出流,将图片文件写出去。 


4.定义上传结束标记。 


5.服务端给客户端反馈一个结果。 


6.关闭流资源。关闭客户端资源。关闭服务端资源。 


*/ 


import java.io.FileInputStream; 


import java.io.FileOutputStream; 


import java.io.InputStream; 


import java.io.OutputStream; 


import java.io.File; 


import java.net.Socket; 


import java.net.ServerSocket; 


class PicClient{




public static void main(String...args) throws Exception{ 


if(args.length!=1){




System.out.println("请选择一个jpg文件"); 


return; 


}




File file = new File(args[0]);




if(!file.getName().endsWith(".jpg")){




System.out.println("文件格式错误,不是jpg"); 


return ; 





if(!(file.exists() && file.isFile())){




System.out.println("该文件有问题,要么不存在,要么不是文件"); 


return ; 


}




if(file.length()>1024*1024*5){




System.out.println("文件过大,无法处理"); 


return ; 


}




Socket s = new Socket("127.0.0.1",10000); 


FileInputStream fis = new FileInputStream(file); 


OutputStream out = s.getOutputStream(); 


byte[]bufout = new byte[1024]; 


int by = 0; 


while((by=fis.read(bufout))!=-1){ 


out.write(bufout,0,by); 





s.shutdownOutput(); 


InputStream in = s.getInputStream(); 


byte[] bufin =new byte[1024]; 


int len = in.read(bufin); 


System.out.println(new String(bufin,0,len)); 


fis.close(); 


s.close(); 





}
/*
服务端:
1.创建服务端服务,并监听一个端口。
2.获取客户端对象。
3.获取客户端的输入流,将传输的数据存储到硬盘中。
4.存储成功则给客户端回馈上传成功,否则上传失败。
5.关闭流资源。关闭客户端资源。关闭服务端资源。
*/ 


class PicThread implements Runnable{ 


private Socket s; 


PicThread(Socket s){ 


this.s=s; 





public void run(){ 


String ip = s.getInetAddress().getHostAddress();
int count = 1;




try{ 


System.out.println(ip+"...连接进来了");
File file = new File("D:\\Pic\\"+ip+"("+(count)+").jpg");
while(file.exists()) 


file = new File("D:\\Pic\\"+ip+"("+(count++)+").jpg"); 




FileOutputStream fos = new FileOutputStream(file); 






InputStream in = s.getInputStream(); 






byte [] buf =new byte[1024]; 






int by = 0; 






while((by=in.read(buf))!=-1){ 






fos.write(buf,0,by); 









OutputStream out = s.getOutputStream(); 


out.write("上传成功".getBytes()); 


fos.close(); 


s.close(); 





catch(Exception e){ 


throw new RuntimeException("图片上传失败"); 








}
class PicServer{




public static void main(String...args) throws Exception{ 


ServerSocket ss = new ServerSocket(10000); 


while(true){ 


Socket s = ss.accept(); 


new Thread(new PicThread(s)).start(); 











/* 


客户端通过键盘录入用户名。 


服务端对这个用户名进行校验。 








如果该用户存在,在服务端显示xxx,已登陆。 


并在客户端显示 xxx,欢迎光临。 








如果该用户存在,在服务端显示xxx,尝试登陆。 


并在客户端显示 xxx,该用户不存在。 


最多就登录三次。 








客户端: 


1.建立客户端服务,并指定主机和端口。 


2.通过键盘录入一个用户名。最多三次输入。 


3.获取客户端输出流将键盘录入的用户名发送到服务端去。 


4.通过客户端输入流,读取服务反馈的信息,如果服务端反馈信息是 


用户成功登录,那么就退出循环。否则则继续输入。 


5.关闭资源。 


服务端: 


1.建立服务端服务,并监听一个端口。 


2.获取客户端对象。 


3.通过客户端输入流接收客户端发送过来的用户名。最多三次验证。 


4.对用户名进行验证,如果该用户名在数据库存在, 


那么给客户端回馈一个欢迎光临的信息。 


如果不存在,那么将回馈一个用户不存在的信息。 


5.关闭资源。 


*/ 


import java.io.BufferedReader; 


import java.io.FileReader; 


import java.io.InputStreamReader; 


import java.io.PrintWriter; 


import java.net.ServerSocket; 


import java.net.Socket; 


class Client { 


public static void main(String... args) throws Exception{ 








Socket s = new Socket("192.168.9.101",10047); 








BufferedReader bufr =  


new BufferedReader(new InputStreamReader(System.in)); 






PrintWriter out = new PrintWriter(s.getOutputStream(),true); 




BufferedReader bufIn = 


new BufferedReader(new InputStreamReader(s.getInputStream())); 


for (int x = 0; x < 3; x++) { 


String line = bufr.readLine(); 


if(line ==null) 


break; 


out.println(line);


String info = bufIn.readLine(); 


System.out.println("info:"+ info); 


if(info.contains("欢迎")) 


break; 





bufr.close(); 


s.close(); 








class UserThread implements Runnable { 


private Socket s; 


UserThread(Socket s) { 


this.s = s; 





public void run() { 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip +"....连接成功"); 


try{ 


for (int x = 0; x < 3; x++) { 


BufferedReader bufIn = 


new BufferedReader(new InputStreamReader(s.getInputStream())); 


String name = bufIn.readLine(); 


if(name ==null) 


break; 


BufferedReader bufr = 


new BufferedReader(new FileReader("C:\\user.txt")); 


PrintWriter out =new PrintWriter(s.getOutputStream(),true); 


String line =null; 


boolean flag = false; 


while ((line = bufr.readLine()) !=null) { 


if (line.equals(name)) { 


flag =true; 


break; 








if(flag) { 


System.out.println(name +"...已登录"); 


out.println(name + "...欢迎光临"); 


break; 


}  


else { 


System.out.println(name +"...尝试登录"); 


out.println(name + "...用户名不存在"); 




s.close(); 
}  


catch (Exception e) { 


throw new RuntimeException(ip + "校验失败"); 





class Server { 




public static void main(String... args) throws Exception { 


ServerSocket ss = new ServerSocket(10047); 


while(true) { 


Socket s = ss.accept(); 


new Thread(new UserThread(s)).start(); 











(网络通讯-浏览器交互) 


/* 


演示客户端和服务端 


客户端:浏览器 


服务端:自定义 


*/ 


import java.io.PrintWriter; 


import java.net.ServerSocket; 


public class Test{ 


public static void main(String...args) throws Exception{ 


ServerSocket ss = new ServerSocket(10005); 


while(true){ 


Socket s = ss.accept(); 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip+"...连接成功"); 


PrintWriter out =new PrintWriter(s.getOutputStream(),true); 


out.println("客户端你好"); 


s.close(); 












}




telnet 命令 相当于一个客户端 在dos命令行输出 telnet 主机IP 端口 


(网络通讯-Tomcat) 


/* 


客户端:浏览器 


服务端:Tomcat服务器 


*/ 


import java.io.PrintWriter; 


import java.net.ServerSocket;




public class Test{




public static void main(String...args) throws Exception{ 


ServerSocket ss = new ServerSocket(11000); 


while(true){ 


Socket s = ss.accept(); 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip+"...连接成功"); 


PrintWriter out =new PrintWriter(s.getOutputStream(),true); 


out.println("客户端你好"); 


s.close(); 















 




 


 


























(网络通讯——Tomcat) 


/* 


客户端:自定义 


服务端:Tomcat服务器 


获取浏览器给Tomcat服务器发送了什么请求呢? 


*/ 


import java.io.PrintWriter; 


import java.io.InputStream; 


import java.net.ServerSocket;


public class Test{ 


public static void main(String...args) throws Exception{ 


ServerSocket ss = new ServerSocket(10005); 


while(true){ 


Socket s = ss.accept(); 


String ip = s.getInetAddress().getHostAddress(); 


System.out.println(ip+"...连接成功"); 


InputStream in = e.getInputStream(); 


byte[] buf =new byte[1024]; 


int len = in.read(buf): 


System.out.println(new String(buf,0,len)); 


PrintWriter out =new PrintWriter(s.getOutputStream(),true); 


out.println("客户端你好"); 




s.close(); 

















/* 


(获取连接客户端的IP地址) 


192.168.9.101...连接成功




GET / HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gi
f, image/pjpeg, application/x-ms-xbap, */*
Accept-Language: zu,zh-CN;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.
0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Cent
er PC 6.0; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 192.168.9.101:11000
Connection: Keep-Alive




请按任意键继续. . .




*/ 












/*
自定义客户端
客户端:自定义
服务器:Tomcat
*/
import java.io.PrintWriter; 


import java.io.BufferedReader; 


import java.io.InputStreamReader; 


import java.net.Socket; 


public class Test{ 


public static void main(String...args)throws Exception{ 


Socket s = new Socket("127.0.0.1",8080); 


PrintWriter out =new PrintWriter(s.getOutputStream(),true); 


out.println("GET /Web/index.html HTTP/1.1"); 


out.println("Accept: */*"); 


out.println("Accept-Language: zh-cn"); 


out.println("Host: 192.168.9.101:11000"); 


out.println("Connection: closed"); 


out.println(); 


out.println(); 


BufferedReader bufr =  


new BufferedReader(new InputStreamReader(s.getInputStream())); 


String line =null; 
while((line=bufr.readLine())!=null){ 


System.out.println(line); 





s.close(); 





}




/*
(获取连接客户端的IP地址)
192.168.9.101...连接成功
GET / HTTP/1.1
Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gi
f, image/pjpeg, application/x-ms-xbap, */*
Accept-Language: zu,zh-CN;q=0.5
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.
0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Cent
er PC 6.0; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: 192.168.9.101:11000
Connection: Keep-Alive




请按任意键继续. . .
*/ 


 


(网络编程——自定义图形界面浏览器-Tomcat服务端) 


这里先放放。因为消息头无法去掉。等下学完URLConnection先来一个图形化界面浏览器。 


(网络编程——URL) 


地址链接是一个复杂的事物,所以Java已经把地址链接封装成URL对象,方便了我们的操作。 


我们只要操作URL对象的方法,就可以拿到URL的数据了。 


import java.net.URL;


public class Test{ 


public static void main(String...args)throws Exception{ 


URL url =new URL("http://127.0.0.1:8080/Web/index.html?姓名=黑马程序员——新长城&年龄=20"); 


String protocol = url.getProtocol(); 


String path = url.getPath(); 


String host = url.getHost(); 


int port = url.getPort();//如果不指定端口,返回的是-1 


String file = url.getFile(); 


String query = url.getQuery();//用?号隔开。获取地址栏的参数,如果多参数用&符号隔开 


//if(port==-1) 


//port=80; 


//System.out.println(protocol+"://"+host+":"+port+path); 


System.out.println(protocol); 


System.out.println(host); 


System.out.println(port); 


System.out.println(path); 


System.out.println(file); 


System.out.println(query); 


}



(网络编程——URLConnection) 


/* 


远程连接对象。 


底层封装了Socket对象,调用的是Socket对象的读取流方法。 


*/ 


import java.io.InputStream; 


import java.net.URL; 


import java.net.URLConnection; 


public class Test{ 


public static void main(String...args)throws Exception{ 


URL url =new URL("http://www.so.com/"); 


URLConnection urlconnection = url.openConnection(); 


InputStream in = urlconnection.getInputStream(); 


byte[]buf =new byte[1024]; 


int len = in.read(buf); 


System.out.println(new String(buf,0,len,"utf-8")); 





}




(网络编程——openStream) 


底层其实调用的是远程连接对象,直接调用远程连接对象的Socket流中的读取流方法。 


更加方便我们的应用。 


(网络编程——自定义图形界面浏览器-Tomcat服务端) 


现在自己去一步一步自己实现,可能晚上才发布。因为难嘛。 


import java.awt.Button; 


import java.awt.FlowLayout; 


import java.awt.Frame; 


import java.awt.TextArea; 


import java.awt.TextField; 


import java.awt.event.ActionEvent; 


import java.awt.event.ActionListener; 


import java.awt.event.WindowAdapter; 


import java.awt.event.WindowEvent; 


import java.io.InputStream; 


import java.net.URL; 


public class Test{




private Frame f; 


private TextField tf; 


private Button b; 


private TextArea ta; 


Test(){ 


init(); 





public void init(){ 


f = new Frame("MyIE"); 


tf = new TextField(70); 


b = new Button("搜索一下"); 


ta =new TextArea(25,80); 


b.setSize(20,30); 


f.setBounds(0,200,1024,500); 


f.setLayout(new FlowLayout()); 


f.add(tf); 


f.add(b); 


f.add(ta); 


myEvent(); 


f.setVisible(true); 





public void myEvent(){ 


b.addActionListener(new ActionListener(){ 


public void actionPerformed(ActionEvent e){ 


ta.setText(""); 


try{ 


URL url = new URL(tf.getText()); 


InputStream in = url.openStream(); 








byte[]buf =new byte[1024]; 


int len = in.read(buf); 


ta.setText(new String(buf,0,len,"gbk")); 











catch (Exception ex){ 


ta.setText("输入错误,请重新输入"); 








}); 


f.addWindowListener(new WindowAdapter(){ 


public void windowClosing(WindowEvent e){ 


System.exit(0); 





}); 





public static void main(String...args){ 


new Test(); 





}




/*花了15分钟,哎真累,吃饭先*/ 


(网络编程——域名解析) 








面向对象 


为什么会出现新特性呢? 




新的技术的出现就是为了解决老的问题,Java语言随着自身的不断发展,对那些不利于提高开发率的技术进行了改进。 


静态导入


静态导入可以导入静态方法,这样就不必写类名而可以直接省略类名调用静态方法了。




语法:import static 包名.类名.静态方法; 










也可以直接导入某个类中的所以静态方法。 


语法:import static 包名.类名.*; 








Java 5.0 代码示例: 


package com.itheima.day01; 


import static java.lang.Math.*; 


import static java.lang.System.out; 


public class StaticImport { 


public static void main(String[] args) { 


out.println("接近数最小值: "+floor(PI)); 


out.println("接近数最大值: "+ceil(PI)); 


out.println("2的3次幂:"+pow(2, 3)); 


out.println("四舍五入:"+round(PI)); 








好处: 


使用静态导入可以简化程序对类静态属性和方法的调用,并且简化了程序代码的书写。 




弊端: 




虽然JDK中出现了这个新特性,但是如果我们在自己的类中定义 了一个方法,与导入的类中的静态方法一样。 




那Java虚拟机怎么知道用的是那个类的方法呢?所以虽然出现了这个新特性,但是建议还是别使用。 














注意:如果将Javac设置为了Java 5.0以下,那么静态导入等JDK 1.5的特性都会报告错误。 








可变参数




可变参数的出现解决了一个方法接受的参数个数不固定的问题。 


例如: 


System.out.println(countScore(2,3,5)); 


System.out.println(countScore(1,2,3,5));   


如果使用重载的方式解决需要写多个重载的方法,可是代码过于繁杂,而使用可变参数就可以避免这种情况。   


Java 5.0 代码示例: 


package com.itheima.day1; 


public class VariableParameter { 


public static void main(String[] args) { 


System. out.println(add(1, 2)); 


System. out.println(add(1, 2, 3)); 





public static int add(int x,int... args){ 


int sum = x; 


for(int i = 0; i < args.length; i++){ 
sum += args[i]; 

return sum; 


可变参数的原理: 


调用可变参数的方法时, 编译器将自动创建一个数组保存传递给方法的可变参数。 


因此,程序员可以在方法体中以数组的形式访问可变参数可变参数只能处于参数列表的最后。 


所以一个方法最多只能有一个可变参数。 




可变参数特点与注意事项: 




1、可变参数只能出现在参数列表的最后。 




2、可变参数只能在参数中只能有一个。 




3、可变参数位于变量类型和变量名之间,前后有无空格都可以。 




4、调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数。 


增强for循环 


引入增强for循环的原因: 


在JDK 1.5 以前的版本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦! 


因此JDK 1.5 中定义了一种新的语法——增强for循环,以简化此类操作。 


语法格式: 


for(修饰符 变量类型 变量  :需迭代的数组或集合){} 


Java 5.0 代码示例: 


package com.itheima.day01; 


public classForeach { 


public static void main(String[] args) { 


int[] arr = {1, 2, 3}; 


for(final int i : arr) { 


System.out.println(i); 







注意事项: 


迭代变量必须在( )中定义! 


集合变量可以是数组或实现了Iterable接口的集合类。 








小细节:向集合中取元素时同时加元素,需要使用迭代器来完成,即需要传统的for循环。 






自动拆箱与装箱 


JDK 1.5的语法允许开发人员把一个基本数据类型直接赋给对应的包装类变量, 或者赋给 Object 类型的变量,这个过程称之为自动装箱。 


自动拆箱与自动装箱与之相反,即把包装类对象直接赋给一个对应的基本类型变量。 




典型应用: 




package com.itheima.study; 


import java.util.List; 


import java.util.ArrayList; 


public class Test{ 




public static void main(String[] args){ 




List list = new ArrayList();//因为集合中不能存储基本数据类型数据。 


list.add(1);//会自动的装箱成(new Integer(1)); 


int i = (Integer)list.get(0);//自动拆箱。 












好处:新特性的出现,程序员省去了很多不必要的麻烦,提高了开发效率。 








Java 5.0 代码示例: 


package com.itheima.day01; 


public class AutoBox { 


public static void main(String[] args) { 


Integer i1 = 127; 


Integer i2 =Integer.parseInt("127"); 


System.out.println(i1==i2); 


Integer i3 = 128; 


Integer i4 = 128; 


System.out.println(i3==i4);










byte常量池 


对于这些基本数据整数要装箱成Integer对象的时候,如果这个数据在1字节(-128 ~ 127)之内的数字,就缓存在byte常量池,下次再用到的时候,先看池子里面有没有,如果有直接从池子里面拿来用。这样节省了内存空间。 


这是一种设计模式叫做享元模式。(flyweight) 


享元模式: 


就是有很多个小的对象,他们有很多属性相同,把他们封装成一个对象,那些不同的属性,把它们变为方法的参数,称之为外部状态,那些相同的属性的称之为这个对象的内部状态。




例如,示例中的Integer对象,在-128~127范围内的Integer对象,用的频率比较高,就会作为同一个对象,因此结果为true。超出这个范围的就不是同一个对象,因此结果为false。 


享元应用:




1、Word中输入英文字母,可创建26对象。 






每个对象值是出现的位置不同(坐标),所以可用一个对象调用位置的方法。 






如,字母Q:Q.zuobiao(int x,int y),将高度重复使用的char类型的字母Q封装成一个对象使用。 






2、图标:Window下的文件夹图标,只是名称这个属性不同,包含了很多其他相同的属性,那么可以应用享元模式。 


枚举 




为什么需要枚举? 


一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值。


此类问题在JDK 1.5 以前采用自定义带有枚举功能的类解决,Java 5.0以后可以直接使用枚举予以解决。 




JDK 1.5 新增的Enum 关键字用于定义一个枚举类。 


自定义类实现枚举功能 


1、私有的构造方法。 




2、每个元素分别用一个公有的静态成员变量表示。 




3、可以自定义若干个公有方法或抽象方法。 


代码示例: 


package com.itheima.day01; 


public class WeekDay { 


private WeekDay() {} 


public static finalWeekDay SUN = new WeekDay(); 


public static final WeekDay MON = new WeekDay(); 


public WeekDay nextDay() { 


if (this == SUN) { 


return MON; 


} else { 


return SUN; 








public String toString() { 


return this == SUN ? "SUN" :"MON"; 








注意:可以采用抽象方法定义nextDay将大量的if...else语句转移到一个个独立的对象中实现。 








代码示例: 


package com.itheima.day01; 


public abstract class WeekDay { 


private WeekDay() {} 


public static final WeekDay SUN = new WeekDay() { 


public WeekDay nextDay() { 


return MON; 





}; 


public static final WeekDay MON =new WeekDay() { 


public WeekDay nextDay() { 


return MON; 





}; 


public abstract WeekDay nextDay(); 


public String toString() { 


return this == SUN ? "SUN" :"MON"; 








代码测试: 
package com.itheima.day01; 


public class WeekDayTest { 


public static void main(String[] args) { 


WeekDay Mon = WeekDay.MON; 


System.out.println(Mon); 








Java5枚举的定义 


代码示例: 


package com.itheima.day01; 


public enum WeekDay { 


SUN,MON,TUE,WED,TUR,FRI,SAT; 





注意:最后一个枚举元素后面可以加分号,也可以不加分号。










代码测试: 


package com.itheima.day01; 


public class WeekDayTest { 


public static void main(String[] args) { 


WeekDay weekDay = WeekDay.SUN; 


for(WeekDay weekday: weekDay.values()){ 


System.out.println("第一个是:"+weekday.ordinal()+" 星期:"+weekday.name()); 





WeekDay weekday = WeekDay.valueOf("SUN"); 


System.out.println(weekday); 


System.out.println(WeekDay.values().length);







}




Java中声明的枚举类,均是java.lang.Enum类的子类,它继承了Enum类的所有方法。 


常用方法: 


name() 


ordinal() 


valueOf(String name) 


values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法。 


它遍历枚举类的所有枚举值非常方便。 


实现带有构造方法的枚举 


Java 5.0 代码示例: 


package com.itheima.day01; 


public classTrafficLampTest { 


public static void main(String[] args) { 


System.out.println(TrafficLamp.YELLOW); 





public enum TrafficLamp{ 


RED(60),YELLOW(5),GREEN(30); 


private TrafficLamp(){ 


System.out.println("First"); 


System.out.println(this.name()); 





private TrafficLamp(int time){ 


System.out.println("Second"); 


try { 


Thread.sleep(time*1000); 


} catch (InterruptedException e) { 


e.printStackTrace(); 





System.out.println("等待了"+time+"秒"+this.name()); 











实现带有抽象方法的枚举 


定义枚举TrafficLamp。
实现抽象的nextTrafficLamp方法:每个元素分别是由枚举类的子类来生成的实例对象,这些子类采用类似内部类的方式进行定义。增加上表示时间的构造方法。




Java 5.0 代码示例: 


package com.itheima.day01; 


public class TrafficLampTest { 


public static void main(String[] args) { 


System.out.println(Lamp.YELLOW.nextLamp()); 





public enum Lamp{ 


RED(60){ 


public Lamp nextLamp(){ 


System.out.println("暂停60秒"); 


return YELLOW; 


}  


},YELLOW(10){ 
public Lamp nextLamp(){ 


System.out.println("等待10秒"); 


return GREEN; 


}  


},GREEN(30){ 


public Lamp nextLamp(){ 


System.out.println("放行30秒"); 


return RED; 


}  


}; 


private Lamp(int time){ 


System.out.println("先把枚举所有元素加载进内存   "+this.name()); 





public abstract Lamp nextLamp(); 






枚举类总结: 


1、枚举类是一种特殊形式的Java类。 


2、枚举类中声明的每一个枚举值代表枚举类的一个实例对象。 


3、枚举类与Java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数。 


但枚举类的构造函数必须为私有的(这点不难理解)。 


4、枚举类也可以实现接口、或继承抽象类。 


5、JDK 1.5 中扩展了switch语句,它除了可以接收int, byte, char, short,String外,还可以接收一个枚举类型。 


6、若枚举类只有一个枚举值,则可以当作单例设计模式使用。 


7、枚举类的实例变量是把所以的枚举实例都加载一次的。 


如果调用了某个枚举类,那么该枚举类先把枚举类里面的所有元素都先加载一次。 


注意: 


1、枚举只有一个成员时,就可以作为一种单例的实现方式。 


2、查看生成的class文件,可以看到内部类对应的class文件。 


也就是枚举的元素都是一个内部类实例对象。 

你可能感兴趣的:(java,eclipse,java基础,代码,黑马程序员)