javase知识点大全总结

JAVASE知识点总结

Java基础语法
1.标识符
1.在java语言中,对各种变量,方法和类等要素命名时所使用的字符序列就是标识符。
这些标识符有jdk定义好的,也有我们自己开发时候需要定义的。
2.java中标识符由26个英文字符大小写,数字0-9,符号_ $。注意:数字不能开头。
3.java中是严格区分大小写
4.在实际写程序的过程中定义标识符遵守“见名之意”.
 类名和接口的规范:
在上面的约束的命名规范的情况下,首字符要大写。如果由多个单词构成每个单词的首字符都大写。
XxxYyy
如:PersonService
 变量名和方法名:
在上面的约束的命名规范的情况下,我们遵守单词首字符不要大写,如果由多个单词构成,从第二个单词起首字符都大写。这叫驼峰模式。
xxxYyyZzz
如:personDao
 包名
在上面的约束的命名规范的情况下,都小写。
xxx.yyy.zzz
 常量
所有字符都大写,多个单词之间使用下划线来分隔。
XXX_YYY_ZZZ
2.关键字
Jdk定义的标识符就是关键字,我们不可以使用。所以我们定义标识符的时候一定要避开关键字。

3.java中的注释
注释就是给程序说明的作用,我们要养成写注释的良好习惯,增强代码的可读性。
Jvm运行时注释不会被解析。Jvm会跳过注释。
 多行注释:/…./,通常用于方法内的多行或者类的多行注释

/*
public static void main(String[] args){

	System.out.println("HelloWorld1");
	System.out.println("HelloWorld1");
	System.out.println("HelloWorld1");
	System.out.println("HelloWorld1");
	System.out.println("HelloWorld1");
	
}
*/

 单行注释语法://,注释代码中的一行,建议大家放在要注释的代码的上面
 文档注释:语法/**…*/,用于类的说明和方法的说明

/**
*这是我们第一个HelloWorld的程序
*/
class HelloWorld{

/**

*这是这是我们的主方法
*/
public static void main(String[] args){

	//输出helloWorld
	System.out.println("HelloWorld1");
	//输出helloWorld1
	System.out.println("HelloWorld1");
	
	/*
	System.out.println("HelloWorld1");
	System.out.println("HelloWorld1");
	System.out.println("HelloWorld1");
	*/
}

}
4.进制(了解)
几进制就是数字达到几就进一位。常用的进制:十进制,二进制,八进制,十六进制。
生活中十进制用的最多。
计算机中二进制用的最多。
1.进制的转换
1.十进制转成R进制
十进制转换R进制,用十进制来除以R,把余数保留下来,用得到的商再去除R再保留余数,知道商为0为止。我们所得到的余数的倒序就是转换成R进制之后的数。
把十进制转换成十进制。

							余数

10| 9527 7
10 952 2
10 95 5

			10	  9				9

把16转换成二进制的数。

							余数

2 16 0

2	  8							0
		2	4					0
		
			2     2				0

					2   1       1

结果是10000
如果要把十进制转换成其他进制同理。
2.把R进制转换成十进制
范例1:把十进制9527数转换成十进制
91000+5100+210+7
9
(10)3+5*(10)2+2*(10)1+7*(10)0=9527
范例2:把二进制10000转换成十进制
1*(2)4+0*(2)3+0*(2)2+0*(2)1+ 0*(2)0=16

总结:如果把R进制的某个数xyz转换成十进制,x*®2+y®1+z®0, 每一位的次方数是数的位数从左到右递减到0的各个数。
5.常量和变量

1.开辟内存空间(创建jvm)
2.加载数据
3.CPU提取数据运行
当数据加载到内存中时,我们按着运行期数据的是否变化把数据分成常量和变量
1常量:
数据不发生变化的量。
例如:
整数常量:24小时,一周7天,一年12月
小数:重力系数9.8, 圆周率,3.14
字符串常量:“旺财”, “小强”
字符常量:‘男’,‘a’
布尔常量:true,false
空常量:null,代表一个空的引用,可以理解占位的作用,表示不存在。
2.变量
程序运行期间可以发成变化的数据

变量的定义需要进行定义变量名字,而且还要定义变量的存储空间,而且还可以定义存储的数据类型。变量中的数据能发生变化。
常量的定义需要进行定义常量名字,而且还要定义常量的存储空间,而且还可以定义存储的数据类型。常量中的数据不能发生变化。
6.数据类型
1.基本数据类型
1.基本数据类型概述
根据不同的数据类型可以划分内存的存储的空间大小,不同的类型就是数据类型
 整数的基本类型
一个字节
1 1 1 1 1 1 1 1

byte		最小存储整数的空间		1字节
short							2字节
int								4字节
long		最大存储整数的空间		8字节

byte和short计算时产生的结果默认是int类型

 小数的基本类型
flout 4个字节
double 8个字节
如果整型数据在计算的时候结果出现了小数,结果类型默认是double

建议使用double
 字符数据类型
char 2字节
如:‘a‘,’亮‘
 布尔数据类型
boolean true false
一共8种数据类型。
2.定义变量
语法:数据类型 变量名 = 值;
我们对变量的操作:取值和存值。
class Demo1{
public static void main(String[] args){
//数据类型 变量名 = 值;
int age = 10;
System.out.println(age);
}
}

变量的定义位置:定义在方法中或者语句块中。
变量的一定要赋初始值,否则使用该变量的时候会报错的。

变量的作用范围:只在当前的大括号内有效,大括号外的所有程序不能使用该变量,所以这种变量也称为局部变量。

class Demo2{
public static void main(String[] args){
//字节数据类型
byte workYear = 10;
//短整型
short salary = 2000;
//数据类型 变量名 = 值;
int age = 30;
//长整型,在定义长长整型的数据时在值后面加上l
long empTime = 10000000l;

	//小数类型float,float类型的数值后面一定要有f
	float price = 45.6f;
	//小数类型double,建议在值的后面加d
	double totalPrice = 10000.5d;
	
	//布尔数据类型
	boolean isMarry = false;
	//字符类型
	char sex = '男';
	
	
	System.out.println("工作年限:"+workYear);
	System.out.println("月薪:"+salary);
	System.out.println("年龄:"+age);
	System.out.println("入职时长:"+empTime);
	
	System.out.println("单价:"+price);
	System.out.println("总价:"+totalPrice);
	System.out.println("是否结婚:"+isMarry);
	System.out.println("性别:"+sex);
}	

}
这八种数据类型是有默认值的。这个默认值如果在变量中不能使用的,必须是在类的属性中使用,因为类的属性可以不赋初始化值。
类型 默认值
byte 0
short 0
int 0
long 0
float 0.0
double 0.0
char ‘/u0000’
boolean False

3.基本数据类型转换
八种数据类型除了布尔类型以外都可以相互的转换。
1.自动类型转换
基本数据类型在计算的时候都会向数值范围大的方向转换
byte—short–int ----long–float—double
1.所有的byte类型和short类型和char值运算的时候都会提供成int类型。
2.如果计算中一个操作数据类型是long,另一个数的空间小于等于long,那么结果就是long
3.如果计算中一个操作数据类型是float,另一个数的空间小于等于float,那么结果就是float
4.如果计算中一个操作数据类型是double,另一个数的空间小于等于double,那么结果就是double
2.强制转换
当大容量类型的变量向小容量的类型去转换需要强制转换。
语法:(目标类型)值
//在java程序中同一个范围内变量名字不能重复
int i3 = 97;
//把int类型的数据强制转换成byte
byte b3 = (byte)i3;
//把int类型的数据强制转换成short
short s3 = (short)i3;
//把int类型的数据强制转换成char
char c3 = (char)i3;
System.out.println(b3);
System.out.println(s3);
System.out.println(c3);

	  int i4 = 200;
	  //注意如果被转换的值超过了要转换的值的最大值,转换时精度就损失了,不准确。
	  byte b4 = (byte)i4;
	  System.out.println(b4);
	  //把long类型的数据转换成int
	  long l4 = 10000l;
	  int i5 = (int)l4;
	  System.out.println(i5);  
	  //把小数float转换成整型,直接把小数舍弃(非四舍五入)
	  float f1 = 12.5f;
	  int i6 = (int)f1;
	  System.out.println(i6);
	   //把小数double转换成整型,直接把小数舍弃(非四舍五入)
	  double d1 = 15.5f;
	  int i7 = (int)d1;
	  System.out.println(i7);

思考:
byte b1 = 3,b2=4, b;
b = b1 + b2;//报错,因为byte类型计算完毕后会自动提升为int类型。
b= 4+3;//不会报错,因为int类型的常量相加只要没有达到byte的上限就可以。
2.引用数据类型
7.运算符
1.算数运算符
 四则运算:
+,-,*,/
 给数值变量自身加1或减一

class Demo4{
public static void main(String[] args){
//定义两个int类型的变量
int a = 30;
int b = 20;
System.out.println(“a+b=”+(a+b));
System.out.println(“a-b=”+(a-b));
System.out.println("ab="+(ab));
//整数之间做除法叫取整30/20=1.5,要把小数位舍弃
System.out.println(“a/b=”+(a/b));
//++, –
//a++起到了给a加1的作用
a++;
//会输出a加1之后的值
System.out.println(a);
//a–起到了给a减1的作用
a–;
//会输出a减一1之后的值
System.out.println(a);

	//如果我后++或者后--和用变量在同一句代码中使用,是先使用a变量,再做加1或者减一
	System.out.println(a--);
	System.out.println(a)
	//起到了给变量a加1的作用
	--a;
	System.out.println(a);	
	//如果我前++或者前--和用变量在同一句代码中使用,是先做加1或者减一,再使用a变量
	System.out.println(--a);
}		

}

2.赋值运算符
=,+=,-=,*=,/=, %=
=:将左边的数值赋给右边的变量
+=:int x = 2;x+=3;相当于x=x+3
class Demo5{
public static void main(String[] args){
//把20这个值赋给a变量
int a = 20;
//+=,相当于a = a + 5;
//a = a + 5;
a+=5;
System.out.println(a);
//-=,相当于a = a - 5;
a-=5;
System.out.println(a);

	//*=,相当于a = a * 5;
	a*=5;
	System.out.println(a);
	///=,相当于a = a / 5;
	a/=5;
	System.out.println(a);
	//%=,相当于a = a % 5;
	a%=5;
	System.out.println(a);
}	

}

3.比较运算符
==,!=, >, >=, <, <=
==:等于
!=:不等于

:大于
=:大于等于
<:小于
<=:小于等于
class Demo6{
public static void main(String[] args){
int a = 19;
int b = 10;
//比较运算符的结果是布尔类型true,false
System.out.println("ab:"+(ab));
System.out.println(“a!=b:”+(a!=b));
System.out.println(“a>b:”+(a>b));
System.out.println(“a<b:”+(a<b));
System.out.println(“a>=b:”+(a>=b));
System.out.println(“a<=b:”+(a<=b));
}
}

4.逻辑运算符
&,|,^, &&, ||,!
应用场景:如果某个结果需要多个条件满足或者部分条件满足的判断时使用。
&: 用于连接多个表达式的判断,true&true=true,&两边的表达式都要参与计算。
|:用于连接多个表达式的判断,false|false=false, &两边的表达式都要参与计算
短路逻辑(效率高)
&&:用于连接多个表达式的判断, true&&true=true,如果第一个表达式能决定整个表达式的结果第二个表达式就不计算了。
||:用于连接多个表达式的判断, false||false=false,如果第一个表达式能决定整个表达式的结果第二个表达式就不计算了。
^:用于连接多个表达式的判断,如果两个表达式相同就是false,不同是true,两边都参加计算 (了解)
!:取反
class Demo7{
public static void main(String[] args){
int java = 90;
int sql = 70;
//只有java和sql打分都大于90分才合格
//System.out.println(java>=90&(sql++) >= 90);
//System.out.println(java>=90|(sql++) >= 90);
//短路与,如果第一个表达式是false,后面的表达式就不需要判断了,效率高
//System.out.println(java>=90&&(sql++) >= 90);
//短路或,如果第一个表达式是true,后面的表达式就不需要判断了,效率高
//System.out.println(java>=90||(sql++) >= 90);
//异或了解
//System.out.println(java>=90^(sql++) >= 90);
//System.out.println(sql);
//如果对于表达式取反需要通过括号括上。
System.out.println(!(java > 80));
}
}

5.位运算符
<< >> >>> & | ^
在计算机中参与计算的都是二进制的数据,二进制数据分为原码,反码,补码,运算的时候都是用补码来运算。
原码 反码 补码

整数	0000 0011		0000 0011          0000 0011
负数	1000 0011		1111 1100		   1111 1101
 1111 1100
  • 0000 0001

 1111 1101

<<:将参与运算的二进制数据向左移动,在低位产生的空位用0来做补齐。
整数3二进制的形式
0 0 0 0 0 0 1 1
整数3二进制左移2位
0 0 0 0 1 1 0 0
 >>将参与运算的二进制数据向右移动,在高位产生的空位如果高位是0那么就用0来做补齐,如果高位是1就用1来补齐。也就是说右移是带着符号位移动
整数3二进制的形式
0 0 0 0 0 0 1 1
右移2位
0 0 0 0 0 0 0 0
如果是负数-3右移2位
1 1 1 1 1 1 0 1
向右移动2位
1 1 1 1 1 1 1 1

 >>>:无符号右移,将参与运算的数据向右移动,在高位所产生的空位0补齐。
3二进制数
0 0 0 0 0 0 0 0
如果是负数-3右移2位
1 1 1 1 1 1 0 1
向右移动2位
0 0 1 1 1 1 1 1
左移和右移特点:执行速度快

&:与,&不仅可以作为逻辑运算符,还可以做与运算,0相当于false,1相当于true,只有1和1与计算结果是1,其余都是0
0011
& 0101

0001
|:与,|不仅可以作为逻辑运算符,还可以做与运算,0相当于false,1相当于true,只有0和0与计算结果是0,其余都是1
0011

0101

0111
^: 异或计算,^不仅可以作为逻辑运算符,还可以做与运算,如果计算的两个数相同就是0,不同就是1
0011

0101

0110
J2SE程序的流程控制
1.判断结果
1.简单if
语法:if(条件判断表达式){
执行语句
}
如果条件判断的表达式返回值是true则可以执行if内部的语句,否则如果是false就不可以执行。
范例1:如果java考试成绩大于等于60及格
class Demo1{
public static void main(String[] args){
int score = 70;
if(score >= 60){
System.out.println(“及格”);
}
System.out.println(“程序结束”);
}
}
2.if…else
语法:if(条件判断表达式){
执行语句
}else{
执行语句
}
范例2:如果java考试成绩大于60及格,否则是不及格
class Demo1{
public static void main(String[] args){
int score = 10;
if(score >= 60){
System.out.println(“及格”);
}else{
System.out.println(“不及格”);
}
System.out.println(“程序结束”);
}
}
3.多重 if….else if…else
语法:if(条件判断表达式){
执行语句
}else if(条件表达式1){
执行语句
}else if(条件表达式2){
……
}else{
}
范例3:如果大于等于60小于等于85及格,大于等于85小于100优秀,如果等于100完美,其余的不及格。
class Demo1{
public static void main(String[] args){
int score = 100;
if(score >= 60 && score < 85){
System.out.println(“及格了”);
}else if(score >= 85 && score < 100){
System.out.println(“优秀”);
}else if(score == 100){
System.out.println(“完美”);
}else{
System.out.println(“不及格”);
}
System.out.println(“程序结束”);

}

}
范例: 如果工资大于3000D级,大于5000C级,大于7000B级,大于10000A级
通过简单if组合的形式
class Demo2{
public static void main(String[] args){
int salary = 7000;
if(salary >= 3000 && salary < 5000){
System.out.println(“D级”);
}
if(salary >= 5000 && salary < 7000){
System.out.println(“C级”);
}
if(salary >= 7000 && salary < 10000){
System.out.println(“B级”);
}
if(salary >= 10000){
System.out.println(“A级”);
}
}
}

通过多重if实现
class Demo3{
public static void main(String[] args){
int salary = 3000;
//多重if当遇到第一个满足的表达式条件时执行当前的if语句,就不会再向下去执行
if(salary >= 10000){
System.out.println(“A级”);
}else if(salary >= 7000){
System.out.println(“B级”);
}else if(salary >= 5000){
System.out.println(“C级”);
}else if(salary >= 3000){
System.out.println(“D级”);
}
}
}
2.Switch分支判断
Switch:由上到下用switch中的表达式和值进行比较,如果匹配成功就执行case后的语句,在执行break的时跳出switch,如果一个也没有匹配上就执行default默认情况。

Switch(表达式){
case 常量1:
执行语句1;
break;
case 常量2:
执行语句2;
break;
……
default:
执行语句 ;
break;
}
范例1:通过等级打印不同星
class Demo4{
public static void main(String[] args){
/***
等级1用☆
等级2用☆☆
等级3用☆☆☆
等级4用☆☆☆☆
等级4用☆☆☆☆☆
*/
int grade = 0;

	switch(grade){
		case 1:
			System.out.println("☆");
			break;
		case 2:
			System.out.println("☆☆");
			break;
		case 3:
			System.out.println("☆☆☆");
			break;
		case 4:
			System.out.println("☆☆☆☆");
			break;
		case 5:
			System.out.println("☆☆☆☆☆");
			break;
		default:
			System.out.println("输入错误");
			break;
	}
}

}
Break可以省略不会报错,如果省略就会穿透执行语句(不管是否能匹配上),知道遇到一个break才会跳出,所以我们不建议省略break。
在jdk1.7之前,swtich的表达式只能是byte, short, char, int,但是1.7后可以使用String
范例2:计算指定年的月中有多少天
class Demo5{

public static void main(String[] args){
	//计算每一年的每一月有几天
	int year = 2000;
	int month = 2;
	int day = 0;
	switch(month){
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			day = 31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			day = 30;
			break;
		case 2:
		if((year%400) == 0 || (year%4 == 0&& year%100 != 0)){
			day = 29;
		}else{
			day = 28;
		}
		break;
		default:
		break;	
	}
	System.out.println(year + "年"+ month+"月有"+day+"天");
}

}
注意:
Switch和多重if的区别:
If可以做等值判断也可以做区间判断。
Switch只能做等值判断,不能做区间判断
3.三元运算符
语法:表达式1 关系运算符 表达式2?表达式3:表达式4
?前面的表达式2如果运算的结果是true,整个表达式的结果就是表达式3
?前面的表达式2如果运算的结果是false,整个表达式的结果就是表达式4
注意:三元运算符适合两个值的判断
class Demo6{
public static void main(String[] args){
//如果gender=1我们genderText就是男,如果gender=2那么genderText=女
int gender = 1;
char genderText = ’ ';
/*
if(gender == 1){
genderText = ‘男’;
}else if(gender == 2){
genderText = ‘女’;
}
System.out.println(genderText);
*/
//表达式1 赋值 表达式2
genderText = gender == 1?‘男’:‘女’;
System.out.println(genderText);
}
}
4.循环结构
循环:就是重复发生的过程(循环一般有重复的前提条件)。
1.While
语法:while(表达式){
循环体
}
表达式结果如果是true那么就执行循环体,如果是false就结束循环

								否




				是

范例:1
class Demo7{
public static void main(String[] args){
/*
打印1到100之间的数字
分析:
循环条件:是否完成打印100次
循环操作:输出,自增
*/

	//循环变量,计数器
	int i = 1;
	while(i <= 100){
		System.out.println(i);
			//更改循环条件
			i++;
	}	
}

}

范例:2
class Demo8{
public static void main(String[] args){
/*
需求:打印1到100之间的所有的偶数和
分析:
循环条件:判断计数器是否小于等于100
循环操作:累加偶数和,更新计数器
*/
//定义计数器
int i = 0;
//定义偶数和的结果变量
int sum = 0;
while(i <= 100){
//判断i是否是偶数
if(i%2 == 0){
//累加偶数
sum += i;
}
//更新计数器
i++;
}
System.out.println(sum);
}
}

2.do…while
语法:do{
循环体
}while(表达式)
注意:do…while和while,前者是先执行循环体,后者是先判断在执行循环体。

范例1:
class Demo9{
public static void main(String[] args){
/*
需求:打印100到1000之间的所有水仙花数。
234
分析:
循环条件:判断计数器是大于等于100小于1000
循环操作:更新计数器,判断是否是水仙花数。
/
int i = 100;
do{
//获得个位数
int g = i%10;
//获得十位数
int s = i/10%10;
//获得百位数
int b = i/100;
//判断是否是水仙花数
if((g
gg + sss + bb*b) == i){
System.out.println(i);
}
i++;

	}while(i < 1000);	
}

}

范例2:
class Demo10{
public static void main(String[] args){
/*
需求:打印100到1000之间的所有夹心饼数。
如:191,838
分析:
循环条件:判断计数器是大于等于100小于1000
循环操作:更新计数器,判断是否是夹心饼干
*/
int i = 100;
do{
//获得个位数
int g = i%10;
//获得百位数
int b = i/100;
//判断是否是水仙花数
if(g == b){
System.out.println(i);
}
i++;

	}while(i < 1000);
}

}

3.for
语法:for(表达式1; 表达式2; 表达式3){
循环体
}
表达式1:计数器的初始化,它只初始化一次
表达式2:循环条件的判断,多次执行
表达式3:修改计数器,多次执行
范例1:
class Demo11{
public static void main(String[] args){
/*
需求:打印1到100之间的所有的偶数和
分析:
循环条件:判断计数器是否小于等于100
循环操作:累加偶数和,更新计数器
*/
//定义偶数和的结果变量
int sum = 0;
for(int i = 0; i <= 100; i++){
if(i%2 == 0){
sum += i;
}
}
System.out.println(sum);
}
}
范例2:打印一个5行5列的☆
class Demo12{

public static void main(String[] args){	
	/*
		需求:打印5行5列 的☆
		分析:
			我们要使用2个循环
			循环条件:判断计数器是否小于等于100
			循环操作:累加偶数和,更新计数器
	*/
	//定义偶数和的结果变量
	for(int i = 0; i < 5; i++){
		for(int j = 0; j < 5; j++){
			System.out.print("☆");
		}
		System.out.println();
	}
	
}

}

范例2:打印乘法口诀
11=1
1
2=2 22=4
1
3=3 23=6 33=9
……
class Demo13{
public static void main(String[] args){
/*
范例2:打印乘法口诀
11=1
1
2=2 22=4
1
3=3 23=6 33=9
……
*/

	for(int i = 1; i <=9; i++){
		for(int j = 1; j <= i; j++){
			System.out.print(j+"*"+i+"="+j*i+"\t");					
		}
		System.out.println();
	}	
}

}

总结:
 最重要的循环是while和for
 如果循环开始之前就能确定循环次数我们建议使用for
 如果循环次数不定建议使用while

4.break
Break用来跳出循环和switch
class Demo14{
public static void main(String[] args){
/**
需求:运动会上跑5000米,跑到第三圈时,抽筋了退赛
/
for(int i = 1; i <= 10; i++){
if(i == 3){
System.out.println(“抽筋了退出”);
//跳出循环
break;
}
System.out.println(“我跑到第”+i+“圈”);
}
}
}
5.continue
也是来控制循环,在某次循环的时候放弃,后续的接着循环。
class Demo15{
public static void main(String[] args){
/
*
需求:一周上五天班,然后我周三请假一天

	*/
	for(int i = 1; i <= 5; i++){
		if(i == 3){
			System.out.println("周三肚子疼请假");
			//跳出本次循环,接着下一次循环
			continue;
		}
		System.out.println("今天星期"+i+"上班");
	}	
}

}

J2SE函数和数组
1.函数(方法)
1.函数(方法)
方法是一段能完成独立功能的代码块。我们只需要写一次方法,可以被多次调用,提高了代码的复用性。

2.语法:
返回值类型[void] 方法名([数据类型 变量名, 数据类型1 变量名1,……]){
//方法体
[return 结果值];
}

 :后续详解
 返回值类型[void]:方法给调用者返回的数据类型,如果放飞没有返回值,我们就使用void
 方法名: 见名之意,使用驼峰模式来规范方法名:xxxYyyZzz
 参数列表:方法的参数可有可无,参数列表中可以有无数个参数,先指定参数数据类型,再指定参数的变量名,多个参数用逗号分隔。
 Return:在方法有返回值的情况,返回的具体数据。
注意:方法是定义在类里面的。

a

									b










				aa     bb

a和b叫做实参,方法参数列表中的aa和bb是形参,a,b和aa,bb的地址是不同的,只不过是通过值传递的方式放实参的值传递给形参,所以参数列表中的数据类型必须匹配,变量名可以随意。
注意:当前语句块中return 语句下不能再有代码。
如果返回值类型是void 就不需要return语句
public static void compareMax1(int aa, int bb){
if(aa > bb){
System.out.println(aa+“大”);
}else{
System.out.println(bb+“大”);
}
}

3.方法的重载
在同一个类中函数(方法)名字,参数列表不一样(1. 参数个数不一样,或者2.类型不一样),跟返回值一点关系没有。
目的:为了节约方法的功能命名和提高代码的可读性。
public static int add(int a, int b){
return a+b;
}
public static double add(int a, double b){
return a+b;
}

public static int compareMax(int aa, int bb){
if(aa > bb){
//把大的值返回去
return aa;
//System.out.println(“hh”);
}else{
return bb;
}
}
public static int compareMax(int aa, int bb, int cc){
//返回的一定aa和bb中大的数
int resultab = compareMax(aa, bb);
//拿aa和bb中大的数和cc比较
int resultabc = compareMax(resultab, cc);
return resultabc;
}

打印乘法口诀
class Demo8{
public static void main(String[] args){
print99();
}
public static void print99(){
for(int i = 1; i <= 9; i++){
for(int j = 1; j <=i; j++){
System.out.print(i+""+j+"="+ij+"\t");
}
System.out.println();
}
}
}
2. 数组
整数类型(byte,short,int,long)
数值型
浮点类型(float, double)
基本数据类型 字符型 (char)

数据类型 布尔类型(boolean)
类(class)
引用数据类型 接口(interface)

							数组([])

数组:内存中保存数据的集合。
1.数组的定义
语法:
定义1:
数据类型[] 数组名 = new 数据类型[整数];
整数:是数组的长度。

获得数组的长度使用数组的属性length。
我们通过数组的变量名(数组的整地址),通过数组的变量名加上数组的下标或者索引可以对数组的每一个值进行操作。
class Demo9{
public static void main(String[] args){
//定义了一个10个长度的int类型的数组
int[] array = new int[10];
array[0] = 12;
array[1] = 63;
array[2] = 87;
array[3] = 45;
array[4] = 52;
array[5] = 134;
array[6] = 29;
array[7] = 98;
array[8] = 13;
array[9] = 56;
//获得数组的长度
System.out.println(“数组的长度:”+array.length);
//打印数组
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
}
}
数组定义的第二种方式:
语法:数据类型[] 数组变量名 = {值1, 值2,……}
Int [] array = {12, 34, 56,……};
数组的长度由value的数量来决定
数组的定义的第三种方式:
语法:数据类型[] 数组变量名 = new 数据类型[]{值1,值2,值3,……}
数组的长度由value的数量来决定
class Demo10{
public static void main(String[] args){
//定义了一个不定长度的int类型的数组
//int[] array = {12,4,5,24,78,94};
int[] array = new int[]{12,4,5,24,78,94};
//获得数组的长度
System.out.println(“数组的长度:”+array.length);
//打印数组
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
}
}

注意:在数组的操作过程中常见的问题就是数组的越界问题
class Demo11{
public static void main(String[] args){
//定义了一个不定长度的int类型的数组
int[] array = {12,4,5,24,78,94};
//获得数组的长度
System.out.println(“数组的长度:”+array.length);
System.out.println(“打印指定数组的值:”+array[6]);
}
}

2.数组在内存中的划分
内存区分配:
栈内存:容量小,速度快,数据的生命周期短,先进后出,保存局部变量(函数里面的变量,语句块中的变量)
堆内存:容量大,速度慢,保存引用数据类型的数据。
方法区:保存所有对象的共享数据。

定义数组
int[] array = new int[]{12,4,5,24,78,94};
栈中存储堆中数组的首地址。

3.数组的常用的操作
1.遍历
把整个数组每个数都访问一遍。
public static void printArr(int[] array){
for(int i = 0; i < array.length; i++){
System.out.print(array[i]+"\t");
}
}

2.求极值
在操作数组的时候常见的错误

12 4 5 78 94 24
Max = 94
class Demo13{
public static void main(String[] args){
//定义了一个不定长度的int类型的数组
int[] array = {12,4,5,24,78,94};
//int[] array = {};
int max = getMax(array);
System.out.println(max);
}
public static int getMax(int[] array){
if(array != null && array.length != 0){
int max = array[0];
for(int i = 0; i < array.length; i++){
if(max < array[i]){
max = array[i];
}
}
return max;
}else{
return 0;
}
}
}

3.排序
冒泡排序(Bubble sort):相邻的两个数逐个的做比较,如果前一个数比后一个数小那么就交换过来,当第一轮比较完毕后最小的值一定产生在末尾。

23 25 25 25 51

25 23 23 51 25

12 12 51 23 23

7 51 12 12 12

51 7 7 7 7
class Demo14{
public static void main(String[] args){
int [] array = {23, 34, 87, 12,7, 83, 57};
bubbleSort(array);
printArr(array);
}
public static void bubbleSort(int [] array){
//比较的轮数
for(int i = 0; i < array.length - 1; i++){
//每一轮所比较的次数,因为每一轮比较时会产生一个最小值,所有每一轮比较就会少一次
for(int j = 0; j < array.length - 1 -i; j++){
//如果后一个数比前一个数大,那么就做交换
if(array[j+1] < array[j]){
//通过临时变量来存储后一个数
int temp = array[j+1];
//把后一个数换成前一个数
array[j+1] = array[j];
//再把前一个数换成后一个数
array[j] = temp;
}
}
}
}
public static void printArr(int [] array){
for(int i = 0; i < array.length; i++){
System.out.print(array[i]+"\t");
}
}
}

4.查找
1.对任意的数组查找:

class Demo15{
public static void main(String[] args){
int [] array = {23, 34, 87, 12, 7, 83, 57};
int index = getValueIndex(array, 57);
System.out.println(index);
}
public static int getValueIndex(int [] array, int value){
//定义要查找的索引
int index = -1;
//遍历数组
for(int i = 0; i < array.length; i++){
//如果找到了目标值
if(array[i] == value){
//把索引赋给结果值
index = i;
//跳出循环
break;
}
}
//返回结果
return index;
}
}
2.对有序的数组查找—二分法查找
二分法查找数据的数组是要有排序的。效率非常高。
我们要查找7

1 2 3 4 5 6 7 8 9 10

我们可以把有序的数组一分为二取到中间值
minIndex = 0;
maxIndex = length -1
midIndex = (minIndex + maxIndex)/2
如果要查找的值大于中间索引的值,那么我们就大于中间索引的半个数组中去查找,然后再在半个数组中取中间值,继续比较然后依次二分,直到找到数据为止。
class Demo16{
public static void main(String[] args){
int [] array = {1,2,3,4,5,6,7,8,9,10};
int index = getBinaryQuery(array, 3);
System.out.println(index);
}
public static int getBinaryQuery(int [] array, int value){
//定义最小的索引
int min = 0;
//定义最大索引
int max = array.length -1;
//计算中间索引
int mid = (min + max)/2;
//通过while来做二分循环
while(array[mid] != value){
//重新计算最小和最大索引
//如果要查找的值比中间小
if(array[mid] > value){
max = mid - 1;
//如果要查找的值比中间大
}else{
min = mid + 1;
}
//更新中间索引
mid = (min + max)/2;
}
return mid;
}
}

5.倒置
原数组
12 3 56 7 23 4 57
倒置后
57 4 23 7 56 3 12

1.获得数组中间的索引length/2;
2.获得中间索引前的索引的对称端的索引
Length -1 – i

class Demo17{
public static void main(String[] args){
int [] array = {1,2,3,4,5,6,7,8,9};
reversArray(array);
printArray(array);
}
public static void reversArray(int [] array){
for(int i = 0; i < array.length/2; i++){
int temp = array[i];
array[i] = array[array.length - 1- i];
array[array.length - 1 - i] = temp;
}
}
public static void printArray(int [] array){
for(int i = 0; i < array.length; i++){
System.out.print(array[i]+"\t");
}
}
}
4.二维数组
二维数组就是集合中套集合。
数据类型[][] 数组名 = new 数据类型[整数][]
注意:必须明确外围数组名
数据类型[][] 数组名 = {{值1,值2,值3},{值4,值5,值6}, ,……}
Int[][] array1 = new int[3][4];
int[][] array = {{1,2,3},{4,5,6},{8,3,6},……}

class Demo18{
public static void main(String[] args){
int [][] array = {{1,2,3,4},{5,6,7,8},{13,3,4,9}};
printArray(array);
}
public static void printArray(int [][] array){
//array.length指的是集合中有几个集合
for(int i = 0; i < array.length;i++){
for(int j = 0; j < array[i].length; j++){
System.out.print(array[i][j]+"\t");
}
System.out.println();
}
}
}
面向对象
1.面向对象概述
1.类的概念
我们把某些具有相同的属性和行为的事物抽象成一类。
狗:狗是一类,所以类是一个概念,类中的一个具体的对象如:金毛犬,牧羊犬,八哥犬,京吧犬等等。
类和对象的关系:犹如模板和样本的关系,通过一个模板可以创建多个当前模板下的样例。
注意:类是概念,对象才是真正的实例。
定义类的语法:
class 类名{
属性
方法
}

类名:首字母大写的驼峰模式XxxYyy

我们可以根据类来创建对象
创建对象的语法:类名 变量名 = new 类名();

实例代码:
class Dog{
/**
定义狗这个类的属性
/
double weight;
double height;
String name;
/
*
定义狗类的方法
/
public void protectHome(){
System.out.println(name+“在看家”);
}
public void sleep(){
System.out.println(name +“在睡觉”);
}
}
/
*
创建测试类
/
class TestClass{
public static void main(String[] args){
//创建一个Dog类的对象
Dog dog = new Dog();
//根据对象变量.属性就可以获得或者设置属性的值
dog.name = “栗子黄”;
dog.height = 0.5;
dog.weight = 50;
System.out.println(“狗的名字:”+dog.name);
System.out.println(“狗的体重:”+dog.weight);
System.out.println(“狗的身高:”+dog.height);
//通过dog对象调用它的方法
dog.protectHome();
dog.sleep();
System.out.println("-------------------------------------");
/
*
通过Dog类再创建一个狗
*/
Dog dog1 = new Dog();
dog1.name = “旺财”;
dog1.height = 0.3;
dog1.weight = 20;
System.out.println(“狗的名字:”+dog1.name);
System.out.println(“狗的体重:”+dog1.weight);
System.out.println(“狗的身高:”+dog1.height);
dog1.protectHome();
dog1.sleep();
}
}

在内存中创建对象:
对象都是存储在堆中,然后在栈中存储局部变量,这个变量所存储的值就是想要的堆内存中的地址

					dog


					dog1

当使用new 创建的两个对象时会开辟两个不同的内存空间所有他们是相互隔离的。

					dog


					dog1



					dog2

我们可以在栈内存中创建两个变量都指向都一个堆内存中的地址,所以其中一个变量修改了堆内存中的数据,另一个变量就会读取到修改后的数据。
2.成员变量和局部变量
1.局部变量
 局变量是定义在方法中或语句块中。
如:public static void printArray(int [] array){
int sum = 0;
for(int i = 0; i < array.length; i++){
sum + = i;
}
}
 作用范围:只限于所定义的大括号。
 存储的位置:存储在栈内存中。
 默认值:无,局部变量必须赋值。
 生命周期:所属的大括号结束就消失。

2.成员变量(类的属性)
 成员变量是定义在类中,也可以叫类的属性。
 作用范围:在整个类中
 存储位置:堆内存
 默认值:有
 生命周期:由jvm通过垃圾回收机制来自动回收。
3.匿名对象
class Car{
String color;
double displacement;
String brand;
public void run(){
System.out.println(brand+“车在跑”);
}
public void introduce(){
System.out.println(“我是一款”+brand+“的排量是”+displacement+“L”+color+“的车”);
}
}

class TestCar{
public static void main(String[] args){
//在堆内存中创建了一个car的对象,但是在栈内存中没有变量引用他。
new Car().brand = “兰博基尼”;
//又在内存中创建了一个匿名对象;
new Car().color = “黄色”;
new Car().introduce();
}
}

匿名对象由于没有栈中的变量来引用,所以不就就会被回收掉,所以匿名对象是无意义的。

4.面向对象的特征之封装
程序是模拟生活,万物皆对象。
目的:提高数据安全性,通过封装,可以实现对属性的访问权限控制,同时增加了程序的可维护性。
封装:
将属性私有化,使用private关键字完成属性私有化,这种属性只有本类能访问。
我们一般对每一个私有属性提供公共public的set和get这种方法供外界来访问我们的私有属性。
class Teacher{
private String name;
/**
private 修饰的属性是私有属性,这个变量只有本类能访问,private也可以作用在方法上
/
private int age;
private char gender;
/
*
通过一个public方法来访问private的属性
/
public void setAge(int a){
age = a;
}
public void setName(String n){
name = n;
}
public void setGender(char g){
gender = g;
}
/
*
通过public公共的方法来访问私有的属性
*/
public String getName(){
return name;
}
public int getAge(){
return age;
}
public char getGender(){
return gender;
}
public void teach(){
System.out.println(name+“在讲课”);
}
public void introduce(){
System.out.println(“我叫”+name+“性别”+gender+“年龄是”+age+“岁”);
}
}

class TestTeacher{
public static void main(String[] args){
Teacher t = new Teacher();
/*
t.name = “任亮”;
t.setAge(30);
t.gender = ‘男’;
*/

	t.setName("任亮");
	t.setAge(30);
	t.setGender('男');
	t.introduce();
	System.out.println(t.getName());
	System.out.println(t.getAge());
	System.out.println(t.getGender());		
}

}
5.this关键字
在每一个方法中都包含一个this关键字,代表调用当前调用方法的对象的自身。This在set方法中可以区分同名的变量,加this是成员变量,没有this就是局部变量。
class Student{
private int age;
private String name;
public void setAge(int age){
//this.name是调用当前set方法的对象的引用
this.age = age;
}
public int getAge(){
return age;
}
public void setName(String name){
//this.name是调用当前set方法的对象的引用
this.name = name;
}
public String getName(){
return name;
}
public void study(){
//代表调用当前调用方法的对象的自身
System.out.println(this);
}
public void introduce(){
System.out.println(“我的名字是”+this.name+",年龄是"+this.age);
}
}
class TestStudent{
public static void main(String[] args){
//创建学生对象
Student student = new Student();
//输出student对象在堆内存中的地址
//Student@1dd3812
//Student@1dd3812
//System.out.println(student);
//student.study();
student.setAge(25);
student.setName(“张三”);
student.introduce();
}
}

This关键字程序的内存结构流程
栈 堆

					student

方法区

第一步:运行java TestStudent时把TestStudent.class载入内存,main方法存储在方法区里面
第二步:将TestStudent的main方法压入栈内存来执行main
第三步:,先把Student.class载入到内存中,把方法存储在方法区中,在堆中创建一个Student对象,在栈中创建student的变量,把堆中对象的地址存储在student变量中。
第四步:调用setAge方法,放setAge方法压栈,把调用setAge的student变量的地址给this,然后通过this给堆中Student的对象来赋值age,set方法执行完毕,setAge方法出栈。
第五步:调用setName方法(和第四步同理).
第六步:调用introduce方法,把introduce压栈,来执行introduce通过this输出name和age,然后introduce出栈。
第七步:main方法出栈。
6.构造器
作用:创建对象,给对象赋初始值;
构造器本身是一个方法:
没有返回值,也没有void。
构造器的方法名必须和类名一致
在方法中定义要初始化的参数列表
在构造器中通过this(…)可以来调用其他的构造器,而且this必须放在方法的第一行
默认构造器,如果在类中没有带有参数的构造器,默认构造器是隐式存在的,如果类中定义了有参数的构造器,那么默认构造器就被覆盖了,如果想要使用默认构造器,只需要把它显示的定义出来即可。
创建对象时使用new
Static关键字和单例模式
1.static关键字
1.static关键字修饰在属性上
1.语法
语法:static数据类型 变量名
使用static修饰的属性我们认为是类的属性,不带static修饰的属性我们认为是对象的属性。
2.类属性访问
类的属性访问:
第一种方式:类名.类属性(推荐使用),
第二种方式:对象实例.类属性
3.应用场景
应用的场景:我们把常量一般定义成static,或者当前类创建的每一个对象都有相同的属性也可以把这种属性定义成static的
class Person{
/**
name和age都是对象属性
/
String name;
int age;
/
*
人的数量,类属性
*/
static int personNum;
//static String file_name = “struts.xml”
public void introduce(){
//通过对象实例来访问类属性
System.out.println(“我叫”+this.name+“年龄是”+this.age+“编号”+this.personNum+“报到”);
}
}
class StaticDemo{
public static void main(String [] args){
//创建一个person的实例
Person p = new Person();
//给人的数量加一
Person.personNum++;
p.name = “任亮”;
p.age = 30;
p.introduce();
//创建一个person的实例
Person p1 = new Person();
//给人的数量加一
Person.personNum++;
p1.name = “鲁达”;
p1.age = 30;
p1.introduce();
//通过类名来访问类的属性
System.out.println(“当前人数:”+Person.personNum);
//通过对象实例来访问类属性
System.out.println(“当前人数:”+p.personNum);
}
}
4.内存中的加载流程
上述代码在内存中的流程

栈内存 堆内存

					p

5.生命周期
对象属性生命周期:创建对象的时候初始化对象属性(没有类属性早),当当前对象变成匿名对象时,jvm会回收该垃圾对象,对象属性随之消失。
类属性的生命周期:当Person.class被载入内存时personNum类属性就初始化了,jvm关闭类属性就消失了
2.static关键字修饰在方法上
1.语法
语法:public static 返回值(void) 方法名(数据类型1 变量1,数据类型2 变量2,….){
方法体
[return 结果]
}

Static修饰在方法上就是类方法。
2.类方法的访问
类方法访问:
第一种方式:类名.类方法()推荐使用
第二种方式:对象实例.类方法()
3.类方法对属性的访问
 访问对象属性:
类方法是无论是通过类访问还是通过对象访问都不能直接访问对象属性的
class Demo{
int num = 50;
static int num1 = 100;
//类方法
public static void printNum(){
//System.out.println(“我是一个静态方法”);
System.out.println(num);
}
}

类方法对类属性的访问:
类方法对类属性的访问是可以的。
注意:对象方法和属性只能通过对象来调用。
类方法和类属性既可以通过类来调用也可以通过对象来调用。
4.类方法应用场景:
做工具类
做数组的工具类
class ArrayUtils{
public static void sort(int [] array){
for(int i = 0; i < array.length -1 ; i++){
for(int j = 0; j < array.length - 1 -i; j++){
if(array[j] < array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
}
public static void printArray(int [] array){
for(int i = 0; i < array.length; i++){
System.out.print(array[i]+"\t");
}
}
public static void main(String [] args){
int [] array = {97,12,190, 4, 52,98};
//ArrayUtils.printArray(array);
//ArrayUtils.sort(array);
System.out.println();
//ArrayUtils.printArray(array);
//在同一个类中可以不加类名去访问静态方法。如果是不同类之间来访问静态方法必须加类名
printArray(array);
sort(array);
System.out.println();
printArray(array);
}
}
2.单例模式
设计模式:一共有23种设计模式 设计模式就是有经验的前人通过实践总结下来被大家公认的代码设计思想。
单例模式:这种模式只能产生一个对象。
应用场景非常多:比如windows的任务管理器,回收站,java中数据库连接池,spring中bean的管理等等。
1.单例模式的创建步骤
(1)将默认的构造器私有化
(2)在类中定义一个当前类的类型的静态属性,并且创建该当前类的对象。
(3)提供一个静态的类方法来返回当前类的静态属性的对象。
懒汉模式
/**
懒汉模式
/
class Singleton{
private static Singleton s = new Singleton();
/
*
创建私有构造器
*/
private Singleton(){

}
/**
	提供一个共外界来获得当前类的一个实例的类方法
	注意:类方法所访问的类的属性一定是类属性
*/
public static Singleton getInstance(){
	return s;
}

}
class TestSingleton{
public static void main(String [] args){
Singleton s = Singleton.getInstance();
System.out.println(s);
Singleton s1 = Singleton.getInstance();
System.out.println(s1);
}
}
饿汉模式
/**
饿汉模式
/
class Singleton1{
private static Singleton1 s = null;
/
*
创建私有构造器
/
private Singleton1(){
}
/
*
提供一个共外界来获得当前类的一个实例的类方法
注意:类方法所访问的类的属性一定是类属性
*/
public static Singleton1 getInstance(){
if(s == null){
s = new Singleton1();
}
return s;
}
}
class TestSingleton1{
public static void main(String [] args){
Singleton1 s = Singleton1.getInstance();
System.out.println(s);
Singleton1 s1 = Singleton1.getInstance();
System.out.println(s1);
}
}

类的继承
1.继承
描述事物的时候,我们如果发现几个类有重复的属性和方法我们就可以采用继承的方式来设计。
1.继承语法
继承的语法:
使用extends关键字来继承
class 子类 extends 父类{
子类属性
子类方法
}
继承的特点:子类会把父类所有的属性和方法继承下来(暂时不考虑final)。

2.细节
1.如果父类中包含了某些类中的共同的属性和行为,我们可以使用继承来设计程序。
2.子类使用extends关键字继承父类的共同属性以外,子类还需要有自己特有的属性或者方法。
3.父类更通用,子类更具体。
4.子类只能获得父类中的非private的属性,如果想要继承就得提供公共的set和get的方法。 私有的方法是无法继承下来的
5.java中只能做单继承
比如:A extends B{
}
6.java支持多级继承
比如:
A extends B{

	}
	C  extends B {
	
	}

继承的好处:提高代码的复用性。
3.继承的内存结构
/**
我们创建老师的父类
*/

class Teacher{
String name;
int age;
public void sleep(){
System.out.println(this.name+“正在睡觉”);
}
}
/**
创建子类继承父类
*/
class JavaTeacher extends Teacher{

public void teachJava(){
	System.out.println(this.name+ "正在教课java");
}	

}

class PHPTeacher extends Teacher{
public void teachPHP(){
System.out.println(this.name+ “正在教课php”);
}
}
class ExtendsDemo2{
public static void main(String [] args){
JavaTeacher jt = new JavaTeacher();
//调用继承下来的set方法
jt.name = “任亮”;
jt.age = 30;
//调用本身的teach方法
jt.teachJava();
//调用继承下来的sleep方法
jt.sleep();
}
}
内存中继承执行流程:
栈 堆

					jt

方法区和数据共享区

2.super关键字
1.子类实例化的过程中父类的构造器先被调用,然后再调用子类的构造器
2.子类通过构造器实例化时要调用父类的默认构造器,是隐含的调用了super()这个方法。但是如果子类的构造器中调用了父类中的有参数的构造器,那么无参数的构造器就不会被调用了。
3.super()的调用必须要放在方法的第一行。
4.super可以表示父类的引用,我们可以使用super和this来区分父类和子类中同名的属性。在子类中访问属性的查找顺序首先在子类中查找指定的属性名字,如果在子类中没有该属性,那么就去父类中去查找该属性。方法也是一样的当子类和父类有同样的方法时通过子类调用的这个相同的方法时调用的是子类的方法。但是我们可以通过super对父类的引用来调用父类的方法。
This关键字
1.代表当前类的引用
2.可以区分同名的属性和局部变量
3.通过this可以调用同类中的构造器(this(), this(参数列表))
4.调用本类里面的属性, this.属性名,this.方法()
3.方法的重写(override)
在子类继承父类时,子类的方法和父类的方法相同(访问修饰限制符, 返回值类型, 方法名, 参数列表),方法体不同。这种子类的方法将父类的方法覆盖叫做重写。

重写和重载的区别:
重写(override):在父子类的继承中有相同的方法,唯一不同就是方法体,一般是父类的该方法满足不了子类的需求所以才发生重写。
重载(overload):重载是在同一个类中,有着相同的方法名但是参数的数据类型或者参数的个数不同这两个方法就是重载。重载的目的:节省类中的命名资源和提高代码的可读性。
4.final关键字
1.修饰在方法上
final修饰的方法不能被复写
语法:
权限修饰符 final 返回值类型 方法名(参数列表){
方法体
}

class User{
int username;
int password;
/**
final修饰的方法不能被复写
/
public final void login(int username, int password){
if(username == 111 && password == 111){
System.out.println(“登录成功”);
}else{
System.out.println(“用户名或者密码错误”);
}
}
}
class Emp extends User{
String realName;
/

final修饰的方法不能被复写
public void login(int username, int password){
System.out.println(“登录成功”);
}
*/
}
class FinalDemo{
public static void main(String [] args){
Emp s = new Emp();
s.login(111,111);
}
}

2.修饰在属性上
语法:
权限修饰符 [static] final 数据类型 属性名 = 值;
属性名:一般采用大写,多个单词使用下划线来分隔。而且这种常量多定义在接口中。

class User{
public static final int USERNAME = 111;
int password;
}
class FinalDemo1{
public static void main(String [] args){
User.USERNAME = 222;
}
}

3.修饰在类上
语法 final class 类名{
属性
方法
}
final所修饰的类是不能被继承的。
final class User{
int username;
int password;
}
class Emp extends User{
String realName;

public void login(int username, int password){
	System.out.println("登录成功");
}

}
class FinalDemo1{
public static void main(String [] args){
Emp s = new Emp();
s.login(111,111);
}
}

5.抽象类
1.抽象方法概念
当多个具体的实力类存在着共同的行为,但是有不同的表现,我们在父类继承过程中父类的方法具体实现不同确定,但是能确定的是他们都有这种行为。
我们要把这种行为方法作为抽象方法。
2.抽象语法
public abtract [返回值][void] 方法名 (参数列表); 没有方法体。如果在一个类中存在一个方法,那么这个类一定是抽象类。这个类上也要有abstract标识,
抽象类的语法:
abstract class 类名{
属性
方法
}
注意:抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类

3.抽象类的特点
1.抽象类不能被实例化。

2.抽象类必须被子类继承才能使用子类实例化。
3.继承了抽象类的非抽象类必须实现抽象类的所有抽象方法。

4.抽象类也可以继承抽象类,这样不需要实现父抽象类的方法。

5.抽象类的抽象方法不能和private,final, static共存。
private 错误

final错误

static错误

接口和多态
1.接口
什么是接口:当一个抽象类,如果抽象类中的所有方法都是抽象的,那么我们就可以把它定义为一个接口,接口是对行为的抽象。类是对属性和行为的抽象。
1.语法
interface 接口名{
方法定的定义;
….
}
2.接口的特征
1.接口中的方法的定义不需要Abstract来修饰,默认就是抽象的
2.接口是不可以实例化的,需要有类来实现接口

实现接口的语法:
class 类名	implements 接口名,接口名,…{
	//实现每一个接口中的方法
}
实现了接口的类必须实现接口中的所有方法,接口实现类的方法的权限限制修饰符一定要大于等于接口的(实现类中建议都使用public)

3.接口中的方法不能和private,static和final共存
4.在接口中可以定义属性,可以通过接口的实现类的实例来访问,还可以通过接口名来访问(推荐大家使用),接口中的属性不能修改,我们接口中的属性默认都是final static 的,通常在接口中来定义属性把它作为常量,常量的名字规范是单词大写,而且多个单词之间用下划线来分隔。比如:FILE_PATH
5.接口可以继承接口(单继承)
interface A{
public void method();
}
interface B extends A{
}
6.接口可以多实现
interface A{
public void method();
}
interface A1{

public void method();	

}
interface B extends A{
}
class Demo implements B{
public void method(){
}
}
class Demo1 implements A,A1{
public void method(){
}
}
3.接口应用
范例:使用接口方式计算圆和正方形的面积和周长。
interface CalInterface{
/*
定义圆周率
/
public static final float PI = 3.14f;
/

*定义计算面积的方法
/
public float getArea(float r);
/

*定义计算周长的方法
*/
public float getLength(float r);
}

/*
创建一个圆的类实现计算的接口
/
class Circle implements CalInterface{
public float getArea(float r){
return PI
r
r;
}
public float getLength(float r){
return 2PIr;
}
}
/*
创建一个正方形的类实现计算的接口
/
class Zfx implements CalInterface{
public float getArea(float r){
return r
r;
}
public float getLength(float r){
return 4
r;
}
}
class InterDemo3{
public static void main(String [] args){
/*
Circle circle = new Circle();
float area = circle.getArea(3f);
float length = circle.getLength(3f);
System.out.println(“半径是3的圆的面积是:”+area);
System.out.println(“半径是3的圆的周长是:”+length);
*/
Zfx z = new Zfx();
float area = z.getArea(5f);
float length = z.getLength(5f);
System.out.println(“边长是5的正方形的面积是:”+area);
System.out.println(“边长是5的正方形的周长是:”+length);
}
}
使用接口的好处:

  1. 接口定义的是一种标准,可以使我们的代码分层开发,分模块开发。
  2. 降低代码的耦合度,提高代码的可扩展性和可维护性
  3. 接口改进了单继承的局限。
    接口和抽象类的区别:
    1.接口的所有方法都是抽象的,抽象类里面的方法可以是抽象的也可以是不抽象的。
    2.接口和抽象类都不能实例化,接口需要类来实现后实例化实现类,抽象类需要类来继承然后实例化子类。
    3.抽象类智能单继承,接口也可以单继承接口,接口还可以多实现。
    4.接口中的属性是static final类型的,抽象类中的属性跟普通类中的属性没有区别。
    5.接口中的方法默认就是抽象的不需要加absract,抽象类中的抽象方法需要加Abstract关键字。
    2.多态
    1.概述
    多态就是事物具有表现多种功能的能力。
    class Teacher{
    String name;
    /**
    • 父类提供一个空实现的方法
      /
      public void teachLession(){
      }
      }
      /
      *
  • 创建JavaTeacher
    /
    class JavaTeacher extends Teacher{
    public void teachLession(){
    System.out.println(name+“在讲java多态”);
    }
    }
    /
    *
  • 创建NetTeacher
    /
    class NetTeacher extends Teacher{
    public void teachLession(){
    System.out.println(name+“在讲.Net基本语法”);
    }
    }
    class TestTeacher{
    public static void main(String [] args){
    JavaTeacher jt = new JavaTeacher();
    jt.name = “任亮”;
    jt.teachLession();
    NetTeacher nt = new NetTeacher();
    nt.name = “张三”;
    nt.teachLession();
    }
    }
    1.继承多态
    我们通常使用抽象类来抽象要使用多态的方法
    abstract class Teacher{
    String name;
    /
    *
    • 父类提供一个抽象方法让子类以多态形式体现
      /
      public abstract void teachLession();
      /
      *
    • 父类提供一个普通的共性的方法给每一个子类使用
      /
      public void sleep(){
      System.out.println(name + “在睡觉”);
      }
      }
      /
      *
  • 创建JavaTeacher
    /
    class JavaTeacher extends Teacher{
    public void teachLession(){
    System.out.println(name+“在讲java多态”);
    }
    }
    /
    *
  • 创建NetTeacher
    */
    class NetTeacher extends Teacher{
    public void teachLession(){
    System.out.println(name+“在讲.Net基本语法”);
    }
    }
    class TestTeacher1{
    public static void main(String [] args){
    JavaTeacher jt = new JavaTeacher();
    jt.name = “任亮”;
    //jt.teachLession();
    jt.sleep();
    NetTeacher nt = new NetTeacher();
    nt.name = “张三”;
    //nt.teachLession();
    nt.sleep();
    }
    }
    特点:
    1.必须要有继承关系,在抽象类中可以定义多态的抽象方法,通过子类来继承这个抽象类然后复写抽象类中的抽象方法以达到多态的效果。
    2.多态子类的实例可以赋给父类的引用

abstract class Teacher{
String name;
/**
* 父类提供一个抽象方法让子类以多态形式体现
/
public abstract void teachLession();
/
*
* 父类提供一个普通的共性的方法给每一个子类使用
/
public void sleep(){
System.out.println(name + “在睡觉”);
}
}
/
*

  • 创建JavaTeacher
    /
    class JavaTeacher extends Teacher{
    public void teachLession(){
    System.out.println(name+“在讲java多态”);
    }
    }
    /
    *
  • 创建NetTeacher
    /
    class NetTeacher extends Teacher{
    public void teachLession(){
    System.out.println(name+“在讲.Net基本语法”);
    }
    }
    /
    *
    *创建领导类

class Leader{
//如果存在着多个学科的老师,就要求领导类中有多个学科老师考察的方法
public void checkJavaTeacher(JavaTeacher jt){
System.out.println(“考察开始”);
jt.teachLession();
System.out.println(“考察结束”);
}
public void checkNetTeacher(NetTeacher nt){
System.out.println(“考察开始”);
nt.teachLession();
System.out.println(“考察结束”);
}
}
/
class Leader{
/
*
* 利用多态中子类的实例可以赋给父类的引用实现多态的程序设计
/
public void checkTeacher(Teacher t){
System.out.println(“考察开始”);
t.teachLession();
System.out.println(“考察结束”);
}
}
class TestTeacher2{
public static void main(String [] args){
/

JavaTeacher jt = new JavaTeacher();
jt.name = “任亮”;
jt.teachLession();
NetTeacher nt = new NetTeacher();
nt.name = “张三”;
nt.teachLession();
/
//子类可以转换为父类,把子类的实例赋给父类的引用
/

Teacher jt = new JavaTeacher();
jt.name = “任亮”;
jt.teachLession();
Teacher nt = new NetTeacher();
nt.name = “张三”;
nt.teachLession();
/
JavaTeacher jt = new JavaTeacher();
jt.name = “任亮”;
NetTeacher nt = new NetTeacher();
nt.name = “张三”;
Leader leader = new Leader();
//考察java老师
/

leader.checkJavaTeacher(jt);
leader.checkNetTeacher(nt);
*/
leader.checkTeacher(jt);
leader.checkTeacher(nt);
}
}
内存结构
栈 堆

						 leader

						 nt

						 jt

方法区和数据共享区

3.我们可以通过instanceof来判断当前父类的引用的实例是什么类型
class Leader{
/**
* 利用多态中子类的实例可以赋给父类的引用实现多态的程序设计
/
public void checkTeacher(Teacher t){
String teacher = null;
if(t instanceof JavaTeacher){
teacher = “java老师”;
}else{
teacher = “.Net老师”;
}
System.out.println(teacher + “考察开始”);
t.teachLession();
System.out.println(teacher +“考察结束”);
}
}
2.接口多态
接口的多态基本上和类的继承的多态一致:不同的是类的继承使用的是继承关系实现多态,接口采用实现的方式实现多态。
interface Teach{
/
*
* 父类提供一个抽象方法让子类以多态形式体现
/
public void teachLession();
}
/
*

  • 创建JavaTeacher
    /
    class JavaTeacher implements Teach{
    String name;
    public void teachLession(){
    System.out.println(name+“在讲java多态”);
    }
    }
    /
    *
  • 创建NetTeacher
    /
    class NetTeacher implements Teach{
    String name;
    public void teachLession(){
    System.out.println(name+“在讲.Net基本语法”);
    }
    }
    class Leader{
    /
    *
    • 利用多态中子类的实例可以赋给父类的引用实现多态的程序设计
      */
      public void checkTeacher(Teach t){
      String teacher = null;
      if(t instanceof JavaTeacher){
      teacher = “java老师”;
      }else{
      teacher = “.Net老师”;
      }
      System.out.println(teacher + “考察开始”);
      t.teachLession();
      System.out.println(teacher +“考察结束”);
      }

}
class TestTeacher4{
public static void main(String [] args){
JavaTeacher jt = new JavaTeacher();
jt.name = “任亮”;
NetTeacher nt = new NetTeacher();
nt.name = “张三”;
Leader leader = new Leader();
leader.checkTeacher(jt);
leader.checkTeacher(nt);
}
}
3.模板模式
第一种角色:抽象模板
定义三种方法:第一个抽象方法需要子类去实现,子类必须实现
第二个扩展方法,是一个空方法,子类可以去复写也可以不复写
第三个私有的最终方法,不可复写的
第四个模板方法,这个方法中定义了每一个方法的执行顺序和逻辑
第二种角色:具体模板要继承抽象模板
需要实现抽象模板中的抽象方法,可以扩展抽象模板中的扩展方法。
理论代码:

/**

  • 抽象模板
    /
    abstract class AbstractTemplate{
    /
    *
    在抽象模板中定义一个抽象方法,这个方法是为了让子类去实现
    /
    public abstract void abstractMethod();
    /

    定义一个回调方法,用于扩展
    /
    public void hookMethod(){
    }
    /
    • 定义抽象模板中的子类不可修改的方法
      /
      private final void concrateMehtod(){
      System.out.println(“不变而且是必须的业务逻辑”);
      }
      /
      *
    • 模板方法
      /
      public void templateMehtod(){
      abstractMethod();
      hookMethod();
      concrateMehtod();
      }
      }
      /
      *
  • 定义具体模板
    */
    class ConcrateTemplate extends AbstractTemplate{
    public void abstractMethod(){
    //写业务方法
    System.out.println(“子类的具体业务逻辑”);
    }
    public void hookMethod(){
    //扩展代码
    System.out.println(“业务逻辑扩展”);
    }
    }
    class TemplateTest{
    public static void main(String [] args){
    ConcrateTemplate ct = new ConcrateTemplate();
    ct.templateMehtod();
    }
    }

范例:计算程序的执行时间。
/**

  • 抽象模板
    /
    abstract class CalTimeTemplate{
    /
    *
    在抽象模板中定义一个抽象方法,这个方法是为了让子类去实现
    /
    public abstract void doJob();
    /

    定义一个回调方法,用于扩展
    /
    public void expandMethod(){
    System.out.println(“运行开始”);
    }
    /
    • 定义抽象模板中的子类不可修改的方法
      /
      private final long getCurrentTime(){
      return System.currentTimeMillis();
      }
      /
      *
    • 模板方法
      /
      public long templateMehtod(){
      expandMethod();
      //获得当前时间的毫秒数
      long startTime = getCurrentTime();
      doJob();
      //获得当前时间的毫秒数
      long endTime= getCurrentTime();
      return endTime - startTime;
      }
      }
      /
      *
  • 定义具体模板
    */
    class ConcrateTemplate extends CalTimeTemplate{
    public void doJob(){
    for(int i = 0; i < 5; i++){
    System.out.println(“正在执行”);
    }
    }
    }
    class TemplateTest1{
    public static void main(String [] args){
    ConcrateTemplate ct = new ConcrateTemplate();
    long times = ct.templateMehtod();
    System.out.println(“程序执行了”+times+“毫秒”);
    }
    }

JAVASE
1.API的使用
Api是我们写代码的帮助文档。后续要接触很多第三方的技术,他们都会给我们提供api,我们就必须会读懂。Jdk也给我们提供了帮助文档。
通过索引的方式来根据类名来查找类的api信息

(1)看包,如果是java.lang下的类,写代码的时候我们不用引入包。

(2)看这个指定类是具体类,抽象类,接口,并且关注开始的版本号。

(3)属性和构造器

(4)方法

再看从父类所继承下来的方法

1.Math类
class MathDemo{
public static void main(String [] args){
//Math类中的属性
System.out.println(“自然对数:”+Math.E);
System.out.println(“圆周率:”+Math.PI);
//Math类中的方法
System.out.println(“绝对值:”+Math.abs(-1.5));
//把小数去掉整数加1
System.out.println(“ceil结果:”+Math.ceil(12.1));
//把小数位舍弃
System.out.println(“floor结果:”+Math.floor(12.9));
//比较两个数的大小
System.out.println(“大的数是:”+Math.max(12.9, 27));
//比较两个数的大小
System.out.println(“小的数是:”+Math.min(12.9, 27));
//计算某个数的n次幂
System.out.println(“n次方是:”+Math.pow(3, 3));
//四舍五入
System.out.println(“四舍五入的结果是:”+Math.round(4.5));
//开平方
System.out.println(“16开平方是:”+Math.sqrt(16));
//获得从0到1的随机数包括0,不包括1
for(int i = 0 ; i < 10; i++){
System.out.println(“随机数:”+Math.random());
}
for(int i = 0 ; i < 10; i++){
System.out.println(“1-100之间随机整数数:”+(int)Math.floor(Math.random()*100));
}
}
}
2.Scanner
第一步:导入Scanner,语法:import java.util.Scanner
第二步:创建对象

第三步:使用功能
调用int nextInt(),等待我们从键盘输入一个数值。
2.内部类
1.内部类简单使用
类内部的类就是内部类。
位置:把一个类定义到另一个类中,那么内部的类就是内部类。
注意:内部类不能直接创建
创建内部类的语法:
外部类.内部类 变量名 = new 外部类对象.new内部类对象
内部类的外部类的方法如果想要访问内部类的方法,必须创建内部类的对象,根据内部类的对象来访问。
class Outer{
private int num = 10;
//内部类的定义
class Inner{
public void show(){
System.out.println(“我是内部类”);
System.out.println(“num:”+num);
}
}
/*
创建外部类的方法
/
public void method(){
//在外部类内部创建内部类对象
Inner inner = new Inner();
inner.show();
}
}
class OutDemo{
public static void main(String [] args){
//内部类不能直接创建
//Inner inner = new Inner();
//inner.show();
//创建内部类
//Outer.Inner inner = new Outer().new Inner();
//inner.show();
Outer outer = new Outer();
outer.method();
}
}
2.内部类被private来修饰
被private修饰的内部类只能在它所属的外部类中访问
class Outer{
private int num = 10;
public int getNum(){
return num;
}
public void setNum(int num){
this.num = num;
}
//内部类的定义
private class Inner{
public void show(){
System.out.println(“我是内部类”);
System.out.println(“num:”+num);
}
}
/

* 对内部类的封装,给其他的外部类提供接口来访问Inner内的方法
/
public void method(){
Inner inner = new Inner();
inner.show();
}
}
class OutDemo1{
public static void main(String [] args){
//被private修饰的内部类只能在它所属的外部类中访问
//Outer.Inner inner = new Outer().new Inner();
Outer outer = new Outer();
outer.setNum(12);
System.out.println(outer.getNum());
outer.method();
}
}
3.静态内部类
静态内部类的创建语法:
外部类名.内部类名 变量名 = new 外部类名.内部类对象
class Outer{
private static int num = 10;
/
*
定义静态内部类,它只能访问它的外部类的静态属性和静态方法
/
static class Inner{
public void show(){
System.out.println(“num:”+num);
//System.out.println(“我是内部类”);
}
/

* 静态类中创建静态方法
*/
public static void show2(){
System.out.println(“num:”+num);
}
}
}
class OutDemo2{
public static void main(String [] args){
//Outer.Inner inner = new Outer().new Inner();
//静态内部类对象创建
Outer.Inner inner = new Outer.Inner();
//根据内部类的对象来访问内部类的对象方法
inner.show();
//根据内部类的对象来访问内部类中的静态方法
inner.show2();
//根据类名来访问静态类中的静态方法
Outer.Inner.show2();
}
}
4.局部内部类(了解)
把内部类定义到方法中,局部内部类
class Outer{
private static int num = 10;
public void show(){
//把内部类定义到方法中,局部内部类
class Inner{
public void method(){
System.out.println(“num:” +num);
}
}
//创建局部内部类的对象
Inner inner = new Inner();
//调用局部内部类的方法
inner.method();
}
}
class OutDemo3{
public static void main(String [] args){
Outer outer = new Outer();
outer.show();
}
}
5.匿名内部类
什么是匿名类:没有名字的类,这种类需要在接口上实现。
匿名类和匿名内部类都需要接口或者抽象类的支持。
创建一个匿名的类的对象这个类的对象实现OuterInter的接口,在大括号中实现接口中的方法,方法调用完毕后就会被垃圾回收
interface OuterInter{
public void show();
}
class OutDemo4{
public static void main(String [] args){
//创建一个匿名的类的对象这个类的对象实现OuterInter的接口,在大括号中实现接口中的方法,方法调用完毕后就会被垃圾回收
new OuterInter(){
public void show(){
System.out.println(“show something”);
}
}.show();
//匿名类适合一次性的使用
OuterInter oi = new OuterInter(){
public void show(){
System.out.println(“show something”);
}
};
oi.show();
}
}
匿名内部类
interface OuterInter{
public void show();
}
class Outer{
public void method(){
//创建匿名内部类的对象
new OuterInter(){
public void show(){
System.out.println(“我是匿名内部类”);
}
}.show();
//创建一个匿名内部类的对象,并且把这个对象赋给接口
OuterInter oi = new OuterInter(){ //多态
public void show(){
System.out.println(“我是匿名内部类1”);
}
};
oi.show();
}
}
class OutDemo5{
public static void main(String [] args){
Outer outer = new Outer();
outer.method();

} 

}
3.包的使用
1.包的定义
包:就是文件夹
作用:对类做分类管理,可以区分同名不同包的类。
语法: package 表名(不同级别用“.”来分隔);,如 package com.rl;, 位置放置文件的有效代码第一行(注释不算)
如何编译:
Javac –d . 类文件

运行:
在类的编译的目录下使用 java 包名.类名

2.类和类之间的访问
 同一个包下的类的访问。
当前类在编译的时候它所关联的类也会被编译
在同一包下的两个类可以直接访问
ArrayTools
class ArrayTools{
public void show(){
System.out.println(“我是一个show”);
}
}

ArrayTest.java
class ArrayTest{
public static void main(String[] args){
//我们发现当前的文件中没有ArrayTools
//当前类在编译的时候它所关联的类也会被编译
//在同一包下的两个类可以直接访问
ArrayTools at = new ArrayTools();
at.show();
}
}
 不同包下的类如何访问
1.方式1:访问不同包的类在类前面加上包的全路径:如com.rl.array.ArrayTools1, 这种情况我们必须先编译com.rl.array.ArrayTools1才能编译当前ArrayTest1.
2.方式2:在使用某个包下的类时需要引入这个包的类,语法:import 包名.类名;这行代码放在package包代码行的下面,class代码行的上面

package com.rl.test;
//import com.rl.array.ArrayTools1;//引入com.rl.array.ArrayTools1这个类
import com.rl.array.*;//引入com.rl.array包下的所有类
class ArrayTest2{
public static void main(String[] args){
//在使用的类的前面加上包的路径
//这种情况我们必须先编译com.rl.array.ArrayTools1才能编译当前ArrayTest1
ArrayTools1 at = new ArrayTools1();
at.show();
}
}
4.访问权限的修饰符
1.权限修饰符可以作用在哪些概念上
访问权限的修饰符一共有四种:private, 默认, protected, public
private 默认 protected public
类(非内部类) N Y N Y
方法 Y Y Y Y
属性 Y Y Y Y
在类上如果同public来修饰,那么这个类可以被任何类所访问。类如果是默认修饰在本类中可以访问,在同一个包下的类可以访问。其余都不可以访问。
2.权限修饰符对方法和属性的控制

同类中	同一个包下	不同包子类	不同包无关类

private Y N N N
默认 Y Y N N
protected Y Y Y N
public Y Y Y Y
我们通常情况:类我们一般设置成public的,属性一般都是private, 方法一般都是public的,也有少数使用(protect,private)
5.Object类
1.Object概述
Object是所有类的根类,所有的类都是直接或者间接的去继承Object类。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

/**

  • Object的类是Student隐藏着继承的
    */
    public class Student{ //extends Object{
    private String name;
    private int age;
    public Student(){
    super();
    }
    public Student(String name, int age){
    this.name = name;
    this.age = age;
    }
    public void setName(String name){
    this.name = name;
    }
    public String getName(){
    return this.name;
    }
    public void setAge(int age){
    this.age = age;
    }
    public int getAge(){
    return this.age;
    }
    }
    class StudentDemo{
    public static void main(String[] args){
    Student s = new Student();
    System.out.println(s);//打印对象的时候,底层输出的其实是调用toString方法。
    System.out.println(s.toString());
    }
    }
    2.方法的讲解
    1.toString()方法:
    返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
    Object中的toString的实现
    Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
    获得类的名称 “@”

getClass().getName() + ‘@’ + Integer.toHexString(hashCode())

/**

  • Object的类是Student隐藏着继承的
    */
    public class Student1{ //extends Object{
    private String name;
    private int age;
    public Student1(){
    super();
    }
    public Student1(String name, int age){
    this.name = name;
    this.age = age;
    }
    public void setName(String name){
    this.name = name;
    }
    public String getName(){
    return this.name;
    }
    public void setAge(int age){
    this.age = age;
    }
    public int getAge(){
    return this.age;
    }
    }
    class StudentDemo1{
    public static void main(String[] args){
    Student1 s = new Student1();
    System.out.println(“获得当前对象的类名:”+s.getClass().getName());
    System.out.println(“获得当前对象的十进制哈希值:”+s.hashCode());
    System.out.println(“获得当前对象的十六进制哈希值:”+Integer.toHexString(s.hashCode()));
    System.out.println(s);//打印对象的时候,底层输出的其实是调用toString方法。
    System.out.println(s.toString());
    }
    }

2.getClass()
getClass()返回值是Class(类的类对象),这边的知识点我们会在反射中详细讲解。通过getClass().getName()获得对象的类名。
3.hashCode()
由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。
4. finalize()
用于垃圾回收,我们不用手动的去调用,由jvm来调用,
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
面试题:
final,finally,finalize的区别?
5. public boolean equals(Object obj)
equals用于比较两个对象是否相等
/**

  • Object的类是Student隐藏着继承的
    /
    public class Student2{ //extends Object{
    private String name;
    private int age;
    public Student2(){
    super();
    }
    public Student2(String name, int age){
    this.name = name;
    this.age = age;
    }
    public void setName(String name){
    this.name = name;
    }
    public String getName(){
    return this.name;
    }
    public void setAge(int age){
    this.age = age;
    }
    public int getAge(){
    return this.age;
    }
    /

    public String toString(){
    return “name :”+this.name+ " age:"+this.age;
    }
    /
    /
    *

    • 重写equals方法,我们认为所有的属性相等两个对象就相等
      */
      public boolean equals(Object obj){
      //判断传递过来的对象实例是否是Student2的类的对象
      if(!(obj instanceof Student2)){
      return false;
      }
      Student2 s = (Student2)obj;
      if(this.name.equals(s.name) && this.age == s.age){
      return true;
      }else{
      return false;
      }
      }
      //我们建议大家重写hashCode
      public int hashCode(){
      return 1;
      }
      }
      class StudentDemo2{
      public static void main(String[] args){
      Student2 s = new Student2();
      s.setName(“任亮”);
      s.setAge(30);
      Student2 s1 = new Student2();
      s1.setName(“任亮”);
      s1.setAge(30);

      //equals的参数类型是Object但是我们传递的是Student2,多态的应用
      System.out.println(“s和s1是否相等:”+s.equals(s1));
      Demo d = new Demo();
      System.out.println(s.equals(d));
      }
      /*
      public boolean equals(Object obj) {
      return (this == obj);
      }
      */
      }
      class Demo{
      }
      eclipse的使用和异常处理

    (1)视图,视窗
    当前是JavaEE视图

    (2)视图就是某些视窗的组合。
    A:Java视图
    B:Debug视图
    C:JavaEE视图
    (3)视图还原
    在视图操作中,我有可能有误操作。这个时候怎么办?
    Window–Reset重置视图

    (4)Package Explorer 包资源管理器(重点)

     A:该视图中显示当前工作空间中的所有项目以及项目中的文件。
        但不显示项目下bin目录中的运行文件。
     B:可以直接在该视图中创建项目,包,类,接口等。
    

    (5)Outline 大纲视窗

     A:该视图中显示当前代码视图中源文件中定义的类或者接口。
        以及定义的所有成员。
     B:当代码过长时,查找代码中的某一个类或者成员,在该视窗中
        是最方便的。
     C:在代码中出现多次的名称要同一更改,也可以在该视窗中完成。
        同时其他代码如果使用了该变量,那么也会一并改变。
    

    (6)Console 控制台视窗

     A:用于显示程序的运行结果,相当于DOS命令。
     B:如果有多个控制台同时运行。比如:服务器端和客户端。
        可以通过控制台上的小屏幕按钮进行控制台的切换。
     C:通过点击小方框,进行控制台的强制停止,相当于DOS中的Ctrl+C。
    

    (7)Hierarchy 层次视窗
    A:用于显示类之间的层次(继承)关系。
    B:在当前类上,按F4就可以切换到该视窗,并查看层次关系。
    查看原码,当前类上F3,或者Ctrl+鼠标点击

3.对工作空间进行基本配置
注意:在工作空间的设置对于该空间中的所有项目都有效。
更换了工作空间,需要重新设置。
(1)配置Java的编译和运行环境版本

	windows--perference-Java
				|--Compiler 设置成5.0以上,要和运行环境版本一致。
				|--Installed JREs:可以指定多个jre环境,但是仅有一个是当前执行的。
						   要和编译器一致,或者高于编译器版本。
	如果采用高版本编译,用低版本jre运行,会出现异常。
(2)代码视窗加上行号。
	A:首选项--常规--编辑器--文本编辑器
	B:在当前类中,左侧,右键。Show Line Numbers
(3)调整字体
	windows--perference-General--Appearance--Color and Fonts
	右边选择Java。编辑即可。
	字体选择 Courier New 比较标准,个人爱好
 
(4)取消默认注释
	在首选项设置面板中
	Java--Code Style--Code Templates
	右边选择Code,将不希望出现默认注释的代码块中的注释去掉。

4.常用的提高开发效率的操作
(1)创建面板 定义类和接口,权限,父类已经实现的接口等。

syso:然后alt+/就能出现输出语句
main:然后alt+/就能出主方法
(2)常用的快捷键 (A,E,F必须掌握)
	A:alt+/ 内容辅助键 这个功能很酷啊.
		补充类或者接口名,帮我们起变量名,new 后面直接提示等。
	B:ctrl+/ 单行注释,在按一次,取消单行注释
	C:ctrl+shift+/ 对选中的区域进行多行注释的封装
	D:ctrl+shift+\ 用于取消多行注释,只要光标在多行注释中即可
	E:ctrl+shift+o 对使用了其他包中的类或者接口进行自动导入,也可以消除没有引用的包。
	F:ctrl+shift+f 对代码进行格式化
	G:alt+上键 向上移动当前行或者选中行
	H:alt+下键 向下移动当前行或者选中行
	I:ctrl+d 删除当前行,或者删除选中行
	J:ctrl+shift+x 将选中部分的字母大写
	K:ctrl+shift+y 将选中部分的字母小写
	L:ctrl+1 光标放在编译中出现红色波浪线提示的内容上,
	   在该快捷键可以获取建议的处理方式
	M:F3 可以查看类或者方法的源码,前提是,该原码已经关联。
	N: Ctrl + Alt + 下键 拷贝一行

5.代码生成的快捷键
出现source
1:在区域中右键
2:alt+shift+s
(1)私有字段的get/set 重点
(2)构造方法
(3)重写父类方法 重点
@Override 注解 表明此方法是重写父类的.
(4)添加注释 /** 回车
6.Debug 调试程序(重点)

注释找错误
输出打印调试程序

程序不是写出来的,是改出来的.

(1)让我们调试程序更加方便
(2)想要调试,需要在程序中加入断点
(3)运行debug as,打开debug视图
(4)快捷键
	f5:跳入
	f6:跳过
	f7:跳出
	drop to frame 调到方法的第一行
(5)清除断点
	在Breakpoints视窗中清除指定断点或者所有断点。

7.包的管理
1:打jar包。
选中项目–右键–Export–Java–jar–next–自己写jar包的名字和选择路径–finish.
2:jar包的使用。
导入jar包
1:单独添加jar,
把jar复制,然后粘贴到项目路径下
一定要把jar添加至classpath路径中.
怎么添加呢?
直接把依赖包拷贝到我们的项目的src下,然后右键jar包add BuildPath
如果删除,首先remove BuildPath再删除src下的jar
8.导入已有的项目

  1. 空白区域–右键–import–General–Existing Project into Workspace–选中你的项目目录–finish—OK

  2. 删除项目中有两种。
    选中和不选中删除硬盘上的项目.

    请不要选中删除硬盘上的项目。

9.异常
在我们写程序的时候难免会出现错误,java中的异常机制为了提高我们程序的健壮性和容错性而存在。
1.异常体系
Throwable:Throwable 类是 Java 语言中所有错误或异常的超类。

1.错误
Error是throwable的子类,他是程序出现了严重的问题,这种问题程序解决不了。
如:因为内存溢出或没有可用的内存提供给垃圾回收器时,Java 虚拟机无法分配一个对象,这时抛出该异常。
错误都是以Error为结尾
package com.rl.exception;
public class ExceptionDemo {
public static void main(String[] args) {
//发生java.lang.OutOfMemoryError错误,是因为jvm的内存不足了
int [] array = new int[102410241024];
}
}
输出:
Exception in thread “main” java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at com.rl.exception.ExceptionDemo.main(ExceptionDemo.java:7)

2.异常
Exception

异常都是以Exception为结尾。
1.编译期异常
编译期的异常我们必须处理,如果不处理就会编译失败。
我们两种解决方案:抛出异常,把异常抛给调用当前方法的层
内部处理,catch来处理

除了RuntimeException都是编译期的异常。
2.运行时异常
编译的时候没有异常,但是程序执行过程中产出的异常就是运行时异常。这种异常我们需要通过程序来容错提高代码的健壮性。

package com.rl.exception;
public class ExceptionDemo1 {
public static void main(String[] args) {
int a = 20;
//抛出java.lang.ArithmeticException:
int b = 0;
System.out.println(a/b);
}
}
输出:
Exception in thread “main” java.lang.ArithmeticException: / by zero
at com.rl.exception.ExceptionDemo1.main(ExceptionDemo1.java:8)

2.异常处理
1.运行时异常处理
第一种方式是自行处理
我们通过
try{
有可能发生运行时异常的代码
}catch(异常对象){
//处理或者向外抛出
}finally{
释放资源
}
上述代码可以如下组合:
(1)try ……catch
(2)try….finally
(3)try…catch…catch
(4) try…catch…catch…finally
 Try…catch
我们通过try…catch来自己处理异常,那么程序就会走到catch代码块,处理完毕后程序会继续执行。
package com.rl.exception;
public class ExceptionDemo2 {
public static void main(String[] args) {
int a = 20;
int b = 0;
try{
//可以能发生运行时异常的代码
System.out.print(a/b);
//如果发生异常ArithmeticException就捕捉到它
}catch(ArithmeticException e){
//处理异常的代码
System.out.println(“被0整除了”);
}
System.out.println(“ccc”);
}
/public static void divide(int a, int b){
System.out.print(a/b);
}
/
}

异常中的方法:
public String getMessage() 返回此 throwable 的详细消息字符串。
public String toString() 返回此 throwable 的简短描述。结果是以下字符串的串联
public void printStackTrace()打印出异常的详细信息。
 try…catch…catch

package com.rl.exception;
public class ExceptionDemo4 {
public static void main(String[] args) {
int a = 20;
int b = 0;
int [] array = {1,2,3};
/try{
System.out.println(a/b);
System.out.println(array[2]);
}catch(ArithmeticException e){
System.out.println(“被0除”);
}catch(ArrayIndexOutOfBoundsException ae){
System.out.println(“数组越界了,请检查数组长度”);
}
/
try{
System.out.println(a/b);
System.out.println(array[3]);
}catch(RuntimeException e){
//e.printStackTrace();
if(e instanceof ArrayIndexOutOfBoundsException){
System.out.println(“数组越界异常”);
}else{
System.out.println(“被0除”);
}
}
System.out.println(“ccc”);
}
}

第二种向上抛出
如果被调用的方法发生了运行时的异常,那么如果被调用的方法不去处理(不try…catch)jvm默认就会把这个运行时的异常抛到上一层,上一层函数可以对这个异常来处理,如果上一层函数依然没办法处理那么就不处理,就会接着向上抛出,总有一层方法会处理它。
package com.rl.exception;
public class ExceptionDemo3 {
public static void main(String[] args) {
int a = 20;
int b = 0;
//在可能发生异常的代码上加try…catch快捷键 Shift+Alt+z
try {
divide(a, b);
//不会运行
System.out.println(“ccc”);
} catch (ArithmeticException e) {
//处理方案代码
System.out.println(“由经理来处理”);
}
//会运行
System.out.println(“aaa”);
}
/**
* jvm默认对运行时异常的默认处理是向上抛出
* @author renliang
* @param a
* @param b
/
public static void divide(int a, int b){
System.out.print(a/b);
// 不会运行
System.out.println(“bbb”);
}
}
/
*
由经理来处理
aaa
/
 try….finally
finally内部的代码不管是否发生异常一定会被执行,finally主要是来做一些资源的释放。
package com.rl.exception;
public class ExceptionDemo5 {
public static void main(String[] args) {
int a = 20;
int b = 0;
try{
System.out.println(a/b);
}finally{
System.out.println(“finally执行”);
}
}
}
 Try…catch…finally
/
*
* 异常处理形式的finally执行
/
try {
System.out.println(a/b);
} catch (Exception e) {
System.out.println(“被0除了”);
}finally{
System.out.println(“执行finally”);
}
注意:finally可以在return后面执行
Finally
package com.rl.exception;
public class ExceptionDemo6 {
public static void main(String[] args) {
int a = 20;
int b = 2;
//System.out.println(divide(a,b));
System.out.println(getNum());
}
public static int divide(int a, int b){
int i = 0;
try {
i = a/b;
return i;
} catch (Exception e) {
System.out.println(“发生异常”);
return i;
}finally{
//finally可以在return后面执行
System.out.println(“finally执行”);
}
}
/
*
* 容易出面试题
* @author renliang
* @return
*/
public static int getNum(){
int i = 0;
try {
i = 30;
return i;//return 后的语句 返回值再使用变量修改没有意义,修改不了返回值。
} catch (Exception e) {
i = 40;
return i;
}finally{
i = 50;
//return i;//return的语句会把上一个return给覆盖掉
//finally可以在return后面执行
//System.out.println(“finally执行”);
}
}
}

2.编译期异常处理
编译期的异常我们必须处理或者抛出,否则没有办法编译通过。
处理:
public static void method(){
try {
ServerSocket s = new ServerSocket(8888);
} catch (IOException e) {
e.printStackTrace();
}
}
抛出:在方法后面加上throws Exception
public static void method() throws IOException{
ServerSocket s = new ServerSocket(8888);
}
编译期的异常和运行时的异常的区别:
编译期异常:
我们必须要处理或者抛出,否则无法编译通过,继承于Exception的所有异常除了RuntimeException以外都是编译期的异常。
运行时异常:
运行时异常可以编译通过,它是发生在程序的运行阶段,在运行的阶段如果发生了运行时异常,如果我们当前方法不处理就会自动抛出,我们也可以手动通过代码来捕捉来处理,建议向上抛出。
3.自定义异常
在实际的项目中,我们需要跟业务相关的异常,javaAPI中是没有的,所以我们要自定义。

如:在电商系统中,在提交订单的时候如果出现了库存不足,我们要抛出自定义的异常。
自定义的异常只要继承javaAPI中的异常类即可,通常情况下我们会自定义运行时异常。
所以我们自定义异常就去继承RuntimeException。

package com.rl.exception;
/**

  • 自定义运行时异常
  • @author renliang

*/
public class StockException extends RuntimeException {
public StockException() {
super();
}
public StockException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public StockException(String message, Throwable cause) {
super(message, cause);
}
public StockException(String message) {
super(message);
}
public StockException(Throwable cause) {
super(cause);
}
}

测试:
package com.rl.exception;
public class ExceptionDemo8 {
public static void main(String[] args){
try {
submitOrder();
} catch (StockException e) {
String mess = e.getMessage();
System.out.println(“提示给用户:”+mess);
}
}
public static void submitOrder(){
//商品的库存
int stock = 0;
if(stock == 0){
throw new StockException(“库存不足”);
}
}
}
JAVASE第11天字符串
1.字符串概述
整数类型(byte,short,int,long)
数值型
浮点类型(float, double)
基本数据类型 字符型 (char)

数据类型 布尔类型(boolean)
类(class)
引用数据类型 接口(interface)

							数组([])

String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。字符串是常量;它们的值在创建之后不能更改

package com.rl.string;
public class StringDemo {
public static void main(String[] args) {
//定义一个字符类型的常量,这个常量是个对象"ren",字符串的常量需要使用""来引起来
String str = “ren”;
str += “liang”;
System.out.println(str);
}
}

栈空间 堆

					str


							数据共享区
					 str1
							数据共享区

数据共享区里面的字符串是被共享的。
2.字符串的构造器
构造方法摘要
String()
初始化一个新创建的 String 对象,使其表示一个空字符序列。
String(byte[] bytes)
通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
String(byte[] bytes, int offset, int length)
通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。
String(char[] value)
分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。
String(char[] value, int offset, int count)
分配一个新的 String,它包含取自字符数组参数一个子数组的字符。
String(String original)
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
3.面试题
String s1 = new String (“abc”);
String s2 = “abc”;
有什么区别?
前者创建了两个对象,后者创建一个对象。
== :
比较基本类型,比较值是否相同。
比较引用类型,比较地址值是否相同。
equals();
比较引用类型默认比较的是地址是否相同,对于string引用类型都会重写该方法,一个类具体比较的是什么我们就得分析源码。

S1和s2的地址是不同的,但是值是相同的
package com.rl.string;
public class StringDemo2 {

public static void main(String[] args) {
	
	String s1 = new String("abc");
	String s2 = "abc";
	System.out.println(s1 == s2);//false
	//String类对equals方法的重写就是比较字符串的值
	System.out.println(s1.equals(s2));//true
}

}

				S1

				S2
								数据共享区

字符串的比较
package com.rl.string;
public class StringDemo3 {
public static void main(String[] args) {
String s1 = new String(“renliang”);
String s2 = new String(“renliang”);
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2));//true
System.out.println("---------------------------");
String s3 = “renliang”;
String s4 = “renliang”;
System.out.println(s3 == s4);//true
System.out.println(s3.equals(s4));//true
System.out.println("---------------------------");
String s5 = “ren”;
String s6 = “liang”;
String s7 = “renliang”;
System.out.println(s7 == s5 + s6);//false变量相加产生的字符串是个新字符串,有新的地址
System.out.println(s7 == “ren”+“liang”);//true常量相加的结果会去数据共享区中去找和加之后的结果相等的字符串如果找到了就不去创建了
}
}
4.字符串的判断方法
boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。
boolean equals(Object anObject)
将此字符串与指定的对象比较。
boolean equalsIgnoreCase(String anotherString)
将此 String 与另一个 String 比较,不考虑大小写。
boolean contains(CharSequence s)
当且仅当此字符串包含指定的 char 值序列时,返回 true。
boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。
boolean isEmpty()
当且仅当 length() 为 0 时返回 true。

代码:
package com.rl.string;
public class StringDemo4 {
public static void main(String[] args) {
String s1 = “renliang”;
String s2 = “RenLiang”;
//判断字符串是否相等但是忽略大小写
System.out.println(s1.equalsIgnoreCase(s2));
String s3 = “ren”;
//判断某个字符串中是否包含另一个字符串,区分大小写
System.out.println(s1.contains(s3));
System.out.println(s2.contains(s3));
//测试此字符串是否以指定的前缀开始
System.out.println(s1.startsWith(s3));
System.out.println(s1.startsWith(“renl”));
//测试此字符串是否以指定的后缀结束
System.out.println(s1.endsWith(“ang”));
//当且仅当 length() 为 0 时返回 true。
System.out.println(s1.isEmpty());
//判断一个空字符串是否是空串
String s4 = “”;
System.out.println(s4.isEmpty());
String s5 = new String();
System.out.println(s5.isEmpty());
String s6 = null;
System.out.println(s6.isEmpty());
}
}
5.字符串的获取功能
int length()
返回此字符串的长度。
char charAt(int index)
返回指定索引处的 char 值。
int indexOf(int ch)
返回指定字符在此字符串中第一次出现处的索引
int indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。
int indexOf(String str, int fromIndex)
返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
String
substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。
String
substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。
代码:
package com.rl.string;
public class StringDemo5 {
public static void main(String[] args) {
String s1 = “hewolloworld”;
System.out.println(“获得s1的长度:”+s1.length());
char c = s1.charAt(5);
System.out.println(“获得指定索引位置的字符:”+c);
System.out.println(“获得指定的第一次出现字符的索引:”+s1.indexOf(‘h’));
System.out.println(“获得指定的第一次出现字符的索引:”+s1.indexOf(‘l’));
System.out.println(“获得指定的第一次出现字符的索引:”+s1.indexOf(‘o’));
System.out.println(“获得指定的第一次出现字符串的索引:”+s1.indexOf(“ll”));
System.out.println(“获得指定的第一次出现字符串的索引:”+s1.indexOf(“wo”));
System.out.println(“获得从某个索引器指定的第一次出现字符串的索引:”+s1.indexOf(“wo”, 0));
//所截取的字符串包括临界点
System.out.println(“字符串单端截取:”+s1.substring(3));
//注意双端字符串的截取,endIndex不包括临界点
System.out.println(“字符串双端截取:”+s1.substring(3,7));
}
}
字符串获取练习:
package com.rl.string;
import java.util.Scanner;
public class StringDemo6 {
public static void main(String[] args) {
String str = “renliang”;
//printChar(str);
Scanner sc = new Scanner(System.in);
String inputStr = sc.nextLine();
//printChar(inputStr);
countNum(inputStr);
}
/**
* 遍历一个字符串
* @author renliang
* @param str
/
public static void printChar(String str){
for(int i = 0; i < str.length(); i++){
//根据索引获得每一个字符
char c = str.charAt(i);
System.out.print(c+"\t");
}
}
/
*
* 计算一个字符串中大写字母和小写字母还有数字的数量
* char c = ch
*
* ch >= ‘A’ && ch <= ‘Z’
* ch >= ‘a’ && ch <= ‘z’
* ch >= ‘0’ && ch <= ‘9’
*
*
* @author renliang
* @param str
*/
public static void countNum(String str){
int bigChar = 0;
int smallChar = 0;
int nums = 0;
for(int i = 0; i < str.length(); i++){
char ch = str.charAt(i);
/if(ch >= 65 && ch <= 90){
bigChar++;
}else if(ch >= 97 && ch <= 122){
smallChar++;
}else if(ch >= 48 && ch <= 57){
nums++;
}
/
if(ch >= ‘A’ && ch <= ‘Z’){
bigChar++;
}else if(ch >= ‘a’ && ch <= ‘z’){
smallChar++;
}else if(ch >= ‘0’ && ch <= ‘9’){
nums++;
}
}
System.out.println(“大写字母有:”+bigChar);
System.out.println(“小写字母有:”+smallChar);
System.out.println(“数字有:”+nums);
}
}
6.字符串的转换

byte[] getBytes()
使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
char[] toCharArray()
将此字符串转换为一个新的字符数组。
static String
valueOf(boolean b)
返回 boolean 参数的字符串表示形式。
static String
valueOf(char c)
返回 char 参数的字符串表示形式。
static String
valueOf(char[] data)
返回 char 数组参数的字符串表示形式。
static String
valueOf(char[] data, int offset, int count)
返回 char 数组参数的特定子数组的字符串表示形式。
static String
valueOf(double d)
返回 double 参数的字符串表示形式。
static String
valueOf(float f)
返回 float 参数的字符串表示形式。
static String
valueOf(int i)
返回 int 参数的字符串表示形式。
static String
valueOf(long l)
返回 long 参数的字符串表示形式。
String
toUpperCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
String
toUpperCase(Locale locale)
使用给定 Locale 的规则将此 String 中的所有字符都转换为大写。
String
concat(String str)
将指定字符串连接到此字符串的结尾。

测试代码:
package com.rl.string;
public class StringDemo7 {
public static void main(String[] args) {
String str = “renliang”;
//获得字节数组
byte[] bs = str.getBytes();
for(int i = 0; i < bs.length; i++){
System.out.print(bs[i]+"\t");
}
System.out.println();
System.out.println("----------------------------------------------------------");
//获得字符数组
char[] cs = str.toCharArray();
for(int i = 0; i < cs.length; i++){
System.out.print(cs[i]+"\t");
}
System.out.println();
System.out.println("----------------------------------------------------------");
String bStr = String.valueOf(true);
System.out.println(bStr);
String cStr = String.valueOf(‘a’);
System.out.println(cStr);
char[] cs1 = {‘a’,‘b’,‘c’};
String cs1Str = String.valueOf(cs1);
System.out.println(cs1Str);
char[] cs2 = {‘a’,‘b’,‘c’,‘d’,‘e’};
//第二个参数是截取的开始索引,第三个参数是向后截取的长度
String cs2Str = String.valueOf(cs2, 2, 2);
System.out.println(cs2Str);
String dStr = String.valueOf(0.12d);
System.out.println(dStr);
String fStr = String.valueOf(0.12f);
System.out.println(fStr);
String iStr = String.valueOf(10);
System.out.println(iStr);
//数值后面加上"l"就是代表这个数是long类型
String lStr = String.valueOf(10l);
System.out.println(lStr);
//把字符串变成大写
String upperStr = str.toUpperCase();
System.out.println(upperStr);
String str2 = “RENLIANG”;
String lowerStr = str2.toLowerCase();
System.out.println(lowerStr);
String str3 = str2.concat(“helloworld”);
System.out.println(str3);
System.out.println(str2+“helloworld”);
//字符串和任何基本数据类型相加都会转换成字符串
System.out.println(“helloworld”+1);
}
}
7.其他功能
String[]
split(String regex)
根据给定正则表达式的匹配拆分此字符串。
String
replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String
replace(CharSequence target, CharSequence replacement)
使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String
trim()
返回字符串的副本,忽略前导空白和尾部空白。
代码:
package com.rl.string;
/**
*

  • @author renliang

/
public class StringDemo9 {
public static void main(String[] args) {
//String str = “10-9-7-12”;
String str = “10.9.7.12”;
//获得以"-“分隔的每一个字符串,注意对于特殊的字符的分隔要加\, 避免特殊字符
String [] strArr = str.split(”\.");
for(int i = 0; i< strArr.length; i++){
System.out.println(strArr[i]);
}
System.out.println("--------------------------");
String str1 = “helloworld”;
str1 = str1.replace(‘l’, ‘o’);
System.out.println(str1);
System.out.println("--------------------------");
//第一个参数是被替换的字符串,第二个参数是替换成的字符串
str1 = str1.replace(“owo”, “xxx”);
System.out.println(str1);
String str2 = " renliang ";
System.out.println("
"+str2+"");
str2 = str2.trim();
System.out.println("
"+str2+"*");
}
}
8.练习
package com.rl.string;
/**
*

  • @author renliang
  • 需求:找出下面字符串中li的数量
  • “liasdflihsdhllihsdflihsdfiligsdfglikhsdfklilisdflio”

*/
public class StringDemo10 {
public static void main(String[] args) {
String str = “liasdflihsdhllihsdflihsdfiligsdfglikhsdfklilisdflioli”;
int count = 0;
//获得str字符串中第一个li的索引位置,如果在一个字符串中查找指定的字符串没有找到就返回-1
String targetStr = “li”;
//获得li的长度
int liLength = targetStr.length();
//定义索引位置
int inIndex = 0;
//获得第一个li的索引
inIndex = str.indexOf(targetStr);
//如果索引不等于-1就继续查询
while(inIndex != -1){
//计数器做累加
count++;
//获得每次迭代的开始索引号
inIndex += liLength;
//获得每次迭代后的某个开始索引号后的第一个li
inIndex = str.indexOf(targetStr, inIndex);
}
System.out.println(targetStr+“的数量是:”+count);
}
}

可变字符串包装类日期
1.可变字符串
1.StringBuffer概述
StringBuffer:字符串缓冲区。
StringBuffer和String区别呢?
String一旦被创建后,值不能改变,如果参与了操作,引用发生了变化,不是在原有的字符串上操作,而是新产生了一个字符串
String s = “hello”;
s += “world”;
System.out.println(s)//helloworld
StringBuffer:是线程安全的可变字符串。
StringBuffer b = “hello”;
b += “world”;//使用hello的空间追加world,不是新创建一个字符串。
System.out.println(s)//helloworld
b追加
追加a

StringBuffer是线程安全的,效率稍低。
2.StringBuffer的构造器

StringBuffer()
构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。
StringBuffer(int capacity)
构造一个不带字符,但具有指定初始容量的字符串缓冲区。
StringBuffer(String str)
构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容。
代码:
package com.rl.sbuffer;
public class StringBufferDemo {
public static void main(String[] args) {
//创建可变字符串的对象
StringBuffer sb = new StringBuffer();
System.out.println(“可变字符串的长度是:”+sb.length()+ " 容量是:"+sb.capacity());
System.out.println(“sb:”+sb);
StringBuffer sb1 = new StringBuffer(20);
System.out.println(“可变字符串的长度是:”+sb1.length()+ " 容量是:"+sb1.capacity());
System.out.println(“sb1:”+sb1);
StringBuffer sb2 = new StringBuffer(“renliang”);
System.out.println(“可变字符串的长度是:”+sb2.length()+ " 容量是:"+sb2.capacity());
System.out.println(“sb2:”+sb2);
}
}
3StringBuffer字符串处理
 追加:
StringBuffer
append(boolean b)
Appends the string representation of the boolean argument to the sequence.
StringBuffer
append(char c)
Appends the string representation of the char argument to this sequence.
StringBuffer
append(char[] str)
Appends the string representation of the char array argument to this sequence.
StringBuffer
append(char[] str, int offset, int len)
Appends the string representation of a subarray of the char array argument to this sequence.
StringBuffer
append(double d)
Appends the string representation of the double argument to this sequence.
StringBuffer
append(float f)
Appends the string representation of the float argument to this sequence.
StringBuffer
append(int i)
Appends the string representation of the int argument to this sequence.
StringBuffer
append(long lng)
Appends the string representation of the long argument to this sequence.
StringBuffer
append(String str)
Appends the specified string to this character sequence.
StringBuffer
append(StringBuffer sb)
将指定的 StringBuffer 添加到此序列中。
 插入:
StringBuffer
insert(int offset, boolean b)
Inserts the string representation of the boolean argument into this sequence.
StringBuffer
insert(int offset, char c)
Inserts the string representation of the char argument into this sequence.
StringBuffer
insert(int offset, char[] str)
Inserts the string representation of the char array argument into this sequence.
StringBuffer
insert(int index, char[] str, int offset, int len)
Inserts the string representation of a subarray of the str array argument into this sequence.
StringBuffer
insert(int offset, double d)
Inserts the string representation of the double argument into this sequence.
StringBuffer
insert(int offset, float f)
Inserts the string representation of the float argument into this sequence.
StringBuffer
insert(int offset, int i)
Inserts the string representation of the second int argument into this sequence.
StringBuffer
insert(int offset, long l)
Inserts the string representation of the long argument into this sequence.
StringBuffer
insert(int offset, String str)
Inserts the string into this character sequence.
实例代码:
package com.rl.sbuffer;
public class StringBufferDemo1 {
public static void main(String[] args) {
//创建可变字符串的对象
StringBuffer sb = new StringBuffer();
StringBuffer sb1 = sb.append(true);//sb追加后字符串的地址不变
System.out.println(sb == sb1);//true
sb.append(‘a’);
//追加字符的数组
char[] chs = {‘b’,‘c’,‘d’};
sb.append(chs);
//追加字符数组的指定位置的和指定长度的部分
char[] chs1 = {‘l’,‘o’,‘v’,‘e’};
sb.append(chs1, 1, 3);
//对double数据类型追加
sb.append(10.19d);
//追加float类型
sb.append(12.34f);
//追加int类型
sb.append(99);
//追加long类型
sb.append(222l);
//追加String类型
sb.append(“zhangsan”);
StringBuffer sb2 = new StringBuffer(“lisi”);
sb.append(sb2);
System.out.println(sb);

	System.out.println("----------------------------");
	StringBuffer sb3 = new StringBuffer();
	sb3.append(false)
	   .append('a')
	   .append(10)
	   .append("wangwu");
	System.out.println(sb3);	
	System.out.println("------------------------------");
	StringBuffer sb4 = new StringBuffer("helloworld");
	//在指定位置插入字符串
	//sb4.insert(3, true);
	char[] chs2 = {'x','y','z'};
	//sb4.insert(3, chs2);
	sb4.insert(3, chs2, 1, 2);
	System.out.println(sb4);
}

}
 删除
StringBuffer
delete(int start, int end)
Removes the characters in a substring of this sequence.
StringBuffer
deleteCharAt(int index)
Removes the char at the specified position in this sequence.
实例代码:
package com.rl.sbuffer;
public class StringBufferDemo2 {
public static void main(String[] args) {
//创建可变字符串的对象
StringBuffer sb = new StringBuffer(“helloworld”);
//删除的索引包括开始不包括结束
sb.delete(2, 4);
System.out.println(sb);
//删除指定索引的字符
sb.deleteCharAt(4);
System.out.println(sb);
//清空缓存区
sb.delete(0, sb.length());
System.out.println(sb);
}
}

 替换
StringBuffer
replace(int start, int end, String str)
Replaces the characters in a substring of this sequence with characters in the specified String.
 字符串的反转
StringBuffer
reverse()
Causes this character sequence to be replaced by the reverse of the sequence.
 某个字符串的倒序索引
int lastIndexOf(String str)
Returns the index within this string of the rightmost occurrence of the specified substring.
int lastIndexOf(String str, int fromIndex)
Returns the index within this string of the last occurrence of the specified substring.
实例代码:
package com.rl.sbuffer;
public class StringBufferDemo3 {
public static void main(String[] args) {
//创建可变字符串的对象
StringBuffer sb = new StringBuffer(“helloworld”);
//替换指定的字符串,指定开始索引和结束索引,替换时包括开始的索引,不包括结束的索引
sb.replace(2, 4, “xxx”);
System.out.println(sb);
//可变字符串反转
sb.reverse();
System.out.println(sb);
StringBuffer sb1 = new StringBuffer(“helloworld”);
int index = sb1.indexOf(“l”);
System.out.println(index);
//从后向前数第一个字符串
int lastIndex = sb1.lastIndexOf(“l”);
System.out.println(lastIndex);
//获得从某个索引开始向前数第一个字符串
int lastIndex1 = sb1.lastIndexOf(“l”, 5);
System.out.println(lastIndex1);
}
}
2.Random随机数产生类
1.Random的构造器

构造方法摘要
Random()
创建一个新的随机数生成器。
Random(long seed)
使用单个 long 种子创建一个新的随机数生成器。
常用的方法
int nextInt()
返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。
int nextInt(int n)
返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
示例代码:
package com.rl.random;
import java.util.Random;
public class RandomDemo {
public static void main(String[] args) {
//创建随机数产生的对象
Random random = new Random();
int num = 0;
for(int i = 0; i < 10; i++){
//获得在int范围内的一个随机数
//num = random.nextInt();
//我们的随机数只能产生在100之内
num = random.nextInt(100);
System.out.println(num);
}
//创建一个以指定的数值为种子的随机数,可以生成不变的序列
Random random1 = new Random(99);
for(int i = 0; i < 10; i++){
//获得在int范围内的一个随机数
//num = random.nextInt();
//我们的随机数只能产生在100之内
num = random1.nextInt(100);
System.out.println(num);
}
}
}

3.System类
常用的属性:
static InputStream
in
“标准”输入流。
static PrintStream
out
“标准”输出流。
常用方法:
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
static long currentTimeMillis()
返回以毫秒为单位的当前时间。
static void exit(int status)
终止当前正在运行的 Java 虚拟机。
static void gc()
运行垃圾回收器。
static String
getProperty(String key)
获取指定键指示的系统属性。
实例代码:
package com.rl.system;
public class SystemDemo {
public static void main(String[] args) {
int [] arr1 = {1, 2, 3, 4, 5};
int [] arr2 = {11, 22, 33, 44, 55, 0, 0};
//第一个参数:源数组,第二个参数:要拷贝的源数组的起始索引, 第三个参数是目标数组,第四个是目标数据的起始位置,第五个参数拷贝的长度
System.arraycopy(arr1, 2, arr2, 5, 2);
for(int i = 0 ; i < arr2.length; i++){
System.out.println(arr2[i]);
}
//long timeMillis = System.currentTimeMillis();
//System.out.println("1970年1月1日距离现在 "+timeMillis+“毫秒”);
long startTime = System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTime = System.currentTimeMillis();
System.out.println(“程序运行了:”+(endTime - startTime)+“毫秒”);
//退出虚拟机
//System.exit(0);
//手动调用垃圾回收器
System.gc();
//获得系统属性
String value = System.getProperty(“java.home”);
System.out.println(value);
}
}
4.包装类
1.概述
把基本数据类型转换成类,我们使用基本数据类型做进制转换很麻烦,对于临界值也不好判断,我们的包装类提供了很多方法供我们使用,这样会方便很多。
基本数据类型 byte short int long float double char boolean
包装类 Byte Short Integer Long Float Double Character Boolean
Integer 类在对象中包装了一个基本类型 int 的值。
2.Integer的构造器
Integer(int value)
构造一个新分配的 Integer 对象,它表示指定的 int 值。
Integer(String s)
构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
3.数据转换
int或Integer转换string
第一种:
String类的类方法
static String
valueOf(int i)
返回 int 参数的字符串表示形式。
第二种Integer类里面
static String
toString(int i)
返回一个表示指定整数的 String 对象。
第三种:直接用int的值加空字符串:如100+“”

String转换int或Integer
Integer(String s)
构造一个新分配的 Integer 对象,它表示 String 参数所指示的 int 值。
static Integer
valueOf(String s)
返回保存指定的 String 的值的 Integer 对象。

static int parseInt(String s)
将字符串参数作为有符号的十进制整数进行解析。

Integer转换成字符串
static String
valueOf(Object obj)
返回 Object 参数的字符串表示形式。
注意:8种基本数据类型和其相应的包装类之间可以自动的转换(自动装箱拆箱)
package com.rl.integer;
public class IntegerDemo2 {
public static void main(String[] args) {
//int转换成String
int num = 100;
//任何基本数据类型和字符串相加都能得到字符串类型的结果
String s = num + “”;
System.out.println(s);
String s1 = String.valueOf(num);
System.out.println(s1);
String s2 = Integer.toString(num);
System.out.println(s2);
//字符串转换成int和Integer
System.out.println("---------------------------------------");
String numStr = “99”;
//字符串一定是数值形式的
Integer i = new Integer(numStr);
int intVal = i.intValue();
System.out.println(i);
System.out.println(intVal);
Integer i2 = Integer.valueOf(numStr);
int i2Val = i2.intValue();
System.out.println(i2);
System.out.println(i2Val);

	Integer i3 = Integer.parseInt(numStr);
	int i3Val = i3.intValue();
	System.out.println(i3);
	System.out.println(i3Val);
	//Integer转换String
	System.out.println("-----------------------------");
	Integer i4 = new Integer(66);
	String i4Str = String.valueOf(i4);
	System.out.println(i4Str);
	String i4Str1 = i4 +"";
	System.out.println(i4Str1);
	//同样可以使用Integer.toString(int i);来转换
	String i4Str2 = Integer.toString(i4);
	System.out.println(i4Str2);
}

}
4.自动装箱和拆箱
装箱:把int类型转换正Integer--------------》new Integer(int i)
拆箱:把Integer转换成int------------》intValue()对象方法
装箱和拆箱是不需要我们主动调用的,是jvm自动给我们完成的。

Integer数据类型的默认值:null
int数据类型的默认值:0
建议大家在实际做项目时都使用Integer数据类型
package com.rl.integer;
public class IntegerDemo3 {
public static void main(String[] args) {
//自动的装箱
Integer i = 1;
System.out.println(i);
Integer i2 = new Integer(100);
//拆箱
int i3 = i2;
System.out.println(i3);
System.out.println("--------------------------");
/Integer数据类型的默认值:null
int数据类型的默认值:0
建议大家在实际做项目时都使用Integer数据类型
/
Person p = new Person();
System.out.println(“Integer数据类型的默认值:”+p.getPersonId());
System.out.println(“int数据类型的默认值:”+p.getAge());
String str = String.valueOf(p.getPersonId());
System.out.println(str);
//出现null+100;
//java.lang.NullPointerException, 使用null值计算或者取值时就会报空指针异常。
int i1 = p.getPersonId() + 100;
System.out.println(i1);
String s = null;
//字符串在使用之前一定要做判空
//java.lang.NumberFormatException
Integer i4 = new Integer(s);
System.out.println(i4);
}
}
5.日期处理
1.Date类
1.date的构造器
构造方法摘要
Date()
分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
Date(long date)
分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。
2.date的方法
long getTime()
返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
实例代码:
package com.rl.date;
import java.util.Date;
public class DateDemo {
public static void main(String[] args) {
//创建时间对象
Date date = new Date();
System.out.println(date);
//从1970年到现在的毫秒数
long timeSeconds = System.currentTimeMillis();
Date date1 = new Date(timeSeconds);
System.out.println(date1);
long hourSeconds = 60
60
1000;
Date date2 = new Date(timeSeconds - hourSeconds);
System.out.println(date2);
//获得一个指定的日期到1970年的毫秒数
long seconds = date2.getTime();
//当前时间1个小时之前的毫秒数
System.out.println(seconds);
//当前时间的毫秒数
System.out.println(timeSeconds);
}
}
2.日期的格式化
掌握:
 日期转换String
要求我们掌握DateFormat是抽象类,我们要学习的是它的子类SimpleDateFormat
SimpleDateFormat()
用默认的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
SimpleDateFormat(String pattern)
用给定的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
掌握的方法
String
format(Date date)
将一个 Date 格式化为日期/时间字符串。

 String转换日期

Date
parse(String source)
从给定字符串的开始解析文本,以生成一个日期。
实例代码:

package com.rl.date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo {
public static void main(String[] args) {
//把时间转换成字符串
//创建时间格式化的对象
SimpleDateFormat sdf = new SimpleDateFormat();
//我们获得格式化之后的字符串
String dateStr = sdf.format(new Date());
System.out.println(dateStr);
//根据自己的定义模板来展示时间
SimpleDateFormat sdf1 = new SimpleDateFormat(“yyyy年MM月dd日 HH:mm:ss:SSS a E”);
SimpleDateFormat sdf2 = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
String dateStr1 = sdf1.format(new Date());
String dateStr2 = sdf2.format(new Date());
System.out.println(dateStr1);
System.out.println(dateStr2);
System.out.println("--------------------------------");
try {
//把字符串转换成日期,前提一定是字符串符合format的pattern
Date date = sdf2.parse(“1985-04-22 23:12:22”);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}

3.Calendar日历类
获得日历类的实例
static Calendar
getInstance()
使用默认时区和语言环境获得一个日历。
实例代码:掌握如果获得时间和设置时间
package com.rl.date;
import java.util.Calendar;
import java.util.Date;
public class CalendarDemo {
public static void main(String[] args) {
//获得日历类的一个子类
Calendar c = Calendar.getInstance();
//java.util.GregorianCalendar
/[time=1446281927642,
areFieldsSet=true,
areAllFieldsSet=true,
lenient=true,
zone=sun.util.calendar.ZoneInfo[id=“Asia/Shanghai”,
offset=28800000,dstSavings=0,useDaylight=false,
transitions=19,lastRule=null],
firstDayOfWeek=1,
minimalDaysInFirstWeek=1,
ERA=1,
YEAR=2015,
MONTH=9, //计算国内的月份需要加1
WEEK_OF_YEAR=44,
WEEK_OF_MONTH=5,
DAY_OF_MONTH=31,
DAY_OF_YEAR=304,
DAY_OF_WEEK=7, //计算国内的星期需要加1
DAY_OF_WEEK_IN_MONTH=5,
AM_PM=1,HOUR=4,
HOUR_OF_DAY=16,
MINUTE=58,
SECOND=47,
MILLISECOND=642
,ZONE_OFFSET=28800000,
DST_OFFSET=0]
/
System.out.println©;
//获得日期的具体时间,通过get方法来指定日历的常量
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH)+1;
int day = c.get(Calendar.DAY_OF_MONTH);
System.out.println(year+“年”+month+“月”+day+“日”);
System.out.println("-------------------------------");
//设置年月日
c.set(2008, 8, 18);
c.set(Calendar.HOUR_OF_DAY, 10);
int year1 = c.get(Calendar.YEAR);
int month1 = c.get(Calendar.MONTH)+1;
int day1 = c.get(Calendar.DAY_OF_MONTH);
int hour = c.get(Calendar.HOUR_OF_DAY);
System.out.println(year1+“年”+month1+“月”+day1+“日” +hour);
}
}
集合上
1.数组回顾
需求:把一个你班级的学生存储起来,使用数组。
数组的长度是固定的,无法满足动态的数据添加。
面试题:数组和集合的区别?

数组:长度固定,
可以存储基本数据类型,也能存储对象
只能存储同一种数据类型的数据

集合:长度可变
只能存储对象类型。
在集合中可以存储任意类型
2.集合
1.集合的体系结构
集合也叫容器用于存储对象。
我们根据不同的需求和不同的数据结构来对集合做了不同的抽象。

2.集合的方法
添加:
boolean add(E e)
确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
删除:
void clear()
移除此 collection 中的所有元素(可选操作)。
boolean remove(Object o)
从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
boolean removeAll(Collection<?> c)
移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。

判断:
boolean contains(Object o)
如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c)
如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean isEmpty()
如果此 collection 不包含元素,则返回 true。
数组的转换:
Object[]
toArray()
返回包含此 collection 中所有元素的数组。
添加删除代码:
package com.rl.coll;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo {
public static void main(String[] args) {
//创建ArrayList集合
Collection c = new ArrayList();
System.out.println©;
c.add(“renliang”);
c.add(“lisi”);
c.add(“zhangsan”);
System.out.println©;
Collection c1 = new ArrayList();
c1.add(“wangwu”);
c1.add(“xueliu”);
//把c这个集合的内容加在c1中,并且在后面追加
c1.addAll©;
System.out.println(c1);
Collection c2 = new ArrayList();
//对于基本类型的添加自动做了装箱,所以其实添加的是Integer
c2.add(1);
c2.add(2);
//集合中可以存储不同类型的数据,但是在实际项目中都是存储同一类型的数据。
c2.add(“renliang”);
System.out.println(c2);

	System.out.println("---------------------------------");
	//c2.clear();
	//System.out.println(c2);
	c2.remove("renliang");
	System.out.println(c2);
	c1.removeAll(c);
	System.out.println(c1);
}

}
判断代码:
package com.rl.coll;
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo1 {
public static void main(String[] args) {
//创建ArrayList集合
Collection c = new ArrayList();
System.out.println©;
c.add(“renliang”);
c.add(“lisi”);
c.add(“zhangsan”);
System.out.println©;
Collection c1 = new ArrayList();
c1.add(“wangwu”);
c1.add(“xueliu”);
//把c这个集合的内容加在c1中,并且在后面追加
c1.addAll©;
System.out.println(c1);
boolean isExist = c.contains(“renliang”);
System.out.println(isExist);
//c.add(“aa”);
//一个集合是否包含某个集合
boolean isExistColl = c1.containsAll©;
System.out.println(isExistColl);
//c.clear();
//判断集合中是否有元素
boolean isEmpty = c.isEmpty();
System.out.println(isEmpty);
//把集合转换成数组
Object[] objArray = c.toArray();
for(int i = 0; i < objArray.length; i++){
System.out.println(objArray[i]);
}
}
}
3.集合的遍历
遍历:
Iterator
iterator()
返回在此 collection 的元素上进行迭代的迭代器。

A
B
C
D
E

实例代码:
package com.rl.coll;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo2 {
public static void main(String[] args) {
//创建ArrayList集合
Collection c = new ArrayList();
c.add(“renliang”);
c.add(“lisi”);
c.add(“zhangsan”);
//创建迭代器,迭代器是依赖于集合的,不能给别的集合使用
Iterator iter = c.iterator();
//判断是否有下一个元素
while(iter.hasNext()){
//区下一个元素
Object obj = iter.next();
System.out.println(obj);
}
//不能二次使用,迭代器的指针已经走到底部了
/while(iter.hasNext()){
//区下一个元素
Object obj = iter.next();
System.out.println(obj);
}
/
}
}

练习:通过集合来存储Student并且遍历
public class Student {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
@Override //必须要重写,,要不然就会输出类名加上哈希个码
public String toString() {
return “Student [name=” + name + “, age=” + age + “]”;
}

}
package com.rl.coll;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo3 {
public static void main(String[] args) {
//创建ArrayList集合
Collection c = new ArrayList();
Student s = new Student(“林冲”, 34);
Student s1 = new Student(“武松”, 30);
Student s2 = new Student(“柴进”, 40);
Student s3 = new Student(“李逵”, 28);
Student s4 = new Student(“鲁智深”, 30);
c.add(s);
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
Iterator it = c.iterator();
while(it.hasNext()){
//获得集合中一个元素
Object obj = it.next();
Student stu = (Student)obj;
System.out.println(stu);
/* 注意使用迭代器的时候一次取一个元素即可。
* java.util.NoSuchElementException
* Student stu1 = (Student)it.next();
System.out.println(stu1);*/
}
}
}
4.List
有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
1.要掌握的方法
存储:
boolean add(E e)
向列表的尾部添加指定的元素(可选操作)。
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
boolean addAll(Collection<? extends E> c)
添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。
代码:
package com.rl.list;
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
//定义List的集合
List list = new ArrayList();
//添加
list.add(“任亮”);
list.add(“吕布”);
list.add(“董卓”);
System.out.println(list);
//[任亮, 吕布, 董卓]
// 0 1 2 List集合的索引号
//在指定的位置插入元素,后续的元素都向后顺移一位。
//在根据索引添加的时候,如果要添加的索引没有前一个值则不能添加,中间不允许有空位。
list.add(3, “貂蝉”);
System.out.println(list);
//定义List的集合
List list1 = new ArrayList();
list1.add(“王允”);
//该方法继承与Collection
list1.addAll(list);
System.out.println(list1);
}
}

获取:
E
get(int index)
返回列表中指定位置的元素。
int size()
返回列表中的元素数。
代码:
package com.rl.list;
import java.util.ArrayList;
import java.util.List;
public class ListDemo1 {
public static void main(String[] args) {
//定义List的集合
List list = new ArrayList();
//添加
list.add(“任亮”);
list.add(“吕布”);
list.add(“董卓”);
System.out.println(list);
//[任亮, 吕布, 董卓]
// 0 1 2 List集合的索引号
//根据索引来获得list中的指定的元素
//注意java.lang.IndexOutOfBoundsException
Object obj = list.get(2);
String str = (String)obj;
System.out.println(str);
//获得list的元素的个数
Integer length = list.size();
System.out.println(length);
//使用for循环来遍历List
for(int i = 0; i < list.size(); i++){
String result = (String)list.get(i);
System.out.println(result);
}
}
}

遍历:
ListIterator
listIterator()
返回此列表元素的列表迭代器(按适当顺序)。
代码:
package com.rl.list;
import java.util.ArrayList;
import java.util.List;
public class ListDemo2 {
public static void main(String[] args) {
//定义List的集合
List list = new ArrayList();
//添加
list.add(“任亮”);
list.add(“吕布”);
list.add(“董卓”);
System.out.println(list);
//[任亮, 吕布, 董卓]
// 0 1 2 List集合的索引号
//根据索引删除list的元素,返回的结果是删除的元素
/*Object obj = list.remove(2);
System.out.println(obj);
System.out.println(list);
*/
/boolean isDelete = list.remove(“任亮”);
System.out.println(isDelete);
System.out.println(list);
/
//定义List的集合
List list1 = new ArrayList();
//添加
list1.add(“任亮”);
list1.add(“吕布”);
//删除多个元素
list.removeAll(list1);
System.out.println(list);
//清空list
list.clear();
System.out.println(list);
}
}

删除:
E
remove(int index)
移除列表中指定位置的元素(可选操作)。
boolean remove(Object o)
从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
boolean removeAll(Collection<?> c)
从列表中移除指定 collection 中包含的其所有元素(可选操作)。
void clear()
移除此 collection 中的所有元素(可选操作)。
代码:
package com.rl.list;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListDemo3 {
public static void main(String[] args) {
//定义List的集合
List list = new ArrayList();
//添加
list.add(“任亮”);
list.add(“吕布”);
list.add(“董卓”);
//[任亮, 吕布, 董卓]
// 0 1 2 List集合的索引号
ListIterator iter = list.listIterator();
while(iter.hasNext()){
String result = (String) iter.next();
System.out.println(result);
}
System.out.println("------------------------");
//获得前一个元素
/String str = (String) iter.previous();
Integer pIndex = iter.previousIndex();
System.out.println(str + " "+pIndex);
String str1 = (String) iter.previous();
Integer pIndex1 = iter.previousIndex();
System.out.println(str1 + " "+pIndex1);
/
while(iter.hasPrevious()){
String result = (String) iter.previous();
System.out.println(result);
}
}
}

2.遍历的并发
添加或删除
遍历

多个线程对同一个集合操作时会产生并发安全性问题。java.util.ConcurrentModificationException,Iterator依赖于list,只要是list发生了变化Iterator就没有用了,就会发生并发修改异常。
package com.rl.list;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListDemo4 {
public static void main(String[] args) {
//定义List的集合
List list = new ArrayList();
//添加
list.add(“任亮”);
list.add(“吕布”);
list.add(“董卓”);
//[任亮, 吕布, 董卓]
// 0 1 2 List集合的索引号
/Iterator iter = list.iterator();
while(iter.hasNext()){
String result = (String) iter.next();
list.add(“王允”);
System.out.println(result);
}
/
/ListIterator iter = list.listIterator();
while(iter.hasNext()){
String result = (String) iter.next();
//在迭代器中来添加数据,其实就是添加到了list中
if(“任亮”.equals(result)){
//新添加的数据不会被当前的这次循环遍历出来
iter.add(“王允”);
}
System.out.println(result);
}
System.out.println(list);
/
/**
* 在存在并发访问集合的时候建议使用for
*/
for(int i = 0; i < list.size(); i++){
String result = (String) list.get(i);
if(“任亮”.equals(result)){
//新添加的数据会被当前的这次循环遍历出来
list.add(“王允”);
}
System.out.println(result);
}
}
}
javase集合下
1.List的子类
1.ArrayList
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
特点:ArrayList中的元素和可以重复
是有序的集合,长度不固定。
不是线程安全的。
效率高。
package com.rl.listson;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class ArrayListDemo {
public static void main(String[] args) {
//method1();
//curr();
currFor();
}
public static void method(){
ArrayList al = new ArrayList();
al.add(“张三”);
al.add(“李四”);
al.add(“王五”);

	Iterator iter = al.iterator();
	while(iter.hasNext()){
		String result = (String) iter.next();
		System.out.println(result);
	}
}
public static void method1(){
	ArrayList al = new ArrayList();
	al.add(new Student("林冲",30));
	al.add(new Student("鲁智深",32));
	al.add(new Student("史文恭",35));
	al.add(new Student("卢俊义",35));	
	Iterator iter = al.iterator();
	while(iter.hasNext()){
		Student result = (Student) iter.next();
		System.out.println(result);
	}
}
/**
 * ListIterator当前的遍历不能输出变化后的集合
 * @author renliang
 */
public static void curr(){
	ArrayList al = new ArrayList();
	al.add(new Student("林冲",30));
	al.add(new Student("鲁智深",32));
	al.add(new Student("史文恭",35));
	al.add(new Student("卢俊义",35));
	
	ListIterator iter = al.listIterator();
	while(iter.hasNext()){
		Student result = (Student) iter.next();
		String stuName = result.getName();
		if("史文恭".equals(stuName)){
			iter.remove();
		}
		System.out.println(result);
	}	
	System.out.println(al);
}
/**
 * 在并发的时候for可以遍历变化后的集合
 * @author renliang
 */
public static void currFor(){
	ArrayList al = new ArrayList();
	al.add(new Student("林冲",30));
	al.add(new Student("鲁智深",32));
	al.add(new Student("史文恭",35));
	al.add(new Student("卢俊义",35));	
	for(int i = 0; i < al.size(); i++){
		Student result = (Student) al.get(i);
		String stuName = result.getName();
		if("史文恭".equals(stuName)){
			al.remove(i);
		}
		System.out.println(result);
	}		
}

}

2.LinkList(了解)
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
不是线程安全的。
栈:

“林冲”
“武松”
“鲁智深”

Push:压栈
Pop:出栈
栈的特点是先进后出,后进先出
队列:

武松 “杨志” 林冲 “鲁智深”

队列的特点是:先进先出。
链表:

0x999					0x998				0x997

void addFirst(E e)
将指定元素插入此列表的开头。
void addLast(E e)
将指定元素添加到此列表的结尾。
E
removeFirst()
移除并返回此列表的第一个元素。
E
removeLast()
移除并返回此列表的最后一个元素。
E
pop()
从此列表所表示的堆栈处弹出一个元素。
void push(E e)
将元素推入此列表所表示的堆栈。

3.Vector
和ArrayList功能类似,最主要的区别就在于vector是线程并发安全的。但是缺点是效率比较低。
B添加(刘唐)
A添加(白胜)

2.泛型
我们在项目中使用集合基本99%都是在集合中存储同一种数据类型。既然我们在集合中存储同一种数据类型,我们事先一定知道这个集合中要存储什么数据类型。我们就可以预先去指定要存储的数据类型。
1.泛型在集合中的使用
泛型:就是提前指定要操作的数据类型。
在集合使用的语法:

在定义集合的时候
List<数据类型> 变量名 = new ArrayList<数据类型>();
示例代码:
package com.rl.generic;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ArrayListDemo1 {
public static void main(String[] args) {
method1();
}
public static void method(){
//al集合中只允许存储字符串的数据类型。
List al = new ArrayList();
al.add(“张三”);
al.add(“李四”);
al.add(“王五”);
/al.add(1);
al.add(new Student(“李逵”,25));
/
//集合的迭代器也要指定泛型
Iterator iter = al.iterator();
while(iter.hasNext()){
//java.lang.ClassCastException:
//如果已经指定了泛型,从集合中取值时就不需要强制转换了
String result = iter.next();
System.out.println(result);
}
}
public static void method1(){
//al集合中只允许存储字符串的数据类型。
List al = new ArrayList();
al.add(new Student(“李逵”,25));
al.add(new Student(“张飞”,35));

	Iterator<Student> iter = al.iterator();
	while(iter.hasNext()){
		//java.lang.ClassCastException:
		Student result = iter.next();
		System.out.println(result);
	}
}

}
2.自定义泛型
在自定义泛型时
语法:class/interface 类名/接口名 {

}
T只是泛型的一个标准,使用什么字符都可以,但是都要大写,不要使用特殊字符,建议用T。
泛型定义代码:
package com.rl.generic;
public class GenericTest {
private E t;
public E getT() {
return t;
}
public void setT(E t) {
this.t = t;
}
}
实现代码:
package com.rl.generic;
import java.util.ArrayList;
import java.util.List;
public class StudentDaoImpl implements BaseDao {
List sList = new ArrayList();
public void save(Student t) {
sList.add(t);
}
public Student getT(Integer id) {
return sList.get(id);
}
public List listT() {
return sList;
}
}
测试:
package com.rl.generic;
public class Test {
public static void main(String[] args) {
//设置泛型为Integer
GenericTest gt = new GenericTest();
gt.setT(20);
Integer num = gt.getT();
System.out.println(num);
System.out.println("--------------------------");
//设置泛型为String
GenericTest gt1 = new GenericTest();
gt1.setT(“张三”);
String result = gt1.getT();
System.out.println(result);
}
}

3.增强的For循环
在Jdk1.5以后出现了增强的for
对数组,集合来做遍历
语法:
for(数据类型 变量:集合变量){
///
}
package com.rl.forp;
import java.util.ArrayList;
import java.util.List;
public class ForDemo {
public static void main(String[] args) {
String[] ss = {“张三”,“李四”,“王五”};
for(int i = 0; i < ss.length; i++){
System.out.println(ss[i]);
}
System.out.println("-------------------------");
//冒号左边是集合或者数组中的数据类型和变量,冒号右边是数组或者集合的变量
for(String str:ss){
System.out.println(str);
}
System.out.println("-------------------------");
List iList = new ArrayList();
iList.add(1);
iList.add(2);
iList.add(3);
for(Integer i : iList){
System.out.println(i);
}
System.out.println("--------------------------");
List sList = new ArrayList();
sList.add(new Student(“李逵”,30));
sList.add(new Student(“李鬼”,40));
for(Student s : sList){
System.out.println(s);
}
System.out.println("-------------------------");
List ss1 = new ArrayList();
ss1.add(“鲁智深”);
ss1.add(“史进”);
ss1.add(“李忠”);
//冒号左边是集合或者数组中的数据类型和变量,冒号右边是数组或者集合的变量
for(String str:ss1){
//java.util.ConcurrentModificationException
if(“李忠”.equals(str)){
ss1.add(“周通”);
}
System.out.println(str);
}
}
}
特点:遍历时存在并发问题。
4.Set集合

一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。

Set里面的方法绝大多数都是继承于Collection,所以set基本学完。
Set的特点:
元素不可重复
元素无序的(跟添加的顺序无关)
package com.rl.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.rl.listson.Student;
public class SetDemo {
public static void main(String[] args) {
method2();
}
public static void method(){
//定义一个set集合
Set set = new HashSet();
set.add(“任亮”);
set.add(“孙坚”);
set.add(“孙坚”);
set.add(“袁绍”);
//set可以去除重复的元素,无序的
System.out.println(set);
Iterator iter = set.iterator();
while(iter.hasNext()){
String result = iter.next();
System.out.println(result);
}
}
public static void method1(){
//定义一个set集合
Set set = new HashSet();
set.add(new Student(“林冲”,30));
set.add(new Student(“鲁智深”,32));
set.add(new Student(“史文恭”,35));
set.add(new Student(“卢俊义”,35));
//set可以去除重复的元素,无序的
System.out.println(set);
Iterator iter = set.iterator();
while(iter.hasNext()){
Student result = iter.next();
System.out.println(result);
}
}
public static void method2(){
//定义一个set集合
Set set = new HashSet();
set.add(new Student(“林冲”,30));
set.add(new Student(“鲁智深”,32));
set.add(new Student(“史文恭”,35));
set.add(new Student(“卢俊义”,35));
for(Student stu : set){
System.out.println(stu);
}
}
}

1.Set的实现类HashSet
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。

HashSet的唯一性:
在HashSet做添加的时候会逐个来判断当前集合中的对象和要添加的对象的比较
通过以下的条件判断两个对象是否相等
* e.hash == hash && ((k = e.key) == key || key.equals(k))
* hash值必须相等并且两个对象的地址值相等或者equals返回true
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

package com.rl.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.rl.listson.Student;
public class HashSetDemo {
public static void main(String[] args) {
method2();
}
/**
* 通过以下的条件判断两个对象是否相等
* e.hash == hash && ((k = e.key) == key || key.equals(k))
* hash值必须相等并且两个对象的地址值相等或者equals返回true
* @author renliang
*/
public static void method2(){
//定义一个set集合
HashSet set = new HashSet();
set.add(new Student(“林冲”,30));
set.add(new Student(“鲁智深”,32));
set.add(new Student(“史文恭”,35));
set.add(new Student(“卢俊义”,35));
set.add(new Student(“林冲”,30));
set.add(new Student(“林冲”,30));
set.add(null);
set.add(null);
for(Student stu : set){
System.out.println(stu);
}
}
}

Student
package com.rl.listson;
public class Student {
private String name;
private Integer age;
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String toString() {
return “Student [name=” + name + “, age=” + age + “]”;
}
public boolean equals(Object obj) {
if(!(obj instanceof Student)){
return false;
}
Student stu = (Student) obj;
if(stu != null && stu.getName().equals(this.name) && stu.getAge() == this.age){
return true;
}
return false;
}
public int hashCode() {
return 1;
}
}

特点:
1.元素唯一性
2.无序行
3.允许null存在一个
4.不是线程安全(效率高)
2.set的实现类LinkedHashSet
具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。
有序
package com.rl.set;
import java.util.LinkedHashSet;
import com.rl.listson.Student;
public class LinkedHashSetDemo {
public static void main(String[] args) {
method2();
}
/**
* 使用LinkedHashSet可以保证添加的顺序
* @author renliang
*/
public static void method2(){
//定义一个set集合
LinkedHashSet set = new LinkedHashSet();
set.add(new Student(“林冲”,30));
set.add(new Student(“鲁智深”,32));
set.add(new Student(“史文恭”,35));
set.add(new Student(“卢俊义”,35));
for(Student stu : set){
System.out.println(stu);
}
}
}
输出:
Student [name=林冲, age=30]
Student [name=鲁智深, age=32]
Student [name=史文恭, age=35]
Student [name=卢俊义, age=35]
特点:
1.元素唯一性
2.有序的
3.允许null存在一个
4.不是线程安全(效率高)

3.Set的实现类TreeSet
TreeSet可以支持自定义排序,如果TreeSet所存储的对象的类没有实现Comparable接口就会报错ClassCastException。所以我们如果想要使用TreeSet来对自定义的对象来排序必须实现Comparable接口。
示例:代码
package com.rl.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
import com.rl.listson.Student;
public class TreeSetDemo {
public static void main(String[] args) {
method1();
}
public static void method(){
TreeSet set = new TreeSet();
//TreeSet在做添加的时候会比较字符串的大小,调用String中的compareTo的方法来比较
set.add(“zhangsan”);
set.add(“lisi”);
set.add(“wangwu”);
set.add(“zhangming”);

	System.out.println(set);
}
/**
 * TreeSet唯一性的规则使用的是compareTo的方式
 * @author renliang
 */
public static void method1(){
	TreeSet<Student> set = new TreeSet<Student>();
	//TreeSet在做添加的时候会比较字符串的大小,调用String中的compareTo的方法来比较
	set.add(new Student("zhangsan", 30));
	set.add(new Student("lisi", 25));
	set.add(new Student("wangwu",40));
	set.add(new Student("zhangming", 25));		
	for(Student stu : set){
		System.out.println(stu);
	}
}

}
代码Student:
package com.rl.listson;
public class Student implements Comparable{
private String name;
private Integer age;
public Student(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String toString() {
return “Student [name=” + name + “, age=” + age + “]”;
}
public boolean equals(Object obj) {
if(!(obj instanceof Student)){
return false;
}
Student stu = (Student) obj;
if(stu != null && stu.getName().equals(this.name) && stu.getAge() == this.age){
return true;
}
return false;
}
public int hashCode() {
return 1;
}
public int compareTo(Student o) {
int num = this.age - o.getAge();
if(num == 0){
num = this.getName().compareTo(o.getName());
}
return num;
}
}
特点:
1.元素唯一性
2.可自定义排序的
3.不允许null存在
4.不是线程安全
5.可变参数
可变参数的语法:
修饰符 返回值类型 方法名(数据类型…变量){

}
public static int sum(int … p){
return 0;
}
注意:参数p实际是一个数组,p都是同一种类型
package com.rl.dynamic.param;
public class DynamicParamTest {

public static void main(String[] args) {
	System.out.println(sum(1,2, 2, 8));
}
/*public static int sum(int a , int b){
	return a + b;
}
public static int sum(int a , int b, int c){
	return a + b +c;
}
public static int sum(int a , int b, int c, int d){
	return a + b +c +d;
}*/	
/**
 * 可变参数方法的定义
 * @author renliang
 * @param p
 * @return
 */
public static int sum(int ... p){
	int sumNum = 0;
	for(int i = 0; i < p.length; i++){
		sumNum += p[i];
	}
	return sumNum;
}

}
6.工具类Arrays
数组的工具类,这里的方法都是静态的
要掌握的功能:
1.把数组转换成字符串
static String
toString(boolean[] a)
返回指定数组内容的字符串表示形式。
static String
toString(byte[] a)
返回指定数组内容的字符串表示形式。
static String
toString(char[] a)
返回指定数组内容的字符串表示形式。
static String
toString(double[] a)
返回指定数组内容的字符串表示形式。
static String
toString(float[] a)
返回指定数组内容的字符串表示形式。
static String
toString(int[] a)
返回指定数组内容的字符串表示形式。
static String
toString(long[] a)
返回指定数组内容的字符串表示形式。
static String
toString(Object[] a)
返回指定数组内容的字符串表示形式。
static String
toString(short[] a)
返回指定数组内容的字符串表示形式
2.对任意数组排序
static void sort(byte[] a)
对指定的 byte 型数组按数字升序进行排序。
static void sort(byte[] a, int fromIndex, int toIndex)
对指定 byte 型数组的指定范围按数字升序进行排序。
static void sort(char[] a)
对指定的 char 型数组按数字升序进行排序。
static void sort(char[] a, int fromIndex, int toIndex)
对指定 char 型数组的指定范围按数字升序进行排序。
static void sort(double[] a)
对指定的 double 型数组按数字升序进行排序。
static void sort(double[] a, int fromIndex, int toIndex)
对指定 double 型数组的指定范围按数字升序进行排序。
static void sort(float[] a)
对指定的 float 型数组按数字升序进行排序。
static void sort(float[] a, int fromIndex, int toIndex)
对指定 float 型数组的指定范围按数字升序进行排序。
static void sort(int[] a)
对指定的 int 型数组按数字升序进行排序。
static void sort(int[] a, int fromIndex, int toIndex)
对指定 int 型数组的指定范围按数字升序进行排序。
static void sort(long[] a)
对指定的 long 型数组按数字升序进行排序。
static void sort(long[] a, int fromIndex, int toIndex)
对指定 long 型数组的指定范围按数字升序进行排序。
static void sort(Object[] a)
根据元素的自然顺序对指定对象数组按升序进行排序。

static void sort(Object[] a, int fromIndex, int toIndex)
根据元素的自然顺序对指定对象数组的指定范围按升序进行排序。
static void sort(short[] a)
对指定的 short 型数组按数字升序进行排序。
static void sort(short[] a, int fromIndex, int toIndex)
对指定 short 型数组的指定范围按数字升序进行排序。
static
void
sort(T[] a, Comparator<? super T> c)
根据指定比较器产生的顺序对指定对象数组进行排序。
static
void
sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c)
根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。
3.对任意的数组做二分法的查找
static int binarySearch(byte[] a, byte key)
使用二分搜索法来搜索指定的 byte 型数组,以获得指定的值。
static int binarySearch(byte[] a, int fromIndex, int toIndex, byte key)
使用二分搜索法来搜索指定的 byte 型数组的范围,以获得指定的值。
static int binarySearch(char[] a, char key)
使用二分搜索法来搜索指定的 char 型数组,以获得指定的值。
static int binarySearch(char[] a, int fromIndex, int toIndex, char key)
使用二分搜索法来搜索指定的 char 型数组的范围,以获得指定的值。
static int binarySearch(double[] a, double key)
使用二分搜索法来搜索指定的 double 型数组,以获得指定的值。
static int binarySearch(double[] a, int fromIndex, int toIndex, double key)
使用二分搜索法来搜索指定的 double 型数组的范围,以获得指定的值。
static int binarySearch(float[] a, float key)
使用二分搜索法来搜索指定的 float 型数组,以获得指定的值。
static int binarySearch(float[] a, int fromIndex, int toIndex, float key)
使用二分搜索法来搜索指定的 float 型数组的范围,以获得指定的值。
static int binarySearch(int[] a, int key)
使用二分搜索法来搜索指定的 int 型数组,以获得指定的值。
static int binarySearch(int[] a, int fromIndex, int toIndex, int key)
使用二分搜索法来搜索指定的 int 型数组的范围,以获得指定的值。
static int binarySearch(long[] a, int fromIndex, int toIndex, long key)
使用二分搜索法来搜索指定的 long 型数组的范围,以获得指定的值。
static int binarySearch(long[] a, long key)
使用二分搜索法来搜索指定的 long 型数组,以获得指定的值。
static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key)
使用二分搜索法来搜索指定数组的范围,以获得指定对象。
static int binarySearch(Object[] a, Object key)
使用二分搜索法来搜索指定数组,以获得指定对象。
static int binarySearch(short[] a, int fromIndex, int toIndex, short key)
使用二分搜索法来搜索指定的 short 型数组的范围,以获得指定的值。
static int binarySearch(short[] a, short key)
使用二分搜索法来搜索指定的 short 型数组,以获得指定的值。
static
int
binarySearch(T[] a, int fromIndex, int toIndex, T key, Comparator<? super T> c)
使用二分搜索法来搜索指定数组的范围,以获得指定对象。
static
int
binarySearch(T[] a, T key, Comparator<? super T> c)
使用二分搜索法来搜索指定数组,以获得指定对象。
把数组转换成List
static
List

asList(T... a) 
      返回一个受指定数组支持的固定大小的列表。

实例代码:
package com.rl.arrays;
import java.util.Arrays;
import java.util.List;
import com.rl.listson.Student;
public class ArraysTest1 {
public static void main(String[] args) {
//toSortTest();
toConverterTest();
}
public static void toSortTest(){
Student [] ss = new Student[3];
ss[0] = new Student(“唐僧”, 30);
ss[1] = new Student(“悟空”, 500);
ss[2] = new Student(“八戒”, 200);
//对自定义对象的数组排序需要自定义对象来定义排序规则,实现comparable接口,实现toCompare方法
Arrays.sort(ss);
for(Student s : ss){
System.out.println(s);
}
}
/**
* static List asList(T… a)
* 数组转换成List后,这个list无法删除和新增。
* @author renliang
/
public static void toConverterTest(){
Integer [] arr = {13, 44, 41, 8, 10};
//从数组转换成list时候int自动装箱失效了
List iList = Arrays.asList(arr);
//java.lang.UnsupportedOperationException
//iList.add(99);
//iList.remove(0);
iList.set(1, 55);
System.out.println(iList);
}
}
7.工具类Collections
面试题:
问:Collection和Collections的区别:
前者是集合的接口
后者操作集合的工具类
package com.rl.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo {
public static void main(String[] args) {
//sortTest();
//binarySearchTest();
//maxOrMinTest();
//reverseTest();
shuffleTest();
}
/
*
* 对list的排序
* @author renliang
/
public static void sortTest(){
List list = new ArrayList();
list.add(33);
list.add(19);
list.add(24);
list.add(45);
Collections.sort(list);
System.out.println(list);
}
/
*
* 二分法查找
* @author renliang
/
public static void binarySearchTest(){
List list = new ArrayList();
list.add(33);
list.add(19);
list.add(24);
list.add(45);
Collections.sort(list);
System.out.println(list);
Integer index = Collections.binarySearch(list, 33);
System.out.println(index);
}
/
*
* 在集合中找极值
* @author renliang
*/
public static void maxOrMinTest(){
List list = new ArrayList();
list.add(33);
list.add(19);
list.add(24);
list.add(45);
//Integer maxNum = Collections.max(list);
Integer minNum = Collections.min(list);
System.out.println(minNum);
}
public static void reverseTest(){
List list = new ArrayList();
list.add(33);
list.add(19);
list.add(24);
list.add(45);
System.out.println(list);
Collections.reverse(list);
System.out.println(list);
}
public static void shuffleTest(){
List list = new ArrayList();
list.add(33);
list.add(19);
list.add(24);
list.add(45);
System.out.println(list);
Collections.shuffle(list);
System.out.println(list);
}
public static void synTest(){
List list = new ArrayList();
list.add(33);
list.add(19);
list.add(24);
list.add(45);
//把list集合变成线程安全的,效率会变低。
List iList = Collections.synchronizedList(list);
}
}
Javase中Map集合
1.Map概述
Map即使键值对的集合的接口抽象。

Key1 Key2 Key3
Value1 Value2 Value3
我们可以通过key的值来获得相应的值,将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。键只允许有一个空值,值可以有多个空值。

Map集合和之前学过的Collection接口无关。

Map的特点:
1.数据成对出现
2.数据的键是唯一的
3.一个键只能对应一个值
4.值可以重复
5.键允许有一个为空,值可以多个是空。

面试题:
问:map集合和Collection集合的区别?
答:1.Map集合是键值对的集合,Collection是单一出现的数据的集合
2.Map的键唯一的,而Collection的子接口List集合中的元素是可以重复的,set是唯一的
3.map是夫妻对,Collection是光棍。
2.map的功能

添加功能
V
put(K key, V value)
将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m)
从指定映射中将所有映射关系复制到此映射中(可选操作)。

2.删除功能
void clear()
从此映射中移除所有映射关系(可选操作)。
V
remove(Object key)
如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

3.获取功能
V
get(Object key)
返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
Set
keySet()
返回此映射中包含的键的 Set 视图。
Collection
values()
返回此映射中包含的值的 Collection 视图。

int size()
返回此映射中的键-值映射关系数。

4.判断功能
boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。
boolean isEmpty()
如果此映射未包含键-值映射关系,则返回 true
5.遍历
Set<Map.Entry<K,V>>
entrySet()
返回此映射中包含的映射关系的 Set 视图。

实例代码:
package com.rl.map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapTest {
public static void main(String[] args) {
//deleteTest();
//getTest();
//keySetTest();
//valuesTest();
//updateTest();
//isTest();
loopTest();
}
public static void putTest(){
//创建map的实例的集合对象
Map<String, String> map = new HashMap<String, String>();
map.put(“1000”, “王伦”);
map.put(“2000”, “杜迁”);
map.put(“3000”, “朱贵”);
System.out.println(map);
Map<String, String> map1 = new HashMap<String, String>();
map.put(“4000”, “晁盖”);
map.put(“5000”, “吴用”);
map.put(“6000”, “阮氏三雄”);
//把map1集合的内容加入到map中
map.putAll(map1);
System.out.println(map);
}
/**
* put的修改
* @author renliang
/
public static void updateTest(){
//创建map的实例的集合对象
Map<String, String> map = new HashMap<String, String>();
map.put(“1000”, “王伦”);
map.put(“2000”, “杜迁”);
map.put(“3000”, “朱贵”);
//如果做重复的key的put就会覆盖前面的数据
map.put(“2000”, “摸着天”);
System.out.println(map);
}
/
*
* map的删除
* @author renliang
*/
public static void deleteTest(){
//创建map的实例的集合对象
Map<String, String> map = new HashMap<String, String>();
map.put(“1000”, “王伦”);
map.put(“2000”, “杜迁”);
map.put(“3000”, “朱贵”);

	System.out.println(map);
	//情况map
	/*map.clear();
	System.out.println(map);*/
	String value = map.remove("1000");
	System.out.println("删除的元素:"+value);
	System.out.println(map);
}
/**
 * 获取功能
 * @author renliang
 */
public static void getTest(){
	//创建map的实例的集合对象
	Map<String, String> map = new HashMap<String, String>();
	map.put("1000", "王伦");
	map.put("2000", "杜迁");
	map.put("3000", "朱贵");
	//在map中根据key来查询值
	/*String value = map.get("4000");
	System.out.println("获得的值:"+value);*/
}
public static void keySetTest(){
	//创建map的实例的集合对象
	Map<String, String> map = new HashMap<String, String>();
	map.put("1000", "王伦");
	map.put("2000", "杜迁");
	map.put("3000", "朱贵");
	//获得指定的集合的每一个键
	Set<String> set = map.keySet();
	System.out.println(set);
	//根据键的集合来遍历map
	for(String key : set){
		String value = map.get(key);
		System.out.println("键是:"+key+" 值是:"+value);
	}
}
public static void valuesTest(){
	//创建map的实例的集合对象
	Map<String, String> map = new HashMap<String, String>();
	map.put("1000", "王伦");
	map.put("2000", "杜迁");
	map.put("3000", "朱贵");
	//map集合中的元素个数
	int length = map.size();
	System.out.println("map的长度:"+length);
	Collection<String> coll = map.values();
	System.out.println(coll);
}
/**
 * map的判断功能
 * @author renliang
 */
public static void isTest(){
	//创建map的实例的集合对象
	Map<String, String> map = new HashMap<String, String>();
	map.put("1000", "王伦");
	map.put("2000", "杜迁");
	map.put("3000", "朱贵");
	//map集合中的元素个数
	boolean isExist = map.containsKey("4000");
	System.out.println(isExist);
	//判断map中是否存在某个值
	boolean isExistVal = map.containsValue("林冲");
	System.out.println(isExistVal);
	map.clear();
	//判断map中的内容是不是空
	boolean isEmpty = map.isEmpty();
	System.out.println(isEmpty);
}
public static void loopTest(){
	//创建map的实例的集合对象
	Map<String, String> map = new HashMap<String, String>();
	map.put("1000", "王伦");
	map.put("2000", "杜迁");
	map.put("3000", "朱贵");
	/*Set<String> set = map.keySet();
	for(String key : set){
		String value = map.get(key);
		System.out.println("key:"+key+ " value:"+value);
	}*/
	//获得 的Entry映射想的集合
	Set<Entry<String, String>> set = map.entrySet();
	//如果在Map.Entry它的后面对集合进行修改,那么就会同步到Entry中
	//map.put("4000", "杨志");
	map.remove("1000");
	for(Entry<String, String> entry : set){
		
		
		//获得键
		String key = entry.getKey();
		/*if("3000".equals(key)){
			map.put("4000", "杨志");
		}*/	
		//根据映射想来获得的值
		String value = entry.getValue();
		System.out.println("key: "+key+ "  value:"+value);
	}	
}

}

3.map的实现类HashMap
HashMap的特点
1.HashMap是map的实现类
2.允许多个null值和一个null键
3.HashMap中的元素没有顺序(跟添加的顺序无关)
4.HashMap不是线程安全的。
package com.rl.map.impl;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
//创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
//HashMap<String, Object> hm = new HashMap<String,Object>();
HashMap<String, Person> hm = new HashMap<String,Person>();
hm.put(“神行太保”, new Person(“戴宗”, 32));
hm.put(“浪里白条”, new Person(“张顺”, 25));
hm.put(“及时雨”, new Person(“宋江”, 30));
//只允许一个null键
hm.put(null, new Person(“李鬼”, 40));
hm.put(null, new Person(“张三”, 15));
hm.put(“白衣秀士”, null);
hm.put(“活阎罗”, null);
Set<Entry<String, Person>> set = hm.entrySet();
Iterator<Entry<String, Person>> iter = set.iterator();
while(iter.hasNext()){
Entry<String, Person> entry = iter.next();
String key = entry.getKey();
Person value = entry.getValue();
System.out.println(“绰号:”+key + " 真人:"+value);
}
}
}
4.map的实现类TreeMap
TreeMap可以参考TreeSet,TreeMap可以支持Map的排序。
package com.rl.map.impl;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo {
public static void main(String[] args) {
//创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
//HashMap<String, Object> hm = new HashMap<String,Object>();
TreeMap<Person, String> hm = new TreeMap<Person,String>();
hm.put(new Person(“戴宗”, 32), “神行太保”);
hm.put(new Person(“张顺”, 25),“浪里白条”);
hm.put(new Person(“宋江”, 30),“及时雨”);
//只允许一个null键
Set<Entry<Person, String>> set = hm.entrySet();
Iterator<Entry<Person, String>> iter = set.iterator();
while(iter.hasNext()){
Entry<Person, String> entry = iter.next();
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(“绰号:”+value + " 真人:"+key);
}
}
}
5.map的实现类HashTable
HashTable的特点

  1. HashTable是map的实现类
    2.不允许任何null值和null键

  2. HashTable中的元素没有顺序(跟添加的顺序无关)

  3. HashTable是线程安全的。
    package com.rl.map.impl;
    import java.util.Hashtable;
    import java.util.Iterator;
    import java.util.Map.Entry;
    import java.util.Set;
    public class HashTableDemo {
    public static void main(String[] args) {
    //创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
    //HashMap<String, Object> hm = new HashMap<String,Object>();
    Hashtable<String, Person> hm = new Hashtable<String,Person>();
    hm.put(“神行太保”, new Person(“戴宗”, 32));
    hm.put(“浪里白条”, new Person(“张顺”, 25));
    hm.put(“及时雨”, new Person(“宋江”, 30));
    //只允许一个null键
    //hm.put(null, new Person(“李鬼”, 40));
    //hm.put(null, new Person(“张三”, 15));
    //hm.put(“白衣秀士”, null);
    //hm.put(“活阎罗”, null);
    Set<Entry<String, Person>> set = hm.entrySet();
    Iterator<Entry<String, Person>> iter = set.iterator();
    while(iter.hasNext()){
    Entry<String, Person> entry = iter.next();
    String key = entry.getKey();
    Person value = entry.getValue();
    System.out.println(“绰号:”+key + " 真人:"+value);
    }
    }
    }
    6.map的实现类LinkedHashMap
    LinkedHashMap
    的特点

  4. LinkedHashMap是map的实现类
    2.允许多个null值和一个null键

  5. LinkedHashMap有顺序(添加的顺序)

  6. LinkedHashMap不是线程安全的。
    package com.rl.map.impl;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.Map.Entry;
    import java.util.Set;
    public class LinkedHashMapDemo {
    public static void main(String[] args) {
    //创建了一个HashMap的实例一般情况建议大家使用<string,Object>泛型
    //HashMap<String, Object> hm = new HashMap<String,Object>();

     LinkedHashMap<String, Person> hm = new LinkedHashMap<String,Person>();
     hm.put("神行太保", new Person("戴宗", 32));
     hm.put("浪里白条", new Person("张顺", 25));
     hm.put("及时雨", new Person("宋江", 30));
     hm.put(null, new Person("李鬼", 40));
     hm.put(null, new Person("张三", 15));
     hm.put("白衣秀士", null);
     hm.put("活阎罗", null);
     
     Set<Entry<String, Person>> set = hm.entrySet();
     Iterator<Entry<String, Person>> iter =  set.iterator();
     while(iter.hasNext()){
     	Entry<String, Person> entry = iter.next();
     	String key = entry.getKey();
     	Person value = entry.getValue();
     	System.out.println("绰号:"+key + "   真人:"+value);
     }
    

    }
    }
    Javase中文件详解和IO流
    1.IO概述
    IO(Input/Output):输入和输出,指的是某个设备或环境进行数据的输入或者输出。例如:键盘的输入,再比如显示器就是输出设备,输出图像。
    对于java来说输入输出问题,java将它抽象成流对象来解决。
    以游戏程序为中心读取文件就是输入,写入文件是输出。

     					读取文件(输入)
    
    
    
     					写入文件(输出)
    

IO流在java中从输入输出角度分类:
1.输入流
2.输出流
IO流在java中从数据的角度来分类:
1.字符流
文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等
2.字节流
二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件,等等。
2.File类
1.File的构造器
我们操作系统中所有的设备的体现都是文件(包含文件夹),java对文件做了抽象,在java中IO包提供了文件的操作的功能。
1.File的构造器
File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri)
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。
实例代码:
package com.rl.file;
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
//如果使用正/来指定文件的路径需要使用\
File file = new File(“d:\demo.txt”);
File file1 = new File(“d:/demo.txt”);
System.out.println(file1);
System.out.println("------------------");
//创建文件的第二种方式,第一个参数是文件所在的路径,第二个是文件名
File file2 = new File(“d:/”, “demo.txt”);
System.out.println(file2);
System.out.println("---------------------");
//在java中把文件和文件夹都抽象为File
//创建一个文件夹的File对象
File fileDir = new File(“d:/”);
File file3 = new File(fileDir, “demo.txt”);
System.out.println(file3);
}
}
2.文件的创建
创建文件
boolean createNewFile()
当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
创建目录
boolean mkdir()
创建此抽象路径名指定的目录。
boolean mkdirs()
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。

示例代码:
package com.rl.file;
import java.io.File;
import java.io.IOException;
public class FileDemo1 {
public static void main(String[] args) throws IOException {
createDir();
}
/**
* 创建文件
* @author renliang
* @throws IOException
/
public static void createFile() throws IOException{
//使用绝对路径来创建File对象
File file = new File(“d:/a.txt”);
//创建文件,如果当前目录下的文件不存在的时候可以创建,如果文件已经存在则会创建失败
boolean isSuccess = file.createNewFile();
System.out.println(“a文件创建是否成功:”+isSuccess);
System.out.println("----------------------------");
//使用相对路径来创建文件,不指定绝对路径,在eclipse的工程中所创建的文件就直接在当前的工程目录下
File file1 = new File(“b.txt”);
boolean isSuccessb = file1.createNewFile();
System.out.println(“b文件创建是否成功:”+isSuccessb);
//可以根据相对路径来在我们项目工程中来创建文件
File file2 = new File(“src/com/rl/file/c.txt”);
boolean isSuccessc = file2.createNewFile();
System.out.println(“b文件创建是否成功:”+isSuccessc); System.out.println("---------------------------------------------");
}
/
*
* 创建文件夹
* @author renliang
* @throws IOException
/
public static void createDir() throws IOException{
//创建文件夹
/File filed = new File(“a”);
boolean isSuccessd = filed.mkdir();
System.out.println(“创建目录是否成功:”+isSuccessd);
/
/
//创建文件夹
File filed = new File(“a/b”);
//mkdir是单级目录的创建,如果是多级前面的目录必须存在:如a目录必须存在,才可能创建b
boolean isSuccessd = filed.mkdir();
System.out.println(“创建目录是否成功:”+isSuccessd);*/

	//创建文件夹
	File filed1 = new File("c/d/e");
	//mkdir是单级目录的创建,如果是多级前面的目录必须存在:如a目录必须存在,才可能创建b
	boolean isSuccessd1 = filed1.mkdirs();
	System.out.println("创建多级目录是否成功:"+isSuccessd1);
}

}
3.文件的删除
boolean delete()
删除此抽象路径名表示的文件或目录。
这个方法可以删除文件和目录
package com.rl.file;
import java.io.File;
import java.io.IOException;
public class FileDemo2 {
public static void main(String[] args) throws IOException {
deleteDir();
}
/**
* 删除文件
* @author renliang
* @throws IOException
/
public static void deleteFile() throws IOException{
File fileb = new File(“src/com/rl/file/c.txt”);
//如果本身b文件不存在或者这个文件正在被使用那么就false,否则是true
boolean isDelete = fileb.delete();
System.out.println(“文件是否删除:”+isDelete);
}
/
*
* 删除目录
* @author renliang
* @throws IOException
/
public static void deleteDir() throws IOException{
File file = new File(“c/a.txt”);
file.delete();
//目录删除时,如果目录中有文件则必须先删除文件再删除目录
File fileb = new File(“c”);
//如果本身b文件不存在或者这个文件正在被使用那么就false,否则是true
boolean isDelete = fileb.delete();
System.out.println(“文件夹是否删除:”+isDelete);
}
}
4.文件的重命名和判断功能
1.重命名
2.判断
boolean exists()
测试此抽象路径名表示的文件或目录是否存在。
boolean isFile()
测试此抽象路径名表示的文件是否是一个标准文件。
boolean isDirectory()
测试此抽象路径名表示的文件是否是一个目录。
boolean isAbsolute()
测试此抽象路径名是否为绝对路径名。
boolean canRead()
测试应用程序是否可以读取此抽象路径名表示的文件。
boolean canWrite()
测试应用程序是否可以修改此抽象路径名表示的文件。
boolean isHidden()
测试此抽象路径名指定的文件是否是一个隐藏文件。
示例代码:
package com.rl.file;
import java.io.File;
import java.io.IOException;
public class FileDemo3 {
public static void main(String[] args) throws IOException {
//renameFile();
justfy();
}
/
*
* 文件重命名
* @author renliang
* @throws IOException
/
public static void renameFile() throws IOException{
File fileb = new File(“c.txt”);
fileb.createNewFile();
File fileNew = new File(“b.txt”);
System.out.println(“重命名:”+fileb.renameTo(fileNew));
}
/
*
*
* @author renliang
* @throws IOException
/
public static void justfy() throws IOException{
File file = new File(“d:/aa.txt”);
if(!file.exists()){
file.createNewFile();
}
System.out.println(“是否存存在:”+file.exists());
System.out.println(“是否存是文件:”+file.isFile());
System.out.println(“是否存是目录:”+file.isDirectory());
System.out.println(“是否存是绝对路径:”+file.isAbsolute());
System.out.println(“是否存是可读:”+file.canRead());
System.out.println(“是否存是可写:”+file.canWrite());
System.out.println(“是否存是隐藏:”+file.isHidden());
}
}
5.文件的获取功能
1.文件的属性获取
String
getAbsolutePath()
返回此抽象路径名的绝对路径名字符串。
String
getPath()
将此抽象路径名转换为一个路径名字符串。
String
getName()
返回由此抽象路径名表示的文件或目录的名称。
long length()
返回由此抽象路径名表示的文件的长度。
long lastModified()
返回此抽象路径名表示的文件最后一次被修改的时间。
示例代码:
package com.rl.file;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo4 {
public static void main(String[] args) throws IOException {
//renameFile();
getTest();
}
/
*
*
* @author renliang
* @throws IOException
*/
public static void getTest() throws IOException{
File file = new File(“aa.txt”);
if(!file.exists()){
file.createNewFile();
}
System.out.println(“文件的绝对路径:”+file.getAbsolutePath());
System.out.println(“文件的相对路径:”+file.getPath());
System.out.println(“文件的名字:”+file.getName());
System.out.println(“文件的大小:”+file.length());
long lasttimes = file.lastModified();
//创建时间的对象
Date date = new Date(lasttimes);
//创建时间格式化的对象
SimpleDateFormat sdf = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
//格式化时间
String lastModifyTime = sdf.format(date);
System.out.println(“文件的最后修改时间:”+lastModifyTime);
}
}

2.目录的子文件获取
static File[]
listRoots()
列出可用的文件系统根。
File[]
listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
String[]
list()
返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
示例代码:
package com.rl.file;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo5 {
public static void main(String[] args) throws IOException {
//getRoot();
//getList();
getFile();
}
/**
*
* @author renliang
* @throws IOException
/
public static void getRoot() throws IOException{
//获得系统的跟目录
File[] files = File.listRoots();
for(File file : files){
System.out.println(file.isDirectory());
System.out.println(file.getAbsolutePath());
}
}
public static void getList() throws IOException{
File file = new File(“E:\我的课程\任亮”);
if(file.isAbsolute()){
//获得文件夹下的每一个文件和文件夹的名字
String [] names = file.list();
for(String name : names){
System.out.println(name);
}
}
}
public static void getFile() throws IOException{
File file = new File(“E:\我的课程\任亮”);
if(file.isAbsolute()){
//获得文件夹下的每一个文件和文件夹的名字
File [] files = file.listFiles();
for(File file1 : files){
System.out.println(“文件名:”+file1.getName()+ “\t 绝对路径:”+file1.getAbsolutePath());
}
}
}
}
3.递归查询文件夹的内部所有文件
package com.rl.file;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo7 {
//文件夹的级别
static int level = 0;
public static void main(String[] args) throws IOException {
File file = new File(“E:\我的课程\任亮\任亮-1-java基础阶段2\第13天集合”);
listFile(file);
}
public static void listFile(File file){
File [] files = file.listFiles();
level++;
for(File file1 : files){
for(int i = 0; i < level; i++){
System.out.print("\t");
}
System.out.println(file1.getName());
//如果当前的文件是目录
if(file1.isDirectory()){
//递归调用我们函数自己
listFile(file1);
}
}
level–;
}
}
如何使用递归的方式计算阶乘?
5!= 5
4321

N!= n
(n-1)!
package com.rl.file;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DiGuiDemo7 {
public static void main(String[] args) throws IOException {
int num = f(5);
System.out.println(num);
}
/**
* 递归要有跳出的条件
* @author renliang
* @param n
* @return
/
public static int f(int n){
if(n == 1){
return 1;
}else{
//5
4321
return n
f(n-1);
}
}
}

如何删除一个文件夹下的所有文件(不包括目录)?
package com.rl.file;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo9 {
public static void main(String[] args) {
File file = new File(“d:/wsCode/a”);
deleteFileAll(file);
System.out.println(“deleted”);
}
/**
* 删除指定文件夹下的所有文件(不包括目录)
* @author renliang
* @param file
/
public static boolean deleteFileAll(File file){
if(!file.exists()){
return false;
}
if(file.isFile()){
return false;
}else{
//获得目录下的所有文件对象
File[] files = file.listFiles();
for(File file1 : files){
if(file1.isDirectory()){
//如果是目录就递归
deleteFileAll(file1);
}else{
//如果是文件就删除
file1.delete();
}
}
return true;
}
}
}
如何删除一个文件夹下的所有文件(包括目录)?
package com.rl.file;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileDemo10 {
public static void main(String[] args) {
File file = new File(“d:/wsCode/a”);
deleteFolder(file);
System.out.println(“deleted”);
}
/
*
* 删除空文件夹
* @author renliang
* @param file
/
public static void deleteFolder(File file){
//删除文件夹内的所有文件和文件夹
deleteFileAll(file);
//删除空文件夹
file.delete();
}
/
*
* 删除指定文件夹下的所有文件(不包括目录)
* @author renliang
* @param file
*/
public static boolean deleteFileAll(File file){
if(!file.exists()){
return false;
}
if(file.isFile()){
return false;
}else{
//获得目录下的所有文件对象
File[] files = file.listFiles();
for(File file1 : files){
if(file1.isDirectory()){
//如果是目录就递归
deleteFileAll(file1);
//删除file1下的说有文件后就可以删除file1了
deleteFolder(file1);
}else{
//如果是文件就删除
file1.delete();
}
}
return true;
}
}
}

3.IO流
IO流在java中从输入输出角度分类:
1.输入流:从文件中读取数据,或者从键盘输入数据都属于输入流
2.输出流:向文件中写入数据。
IO流在java中从数据的角度来分类:
1.字符流
文本,我们能读的懂的都可以认为是字符流。比如:文章,java文件等等
字符输入流的超类:
Reader: 子类FileReader,BufferedReader
字符输出流的超类
Writer:子类FileWriter,BufferedWriter
2.字节流
二进制的数据,这种数据一般用文本打开我们读不懂。比如,图片文件,mp3文件。

字节输入流的超类:
InputStream: 子类FileInputStream
字节输出流的超类
OutputStream:子类FileOutputStream
1.字符流
1.输出流
使用字符流向一个文件输入helloworld。
分析:
步骤:1.创建文件
2.创建输出流对象
3.把流指向指定的文件
4.释放资源
1.FileWriter的普通构造器
输出字符流的FileWriter的构造器
FileWriter(File file)
根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName)
根据给定的文件名构造一个 FileWriter 对象。
实例代码:
package com.rl.io.cha;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class IOCharDemo {
public static void main(String[] args) {
writerFile1();
}
public static void writerFile(){
//创建文件
File file = new File(“a.txt”);
FileWriter fw = null;
try {
//创建输出流的对象
fw = new FileWriter(file);
//把内容写入文件
fw.write(“helloworld”);
//字符流的特点:清空缓存区,把内容写入到文件中
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
//close关闭输出流时会先清理缓存区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void writerFile1(){
FileWriter fw = null;
try {
//创建输出流的对象
fw = new FileWriter(“b.txt”);
//把内容写入文件
fw.write(“helloworld”);
//字符流的特点:清空缓存区,把内容写入到文件中
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
//close关闭输出流时会先清理缓存区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

向一个文件中输出100个HelloWorld
package com.rl.io.cha;
import java.io.FileWriter;
import java.io.IOException;
public class IOCharDemo1 {
public static void main(String[] args) {
writerFile1();
}
public static void writerFile1(){
FileWriter fw = null;
try {
//创建输出流的对象
fw = new FileWriter(“b.txt”);
for(int i = 0; i < 100; i++){
//把内容写入文件
fw.write(“helloworld”);
if(i%10 == 0){
//清空缓存区,把内容写入到文件中
fw.flush();
}
}
//把 缓冲区中残留的数据写入文件
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
//close关闭输出流时会先清理缓存区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.FileWriter的追加构造器
FileWriter(File file, boolean append)
根据给定的 File 对象构造一个 FileWriter 对象。
FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
示例代码:
package com.rl.io.cha;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class IOCharDemo2 {
public static void main(String[] args) {
writerFile1();
}
public static void writerFile1(){
FileWriter fw = null;
try {
//创建输出流的追加对象
//fw = new FileWriter(“b.txt”, true);
fw = new FileWriter(new File(“b.txt”), true);
for(int i = 0; i < 100; i++){
//把内容写入文件
fw.write(“我爱你”);
if(i%10 == 0){
//清空缓存区,把内容写入到文件中
fw.flush();
}
}
//把 缓冲区中残留的数据写入文件
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
//close关闭输出流时会先清理缓存区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
输出换行
把文本写入文件中\n代表换行
问题是不同的环境下换行的方式也不一样
Windows: \r\n
Linux:\n
Mac:\r
package com.rl.io.cha;
import java.io.FileWriter;
import java.io.IOException;
public class IOCharDemo3 {
public static void main(String[] args) {
writerFile1();
}
public static void writerFile1(){
FileWriter fw = null;
try {
//创建输出流的追加对象
fw = new FileWriter(“b.txt”);
for(int i = 0; i < 100; i++){
//内容换行为了兼容记事本我们建议使用\r\n
fw.write(“我爱你”+i+"\r\n");
if(i%10 == 0){
//清空缓存区,把内容写入到文件中
fw.flush();
}
}
//把 缓冲区中残留的数据写入文件
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
//close关闭输出流时会先清理缓存区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.FileWriter的写入功能
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)
写入字符串的某一部分。

示例代码:
package com.rl.io.cha;
import java.io.FileWriter;
import java.io.IOException;
public class IOCharDemo4 {
public static void main(String[] args) {
writerFile1();
}
public static void writerFile1(){
FileWriter fw = null;
try {
//创建输出流的追加对象
fw = new FileWriter(“test.txt”);
char[] chs = {‘a’,‘b’,‘c’,‘d’};
fw.write(chs);
//把一部分的字符的数组来写入到文件中,第一个参数是字符数组,第二个是开始索引, 第三个是从开始索引开始取得字符串的长度
fw.write(chs, 1, 3);
//通过int值来写入相应的字符
fw.write(100);
//写入字符串
fw.write(“100”);
//把一部分的字符串来写入到文件中,第一个参数是字符数组,第二个是开始索引, 第三个是从开始索引开始取得字符串的长度
fw.write(“helloworld”, 2, 2);
//把 缓冲区中残留的数据写入文件
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
//close关闭输出流时会先清理缓存区
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2.输入流
1.FileReader的构造器和读取
FileReader的爷爷类是Reader
FileReader(File file)
在给定从中读取数据的 File 的情况下创建一个新 FileReader。
FileReader(String fileName)
在给定从中读取数据的文件名的情况下创建一个新 FileReader。
范例:读取文件helloworld.txt打印到控制台
分析:
1.创建出入流对象FileReader
2.读取数据
3.关闭输入流
package com.rl.io.cha.reader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class IOCharReaderDemo {
public static void main(String[] args) {
readFile();
}
public static void readFile(){
FileReader fr = null;
try {
//创建fileReader对象
fr = new FileReader(new File(“helloworld.txt”));
//fr = new FileReader(“helloworld.txt”);
//读取单个字符,返回的是字符的ascii码
/int num = fr.read();
System.out.println((char)num);
num = fr.read();
System.out.println(num);
/
//如果文本读取完毕,最后没有字符会返回-1
int num = 0;
//通过循环来读取字符,判断的跳出循环的标志是num = -1
while((num = fr.read()) != -1){
//打印字符
System.out.print((char)num);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(fr != null){
try {
//释放资源
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
int read(char[] cbuf)
将字符读入数组。
通过字符数组来读取数据
f f s a d
示例代码:
package com.rl.io.cha.reader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class IOCharReaderDemo1 {
public static void main(String[] args) {
readFile();
}
public static void readFile(){
FileReader fr = null;
try {
//创建fileReader对象
fr = new FileReader(“helloworld.txt”);
//创建一个字符的数组
/char[] chs = new char[5];
//读取5个字符放入字符数组中,返回的数值是读取到的字符数量
int num = fr.read(chs);
//String str = new String(chs);
String str = new String(chs, 0, num);
System.out.println(num);
System.out.println(str);
System.out.println("---------------");
num = fr.read(chs);
//str = new String(chs);
str = new String(chs, 0, num);
System.out.println(num);
System.out.println(str);
System.out.println("---------------");
//读取到的是一个字符
num = fr.read(chs);
str = new String(chs, 0, num);
System.out.println(num);
System.out.println(str);
System.out.println("---------------");
//读取到的是一个字符
num = fr.read(chs);
System.out.println(num);
str = new String(chs, 0, num);
System.out.println(str);
/
//如果num的值是-1说明文件中的数据已经读完
char [] chs1 = new char[1024];
int len = -1;
//循环条件的判断的边界是fr.read(char[])如果返回-1说明文件已经读取完毕
while((len = fr.read(chs1)) != -1){
System.out.println(new String(chs1, 0, len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(fr != null){
try {
//释放资源
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.使用字符流来做文件的拷贝

范例:把一个java文件拷贝到项目根目录。
分析:1.创建字符输入流的对象
2.创建字符输出流对象
3.把输出流输入的数据写入输出流中
4.关闭资源
示例代码:
package com.rl.io.cha.copyfile;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class CopyFile {
public static void main(String[] args) {
copy1();
System.out.println(“done”);
}
/**
* 拷贝一个java文件方式1
* @author renliang
*/
public static void copy(){
Reader reader = null;
Writer writer = null;
try {
//创建文件读取对象
reader = new FileReader(“src/com/rl/io/cha/reader/IOCharReaderDemo.java”);
//创建写文件的对象
writer = new FileWriter(“IOCharReaderDemo.java”);
int num = -1;
while( (num = reader.read()) != -1){
writer.write(num);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//释放资源
try {
if(writer != null)
writer.close();
if(reader != null)
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

	}
}
public static void copy1(){
	Reader reader = null;
	Writer writer = null;
	try {
		//创建文件读取对象
		reader = new FileReader("src/com/rl/io/cha/reader/IOCharReaderDemo.java");
		//创建写文件的对象
		writer = new FileWriter("IOCharReaderDemo.java");
		//定义每次的读取的长度的对象
		int len = -1;
		//定义存储读取内容字符的数组
		char[] chs = new char[1024];
		//当len不等于-1就一直读取
		while((len = reader.read(chs)) != -1){
			//把读取的文件写入到目标文件中
			writer.write(chs, 0, len);
		}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}catch (IOException e) {
		e.printStackTrace();
	}finally{
		//释放资源
		try {
			if(writer != null)
				writer.close();
			if(reader != null)
				reader.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

}
3.高效缓存区输入输出流
1.BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
BufferedReader(Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流。
范例:使用高效缓冲区输入流来读取文件中的内容。

package com.rl.io.cha.buffer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
public static void main(String[] args) {
read1();
}
/**
* 使用高效缓存区输入流来读取文件
* @author renliang
/
public static void read(){
//创建创建文件输出流
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(“d.txt”);
//创建高效缓冲区的流对象
br = new BufferedReader(fr);
int num = -1;
while((num = br.read()) != -1){
System.out.print((char)num);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(br != null){
try {
//关闭缓存区的流就会自动的关闭FileWriter
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/
*
* 建议使用如下的方式读取文件
* @author renliang
*/
public static void read1(){
//创建创建文件输出流
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(“d.txt”);
//创建高效缓冲区的流对象
br = new BufferedReader(fr);
char[] chs = new char[1024];
int len = -1;
while((len = br.read(chs)) != -1){
System.out.print(new String(chs, 0, len));
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(br != null){
try {
//关闭缓存区的流就会自动的关闭FileWriter
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

扩展方法readLine读取一行数据

package com.rl.io.cha.buffer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo1 {
public static void main(String[] args) {
read1();
}
/**
* 建议使用如下的方式读取文件
* @author renliang
*/
public static void read1(){
//创建创建文件输出流
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(“d.txt”);
//创建高效缓冲区的流对象
br = new BufferedReader(fr);
String line = null;
//使用高效输入流可以读取一行数据
while((line = br.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(br != null){
try {
//关闭缓存区的流就会自动的关闭FileWriter
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

2.BufferWriter
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
构造器
BufferedWriter(Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
范例1:使用高效缓冲区流来向文件中写入一句话
package com.rl.io.cha.buffer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) {
writer();
}
/**
* 使用高效缓存区流来降d.txt的文件中写入,java太好学了,真简单。
* @author renliang
/
public static void writer(){
//创建创建文件输出流
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(“d.txt”);
//创建高效缓冲区的流对象
bw = new BufferedWriter(fw);
//输出数据
bw.write(“java太好学了,真简单。”);
//清空缓冲区
bw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(bw != null){
try {
//关闭缓存区的流就会自动的关闭FileWriter
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
高效缓冲区的输出流的扩展方法:
newline()可以换行
package com.rl.io.cha.buffer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo1 {
public static void main(String[] args) {
writer();
}
/
*
* 使用高效缓存区流来降d.txt的文件中写入,java太好学了,真简单。
* @author renliang
/
public static void writer(){
//创建创建文件输出流
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(“d.txt”);
//创建高效缓冲区的流对象
bw = new BufferedWriter(fw);
for(int i = 0; i < 10; i++){
//输出数据
bw.write(“java太好学了,真简单。”);
//换行,相当于\r\n
bw.newLine();
}
//清空缓冲区
bw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(bw != null){
try {
//关闭缓存区的流就会自动的关闭FileWriter
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
范例:使用高效缓冲流来复制文本文件
package com.rl.io.cha.copyfile;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
public class CopyFile1 {
public static void main(String[] args) {
copy();
System.out.println(“done”);
}
/
*
* 拷贝一个java文件方式1
* @author renliang
*/
public static void copy(){
Reader reader = null;
BufferedReader br = null;
Writer writer = null;
BufferedWriter bw = null;
try {
//创建文件读取对象
reader = new FileReader(“src/com/rl/io/cha/reader/IOCharReaderDemo.java”);
//创建高效缓冲区的输入流
br = new BufferedReader(reader);
//创建写文件的对象
writer = new FileWriter(“IOCharReaderDemo.java”);
//创建高效缓冲区的输出流
bw = new BufferedWriter(writer);
String line = null;
//读取数据并且写入另一个文件中
while((line = br.readLine()) != null){
bw.write(line);
//换行
bw.newLine();
}
bw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
//释放资源
try {
if(writer != null)
writer.close();
if(reader != null)
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Javase中IO字节流
1.字节流概述
字节输入流:InputStream:常用子类FileInputStream
字节输出流:OutputStream:常用子类FileOutputStream

2.OutputStream
FileOutputStream(File file)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。

范例:使用字节流向文件中写入”helloworld”
分析:使用三种写入方法

void write(byte[] b)
将 b.length 个字节从指定 byte 数组写入此文件输出流中。
void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
void write(int b)
将指定字节写入此文件输出流。
示例代码:
package com.rl.byt.out;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class OutputStreamDemo {
public static void main(String[] args) {
writeFile();
}
public static void writeFile(){
//创建字节输出流的对象
OutputStream out = null;
try {
//out = new FileOutputStream(“a.txt”);
//out = new FileOutputStream(new File(“a.txt”));
//out = new FileOutputStream(new File(“a.txt”), true);
out = new FileOutputStream(“a.txt”, true);
String str = “helloworld”;
//把字符串变成字节数组
byte[] bs = str.getBytes();
for(byte b : bs){
//写单个字节
out.write(b);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void writeFile1(){
//创建字节输出流的对象
OutputStream out = null;
try {
out = new FileOutputStream(“a.txt”);
String str = “helloworld”;
//把字符串变成字节数组
byte[] bs = str.getBytes();
//一次性把整个字节数组写入到文件中。
out.write(bs);
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void writeFile2(){
//创建字节输出流的对象
OutputStream out = null;
try {
out = new FileOutputStream(“a.txt”);
String str = “helloworld”;
//把字符串变成字节数组
byte[] bs = str.getBytes();
//把一部分的字节写到文件中。
out.write(bs, 0, 5);
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.InputStream
因为InputStream是抽象类,我们要学习的是它的子类。
构造器
FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
读取方法:
int read()
从此输入流中读取一个数据字节。
int read(byte[] b)
从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。
int read(byte[] b, int off, int len)
从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。
范例:使用字节输入流来读取文件并且输出到控制台。
package com.rl.byt.out;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamDemo {
public static void main(String[] args) {
readFile2();
}
/**
* 单个字节读取的效率低
* @author renliang
/
public static void readFile(){
//创建字节输入流的对象
InputStream in = null;
try {
in = new FileInputStream(“a.txt”);
//从文件中读取一个字节
int num = in.read();
System.out.println(num);
System.out.println((char)num);
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/
*
* 向整个的数组中去存储数据
* @author renliang
/
public static void readFile1(){
//创建字节输入流的对象
InputStream in = null;
try {
in = new FileInputStream(“a.txt”);
//定义一个字节数组
byte[] bs = new byte[1024];
//向字节数组中存储数据,返回读取的长度
int len = in.read(bs);
System.out.println(len);
System.out.println(new String(bs, 0, len));
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void readFile2(){
//创建字节输入流的对象
InputStream in = null;
try {
in = new FileInputStream(“a.txt”);
//定义一个字节数组
byte[] bs = new byte[1024];
//从输入字节流的对象中读取指定的字节数, 从字节输入流的来取三个字节,放入字节数组的从索引1的位置开始放
//0104101108
//[0, 104, 101, 108, 0, …]
int len = in.read(bs, 1, 3);
/for(byte b : bs){
System.out.print(b);
}
/
System.out.println(new String(bs, 1, len));
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
范例2:使用字节流来拷贝文件。
package com.rl.byt.out;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class CopyFileDemo {
public static void main(String[] args) {
copyFile1();
}
/
*
* 1.创建输入字节流的对象,输出流的对象
* 2.读取数据并且写入数据
* 3.关闭资源
* @author renliang
*/
public static void copyFile(){
InputStream in = null;
OutputStream out = null;
//创建文件输入流的对象
try {
in = new FileInputStream(“src/com/rl/byt/out/OutputStreamDemo.java”);
//创建文件输出流的对象
out = new FileOutputStream(“OutputStreamDemo.java”);
byte[] bs = new byte[1024];
//定义返回的读取的长度
int len = -1;
while((len = in.read(bs)) != -1){
//把字节数组中的数据写入到文件中
out.write(bs, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(out != null)
out.close();

			if(in != null)
				in.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * 1.创建输入字节流的对象,输出流的对象
 * 2.读取数据并且写入数据
 * 3.关闭资源
 * @author renliang
 */
public static void copyFile1(){
	InputStream in = null;
	OutputStream out = null;
	//创建文件输入流的对象
	try {
		in = new FileInputStream("d:/1.jpg");
		//创建文件输出流的对象
		out = new FileOutputStream("d:/wsCode/1.jpg");
		byte[] bs = new byte[1024];
		//定义返回的读取的长度
		int len = -1;
		while((len = in.read(bs)) != -1){
			//把字节数组中的数据写入到文件中
			out.write(bs, 0, len);
		}	
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		try {
			if(out != null)
				out.close();
				
			if(in != null)
				in.close();			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

}

4.字节流的高效缓冲区
BufferedInputStream(InputStream in)
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

范例:使用高效缓冲区来复制文件来比较性能

package com.rl.byt.out;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class BufferedCopyFileDemo {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
copyFile3();
long endTime = System.currentTimeMillis();
System.out.println(“耗时:”+(endTime - startTime)+“毫秒”);
}
/**
*耗时:8986毫秒
* 单个字符的复制
* @author renliang
*/
public static void copyFile(){
InputStream in = null;
OutputStream out = null;
//创建文件输入流的对象
try {
in = new FileInputStream(“d:/1.pdf”);
//创建文件输出流的对象
out = new FileOutputStream(“d:/wsCode/1.pdf”);
//定义返回的读取的长度
int len = -1;
while((len = in.read()) != -1){
//把字节数组中的数据写入到文件中
out.write(len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(out != null)
out.close();

			if(in != null)
				in.close();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * 耗时:42毫秒
 * 使用字节数组的方式的复制
 * @author renliang
 */
public static void copyFile1(){
	InputStream in = null;
	OutputStream out = null;
	//创建文件输入流的对象
	try {
		in = new FileInputStream("d:/1.pdf");
		//创建文件输出流的对象
		out = new FileOutputStream("d:/wsCode/1.pdf");
		byte[] bs = new byte[1024];
		//定义返回的读取的长度
		int len = -1;
		while((len = in.read(bs)) != -1){
			//把字节数组中的数据写入到文件中
			out.write(bs, 0, len);
		}		
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		try {
			if(out != null)
				out.close();		
			if(in != null)
				in.close();		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * 耗时:79毫秒
 * 使用高效缓冲区单个复制字符的方式
 * @author renliang
 */
public static void copyFile2(){
	InputStream in = null;
	OutputStream out = null;	
try {
		//创建文件高效缓冲区输入流的对象
		in = new BufferedInputStream(new FileInputStream("d:/1.pdf"));
		//创建文件输出流的对象
		out = new BufferedOutputStream(new FileOutputStream("d:/wsCode/1.pdf"));
		//返回的单个字符
		int len = -1;
		while((len = in.read()) != -1){
			//把字节数组中的数据写入到文件中
			out.write(len);
		}		
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		try {
			if(out != null)
				out.close();				
			if(in != null)
				in.close();			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * 耗时:6毫秒
 * 使用高效缓冲区复制字节数组的形式的方式
 * @author renliang
 */
public static void copyFile3(){
	InputStream in = null;
	OutputStream out = null;
	try {
		//创建文件高效缓冲区输入流的对象
		in = new BufferedInputStream(new FileInputStream("d:/1.pdf"));
		//创建文件输出流的对象
		out = new BufferedOutputStream(new FileOutputStream("d:/wsCode/1.pdf"));
		byte[] bs = new byte[1024];
		//定义返回的读取的长度
		int len = -1;
		while((len = in.read(bs)) != -1){
			//把字节数组中的数据写入到文件中
			out.write(bs, 0, len);
		}		
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		try {
			if(out != null)
				out.close();	
			if(in != null)
				in.close();		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

}
范例:从键盘输入学生信息存储到文件中,学生按着年龄排序。
Student:
package com.rl.byt.model;
public class Student implements Comparable {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public int compareTo(Student o) {
int num = this.age - o.getAge();
if(num == 0){
num = this.name.compareTo(o.getName());
}
return num;
}
}
ScannerTest
package com.rl.byt.model;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.TreeSet;
public class ScannerTest {
public static void main(String[] args) {
//定义学生的集合
TreeSet ts = new TreeSet();
//创建键盘输入对象
Scanner sc = new Scanner(System.in);
System.out.println(“请输入你要录入几个学生”);
//获得要输入的学生数量
int count = sc.nextInt();
for(int i = 0; i < count; i++){
sc = new Scanner(System.in);
System.out.println(“请输入学生的姓名:”);
//获得学生的姓名
String name = sc.nextLine();
System.out.println(“请输入学生的年龄:”);
//获得学生的年龄
Integer age = sc.nextInt();
//创建一个学生的对象
Student s = new Student();
s.setName(name);
s.setAge(age);
//把学生加入到集合中
ts.add(s);
}
//定义高效缓冲区的字符输出流
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(“student.txt”));
for(Student s : ts){
bw.write(s.getName()+"-----"+s.getAge());
bw.newLine();
}
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(bw != null)
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(“已写入”);
}
}
5.设计模式之装饰者模式
装饰者模式的目的是给类的功能增强。
继承也能给类的功能增强
Writer类是写文件的类,有三个子类TxtWriter,MP3Writer,AVIWriter
在writer中定义了写文件的标准,三个子类分别去实现Writer中的写方法
使用继承方式来对类增强
Writer
|——TxtWriter
|——MP3Writer
|——AVIWriter
通过继承方式加入高效缓冲区
Writer
|——TxtWriter
|——BufferedTxtWriter
|——MP3Writer
|——BufferedMP3Writer
|——AVIWriter
|——BufferedAVIWriter
|——RMWriter
|——BufferedRMWriter
如果想继续添加写文件的子类,如果想要对它做增强,还需要创建相应的缓冲区。
装饰器的设计模式可以解决我们使用高效缓冲区,但是不需要每一个写文件的类都添加高效缓冲区。
如果写文件的缓冲区是同样的原理,那么我们就可以把缓冲区抽取出来作为装饰器。
角色:
1.抽象构件角色(定义写文件标准):Writer
2.具体的构件角色(实现写文件标准):三个子类TxtWriter,MP3Writer,AVIWriter
3.装饰角色[抽象](高效缓冲区):注意:也可定义成抽象的,如果是抽象的就必须要有具体抽象角色
4.具体的装饰角色:来实现抽象装饰器中的增强方法。

抽象构件角色
public abstract class Writer {

/**
 * 写文件的方法
 * @author renliang
 */
public abstract void writeFile();

}
具体构件角色:
package com.rl.byt.decorator;
public class TxtWriter extends Writer {
public void writeFile() {
System.out.println(“写入文本文件”);
}
}
装饰器:
package com.rl.byt.decorator;
public class BufferedWriterFile extends Writer {
private Writer writer;
public BufferedWriterFile(Writer writer){
this.writer = writer;
}
public void writeFile() {
this.bufferedWrite();
writer.writeFile();
}
public void bufferedWrite(){
System.out.println(“加入高效缓冲区”);
}
}

抽象装饰角色:
package com.rl.byt.decorator;
public abstract class BufferedWriterFile extends Writer {
private Writer writer;
public BufferedWriterFile(Writer writer){
this.writer = writer;
}
public void writeFile() {
this.bufferedWrite();
writer.writeFile();
this.clean();
}
/**
* 高效缓存的方法
* @author renliang
*/
public abstract void bufferedWrite();
public abstract void clean();
}

具体装饰角色:
package com.rl.byt.decorator;
public class BufferedWriterFileImpl extends BufferedWriterFile {
public BufferedWriterFileImpl(Writer writer) {
super(writer);
}
public void bufferedWrite() {
System.out.println(“加入高效缓冲区”);
}
public void clean() {
System.out.println(“做清理工作”);
}
}
6.字符流和字节流的转换桥梁
1.字节流转换字符流
InputStreamReader
范例:把从键盘输入的文本写入到文件中
InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader。
InputStreamReader(InputStream in, Charset cs)
创建使用给定字符集的 InputStreamReader。

package com.rl.tyt.convert;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
//创建Scanner对象
Scanner sc = new Scanner(System.in);
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(“c.txt”));
String line = null;
while((line = sc.nextLine())!= null){
if(“exit”.equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

InputStreamReader用于InputStreamReader 是字节流通向字符流的桥梁
package com.rl.tyt.convert;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class ConverterInDemo {
public static void main(String[] args) {
InputStream is = System.in;
//要想使用字符流的高效缓冲区来操作字节流需要转换
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//定义要入的文件流
BufferedWriter bw = null;
String line = null;
try {
bw = new BufferedWriter(new FileWriter(“d.txt”));
while((line = br.readLine()) != null){
if(“exit”.equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}
2.字符流转换成字节流
OutputStreamWriter 是字符流通向字节流的桥梁
OutputStreamWriter(OutputStream out)
创建使用默认字符编码的 OutputStreamWriter。
OutputStreamWriter(OutputStream out, Charset cs)
创建使用给定字符集的 OutputStreamWriter。

范例:从一个文件中读取内容使用标准字节流来输出到控制台(使用字符串操作)
package com.rl.tyt.convert;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class ConverterOutDemo {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(“c.txt”));
//创建字符流向字节流转换的对象
bw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(bw != null){
bw.close();
}
if(br != null){
bw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

}

}
7.打印流
打印流:只做输出没有输入
打印流分为字节打印流和字符打印流
PrintWriter:字符打印流
特点
1.可以打印各种数据类型。
2.封装了字符输出流,还可以字符流和字节流的转换
3.可以使用自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作
4.可以直接向文件中写数据
范例:使用打印流向文件中打印数据
package com.rl.byt.print;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintDemo {
public static void main(String[] args) throws IOException {
//System.out.println(“helloworld”);
//BufferedWriter bw = new BufferedWriter(new FileWriter(“e.txt”));
PrintWriter pw = null;
try {
pw = new PrintWriter(“e.txt”);
pw.print(true);
pw.print(‘a’);
pw.print(12);
pw.print(“renliang”);
pw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
if(pw != null){
pw.close();
}
}
}
}
范例:从文件总读取数据并且打印在控制台
package com.rl.byt.print;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintDemo1 {
public static void main(String[] args) {
BufferedReader br = null;
PrintWriter pw = null;
try {
//定义缓冲区输入流对象
br = new BufferedReader(new FileReader(“student.txt”));

		//pw = new PrintWriter(System.out);
		//设置自动刷新的打印流
		pw = new PrintWriter(System.out, true);
		String line = null;
		while((line = br.readLine()) != null){
			pw.println(line);
			//pw.flush();
		}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		try {
			if(pw != null){
				pw.close();
			}
			if(br != null){
				br.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}	
}

}
范例:使用打印流来复制文本文件
package com.rl.byt.print;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintDemo2 {
public static void main(String[] args) {
BufferedReader br = null;
PrintWriter pw = null;
try {
//定义缓冲区输入流对象
br = new BufferedReader(new FileReader(“student.txt”));

		//pw = new PrintWriter(System.out);
		//设置自动刷新的打印流
		pw = new PrintWriter(new FileWriter("student1.txt"), true);
		String line = null;
		while((line = br.readLine()) != null){
			pw.println(line);
		}
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		try {
			if(pw != null){
				pw.close();
			}
			if(br != null){
				br.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}	
}

}
8.Properties类
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
特点:
1.继承于HashTable,是线程安全的键值对存储结构
2. Properties 可保存在流中或从流中加载
3. 只能保存字符串的键值对。
构造器:

Properties()
创建一个无默认值的空属性列表。

常用方法:
String
getProperty(String key)
用指定的键在此属性列表中搜索属性。
Object
setProperty(String key, String value)
调用 Hashtable 的方法 put。
void list(PrintWriter out)
将属性列表输出到指定的输出流。
void load(InputStream inStream)
从输入流中读取属性列表(键和元素对)。
void load(Reader reader)
按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。
void store(OutputStream out, String comments)
以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。
void store(Writer writer, String comments)
以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。
范例:使用Properties类存取
package com.rl.byt.prop;
import java.util.Properties;
public class PropTest {
public static void main(String[] args) {
//属性集类不支持泛型
Properties prop = new Properties();
prop.setProperty(“name”, “zhangsan”);
prop.setProperty(“age”, “10”);
prop.setProperty(“gender”, “male”);
System.out.println(prop);
String name = prop.getProperty(“name”);
String age = prop.getProperty(“age”);
String gender = prop.getProperty(“gender”);
System.out.println(name);
System.out.println(age);
System.out.println(gender);
}
}
范例:把属性类的对象数据写入文件
package com.rl.byt.prop;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
public class PropTest1 {
public static void main(String[] args) {
//属性集类不支持泛型
Properties prop = new Properties();
prop.setProperty(“name”, “zhangsan”);
prop.setProperty(“age”, “10”);
prop.setProperty(“gender”, “male”);
PrintWriter pw = null;
try {
pw = new PrintWriter(new FileWriter(“prop.txt”), true);
Set keys = prop.keySet();
for(Object obj : keys){
String key = (String) obj;
String value = prop.getProperty(key);
pw.println(key+"="+value);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(pw != null){
pw.close();
}
}
}
}
范例:把属性类的对象数据写入文件方式2
package com.rl.byt.prop;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.Set;
public class PropTest2 {
public static void main(String[] args) {
//属性集类不支持泛型
Properties prop = new Properties();
prop.setProperty(“name”, “zhangsan”);
prop.setProperty(“age”, “10”);
prop.setProperty(“gender”, “male”);
PrintWriter pw = null;
try {
pw = new PrintWriter(“prop1.txt”);
prop.list(pw);
} catch (IOException e) {
e.printStackTrace();
}finally{
if(pw != null){
pw.close();
}
}
}
}
范例:把属性类的对象数据写入文件方式3
package com.rl.byt.prop;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class PropTest5 {
public static void main(String[] args) {
//属性集类不支持泛型
Properties prop = new Properties();
prop.setProperty(“name”, “zhangsan”);
prop.setProperty(“age”, “10”);
prop.setProperty(“gender”, “male”);
FileWriter fw = null;
try {
fw = new FileWriter(“prop2.txt”);
prop.store(fw, null);
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
范例:从txt文件中加载属性信息
package com.rl.byt.prop;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class PropTest3 {
public static void main(String[] args) {
//属性集类不支持泛型
Properties prop = new Properties();
FileReader fr = null;
try {
fr = new FileReader(“prop.txt”);
//把字符流数据读到prop对象中
prop.load(fr);
//获得数据
String name = prop.getProperty(“name”);
String age = prop.getProperty(“age”);
String gender = prop.getProperty(“gender”);
System.out.println(name);
System.out.println(age);
System.out.println(gender);
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
范例:从txt文件中加载属性信息
package com.rl.byt.prop;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class PropTest4 {
public static void main(String[] args) {
//属性集类不支持泛型
Properties prop = new Properties();
FileReader fr = null;
try {
//实际项目中使用Properties的文件来存储数据,不使用txt
fr = new FileReader(“src/prop.properties”);
//把字符流数据读到prop对象中
prop.load(fr);
//获得数据
String name = prop.getProperty(“name”);
String age = prop.getProperty(“age”);
String gender = prop.getProperty(“gender”);
System.out.println(name);
System.out.println(age);
System.out.println(gender);
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
9.序列化流(对象流)
把对象以流的形式存储在硬盘上或者数据库中的过程就是写序列化流
序列化流:
对象输出流:
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。
对象输入流:
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectOutputStream的构造器
构造方法摘要
ObjectOutputStream(OutputStream out)
创建写入指定 OutputStream 的 ObjectOutputStream。
ObjectInputStream的构造器
构造方法摘要
ObjectInputStream(InputStream in)
创建从指定 InputStream 读取的 ObjectInputStream。

如果想序列化某个对象,那么这个对象所对应的类必须实现
类通过实现 java.io.Serializable 接口以启用其序列化功能,在序列化的过程中要手动指定要序列化的类的的serialVersionUID,这样可以在类改变后依然可以反序列化,否则会报错。
示例代码:
package com.rl.byt.seril;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class SerilDemo1 {
public static void main(String[] args) {
//writeObject1();
readObject1();
}
public static void writeObject(){
ObjectOutputStream oos = null;
try {
//创建序列化的流对象
oos = new ObjectOutputStream(new FileOutputStream(“person.txt”));
Person p = new Person();
p.setName(“任亮”);
p.setAge(30);
Person p1 = new Person();
p1.setName(“张三”);
p1.setAge(31);
Person p2 = new Person();
p2.setName(“李四”);
p2.setAge(29);
//调用序列化对象流的写入方法
oos.writeObject§;
oos.writeObject(p1);
oos.writeObject(p2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 反序列化
* @author renliang
/
public static void readObject(){
ObjectInputStream oos = null;
try {
//创建序列化的流对象
oos = new ObjectInputStream(new FileInputStream(“person.txt”));
//从反序列化的流中来读取数据
Object obj = oos.readObject();
Object obj1 = oos.readObject();
Object obj2 = oos.readObject();
Person p = (Person) obj;
System.out.println§;
System.out.println(obj1);
System.out.println(obj2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e){
e.printStackTrace();
}finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void writeObject1(){
ObjectOutputStream oos = null;
try {
//创建序列化的流对象
oos = new ObjectOutputStream(new FileOutputStream(“person.txt”));
ArrayList al = new ArrayList();
Person p = new Person();
p.setName(“任亮”);
p.setAge(30);
Person p1 = new Person();
p1.setName(“张三”);
p1.setAge(31);
Person p2 = new Person();
p2.setName(“李四”);
p2.setAge(29);
al.add§;
al.add(p1);
al.add(p2);
//调用序列化对象流的写入方法
oos.writeObject(al);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/
*
* 反序列化
* @author renliang
*/
public static void readObject1(){
ObjectInputStream oos = null;
try {
//创建序列化的流对象
oos = new ObjectInputStream(new FileInputStream(“person.txt”));
Object obj = oos.readObject();
ArrayList al = (ArrayList) obj;
for(Person p : al){
System.out.println§;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e){
e.printStackTrace();
}finally{
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
10.字符编码
存储:
在计算机中存储字符都是存储的字符所对应的数值以二进制的形式表示。
展示:
去相关的编码表中去查找该值(存储的值)所对应的字符。

常见的:
ASCII表:
用7bit来表示存储数据
ISO-8859-1:拉丁码表
用8bit来表示
GB2312:
简体中文编码(国标码)
GBK:
gb2312做了增强
GB18030:
对GBK做了增强
BIG5:
支持繁体
Unicode:
支持多种国家的语言,这是国际标准。用2个字节来存储。
不管是什么字符都用2个字节,会有浪费。
UTF-8:
支持多种国家的语言,针对不同的字符的范围给出不同的字节表示。
0,a,A用一个字符存储
中间的范围用二个字节
中文就使用3个字节。

	写入的编码和读取的编码必须要一致,否则会有乱码。

范例:使用GBK的编码方式来写入文件。
package com.rl.byt.charset;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class CharsetDemo {
public static void main(String[] args) {
//printCharset();
readCharset();
}
public static void printCharset(){
OutputStreamWriter ow = null;
try {
ow = new OutputStreamWriter(new FileOutputStream(“2.txt”), “UTF-8”);
ow.write(“中国”);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(ow != null){
try {
ow.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void readCharset(){
InputStreamReader ow = null;
try {
ow = new InputStreamReader(new FileInputStream(“2.txt”), “UTF-8”);
char[] chs = new char[1024];
int len = ow.read(chs);
System.out.println(new String(chs, 0, len));

	} catch (UnsupportedEncodingException e) {
		e.printStackTrace();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}finally{
		if(ow != null){
			try {
				ow.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

}
字符串的编码问题:
package com.rl.byt.charset;
import java.io.UnsupportedEncodingException;
public class CharsetDemo1 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = “中国”;
//使用默认的编码来编码(gbk)
byte[] bsGbk = str.getBytes();
//使用UTF-8来编码
byte[] bsTtf8 = str.getBytes(“UTF-8”);
//打印编码值
printByte(bsGbk);
//打印编码值对应的字符(默认编码)
System.out.println(new String(bsGbk));
//打印用UTF-8编码后的编码值
printByte(bsTtf8);
//打印UTF-8编码对应的字符串
System.out.println(new String(bsTtf8, “UTF-8”));
}

public static void printByte(byte[] bs){
	for(byte b : bs){
		System.out.print(b+"  ");
	}
}

}
javase线程详解
1.线程概述
进程:计算机中特定功能的程序在数据集上的一次运行。
线程:线程是进程的一个单元。
多线程:一个进程中有多个线程在同时运行,如迅雷下载,迅雷软件的一次运行就是一个进程,那么在迅雷中可以同时下载多个电影,这就是多线程(每一个下载都是一个线程)
Jvm是多线程的,在我们运行jvm的时候后台会运行垃圾回收的线程,来清理没有被引用的对象。

2.线程的实现
1.线程实现的第一种方式
创建新执行线程有两种方法。一种方法是将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。
线程启动的 时候使用线程的start方法而不是run
package com.rl.thread;
public class CountThread extends Thread {
/**
* 线程的执行体
*/
public void run() {
for(int i = 0; i < 50; i++){
System.out.println(this.getName()+"-----hello"+i);
}
}
}
测试线程
package com.rl.thread;
public class ThreadDemo {
public static void main(String[] args) {
//创建线程的实例对象
CountThread ct = new CountThread();
CountThread ct1 = new CountThread();

	//启动线程
	ct.start();
	ct1.start();	
}

}
2.线程实现的第二种方式
创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。
示例代码:
package com.rl.thread;
public class CountThread1 implements Runnable {
public void run() {
for(int i = 0; i < 50; i++){
//输出线程名字 System.out.println(Thread.currentThread().getName()+"-----hello"+i);
}
}
}
测试代码:
package com.rl.thread;
public class ThreadDemo1 {
public static void main(String[] args) {
/**
* 创建两个线程
*/
CountThread1 ct = new CountThread1();
//Thread t1 = new Thread(ct, “线程1”);
Thread t1 = new Thread(ct);

	CountThread1 ct1 = new CountThread1();
	//Thread t2 = new Thread(ct1, "线程2");
	Thread t2 = new Thread(ct1);
	
	t1.start();
	t2.start();
}

}
3.线程的执行原理

线程的并发执行通过多个线程不断的切换CPU的资源,这个速度非常快,我们感知不到,我们能感知到的就是三个线程在并发的执行。
4.线程的生命周期
1.新建: 线程被new出来
2.准备就绪:线程具有执行的资格,即线程调用了start(),没有执行的权利
3.运行:具备执行的资格和具备执行的权利
4.阻塞:没有执行的资格和执行权利
5.销毁: 线程的对象变成垃圾,释放资源。

					Start()

		sleep时间到	        等CPU	抢到CPU
		notify()									run()结束
					sleep()
					wait()						stop()

5.并发
互联网的项目中存在着大量的并发的案例,如卖火车票,电商网站。
范例:火车站有100张票,4个窗口同时买票。
分析:4个窗口是4个线程同时在运行,100票是4个线程的共享资源。
采用继承Thread来实现

并发安全性问题:
线程1 线程2

解决方案:

针对线程的安全性问题,我们需要使用同步(就是要加锁,共享资源只能一个人同时访问)锁。
语法:
synchronized(锁对象){
//操作共享资源的代码
}
同步代码加在什么地方?
1.代码被多个线程访问
2.代码中有共享的数据
3.共享数据被多条语句操作。
代码:
package com.rl.tickets;
/**

  • 买票的窗口
  • @author renliang

/
public class SaleTicket extends Thread{
private String name;
public SaleTicket(String name) {
super(name);
}
/
*
* 100张票是共享的数据
/
private static int tickets = 100;
/
*
* 同步锁(同步钥匙)对象
/
private static Object obj = new Object();
public void run() {
while(true){
//同步代码块
synchronized (obj) {
if(tickets > 0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+“正在卖第”+tickets–+“张票”);
}else{
System.out.println(“票已经售完”);
break;
}
}
}
}
}
Synchronized同步代码块的锁对象可以是任意类对象(线程的实现方式是使用继承于Thread),这个对象必须是线程类共享(静态的)
Synchronized是可以加在方法上,如果是静态方法Synchronized的所对象就是类的类对象,如果不是静态的方法,Synchronized如果加在对象方法上,那么他的锁是this
示例代码:
package com.rl.tickets1;
/
*

  • 买票的窗口
  • @author renliang

/
public class SaleTicket extends Thread{
private String name;
public SaleTicket(String name) {
super(name);
}
/
*
* 100张票是共享的数据
/
private static int tickets = 100;
/
*
* 同步锁(同步钥匙)对象
/
//private static Object obj = new Object();
private static A a = new A();
public void run() {
while(true){
int i = 0;
if(i%2 == 0){
//同步代码块
synchronized (SaleTicket.class) {
if(tickets > 0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.getName()+“正在卖第”+tickets–+“张票”);
}else{
System.out.println(“票已经售完”);
break;
}
}
}else{
//同步代码块
saleTickets();
}
i++;
}
}
/
*
* 静态方法的synchronized锁是当前类的类对象
* @author renliang
/
public synchronized static void saleTickets(){
if(tickets > 0){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+“正在卖第”+tickets–+“张票”);
}else{
System.out.println(“票已经售完”);
}
}
}
class A{
}
代码2:
package com.rl.tickets2;
/
*

  • 买票的窗口
  • @author renliang

/
public class SaleTicket implements Runnable{
/
*
* 100张票是共享的数据
*/
private int tickets = 100;
//private Object obj = new Object();
public void run() {
while(true){

		int i = 0;
		if(i%2 == 0){
			//同步代码块
			synchronized (this) {
				if(tickets > 0){
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票");
				}else{
					System.out.println("票已经售完");
					break;
				}
			}
		}else{
			//同步代码块
			saleTickets();
		}
		i++;		
	}
}	
/**
 * 非静态方法的synchronized锁是当前对象
 * @author renliang
 */
public synchronized void saleTickets(){
	if(tickets > 0){
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets--+"张票");
	}else{
		System.out.println("票已经售完");
	}
}

}
6.线程的休眠
线程的休眠是很必要的,在做服务端的时候为了减少服务器的压力我们需要休眠
如果休眠是在同步代码块中执行,休眠不会让出锁对象。
package com.rl.sleep;
/**

  • 买票的窗口
  • @author renliang

/
public class SaleTicket implements Runnable{
/
*
* 100张票是共享的数据
*/
private int tickets = 100;
//private Object obj = new Object();
public void run() {
while(true){
//同步代码块
synchronized (this) {
if(tickets > 0){
try {
Thread.sleep(3000);
System.out.println("------------");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+“正在卖第”+tickets–+“张票”);
}else{
System.out.println(“票已经售完”);
break;
}
}
}
}
}
7.线程间的通信
生产者和消费者

生产者线程 消费者线程

生产者生成水果,如果水果没有被买走那么就不生产处于等待状态,如果水果被消费者买走就的时候消费者会通知生产者告诉他我们已经把水果买走了请生产,消费者同理,如果水果已经生产出来那么就买走,买走之后再通知生产者水果已经没了请生产。
注意:
1.线程间的通信共享数据一定要有同步代码块synchronized
2.一定要有wait和notify,而且二者一定是成对出现。
3.生产者和消费者的线程实现一定是在while(true)里面
示例代码:
生产者:
package com.rl.tx;
public class ProductFruit implements Runnable{
private Fruit fruit;
public ProductFruit(Fruit fruit) {
super();
this.fruit = fruit;
}
public void run() {
while(true){
//有共享的数据,多个线程操作共享的数据,必须使用锁
synchronized (fruit) {
//如果水果已经存在那么生产者就不生成,等待着消费者买走水果在生成
if(fruit.isExsit()){
try {
//当前生产水果的线程被挂起变成阻塞状态
fruit.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(fruit.getName()+“水果被生产出来”);
//把水果的状态变成存在
fruit.setExsit(true);
//唤醒等待买水果的线程
fruit.notify();
}
}
}
}
消费者
package com.rl.tx;
public class BuyFruit implements Runnable{
private Fruit fruit;
public BuyFruit(Fruit fruit) {
super();
this.fruit = fruit;
}
public void run() {
while(true){
//有共享的数据,多个线程操作共享的数据,必须使用锁
synchronized (fruit) {
if(!fruit.isExsit()){
try {
fruit.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(fruit.getName()+“水果被买走”);
fruit.setExsit(false);
//唤醒生产者线程
fruit.notify();
}
}
}
}
8.线程的优先级
我们可以通过public final void setPriority(int newPriority)
来设置线程的优先级,但是优先级并不是绝对的,只是先对来说比其他的线程得到CPU的资源机会多一些。
示例代码:
package com.rl.prio;
public class PrioTest {
public static void main(String[] args) {
PrioThread pt = new PrioThread();
PrioThread pt1 = new PrioThread();
PrioThread pt2 = new PrioThread();

	/*System.out.println(pt.getPriority());
	System.out.println(pt1.getPriority());
	System.out.println(pt2.getPriority());*/	
	pt2.setPriority(10);	
	pt.start();
	pt1.start();
	pt2.start();
}

}
9.加入线程
join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行
void join()
等待该线程终止。
package com.rl.join;
public class JoinTest {
public static void main(String[] args) {
JoinThread pt = new JoinThread();
JoinThread pt1 = new JoinThread();
JoinThread pt2 = new JoinThread();
pt2.start();
try {
//join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行
pt2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
pt.start();
pt1.start();
}
}
10.等待线程
static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
当前的线程从运行阶段回到就绪阶段,目的是把CPU的资源让给其他的线程。
package com.rl.yield;
public class YieldThread extends Thread{
public void run() {
for(int i = 0; i < 50; i++){
System.out.println(this.getName()+“正在运行”+i);
//当前的线程回到就绪的状态,让出CPU
Thread.yield();
}
}
}
11.守护线程
void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。
守护线程会随着主线程的结束而结束。
package com.rl.daemon;
public class DaemonTest {
public static void main(String[] args) {
DaemonThread pt = new DaemonThread();
DaemonThread pt1 = new DaemonThread();
pt.setDaemon(true);
pt1.setDaemon(true);
pt.start();
pt1.start();
for(int i = 0 ; i < 10; i++){
System.out.println(Thread.currentThread().getName()+“主线程正在运行”+i);
}
}
}
12.线程死锁

示例代码:
package com.rl.dielock;
public class DieLockDemo implements Runnable{
private boolean flag;
public DieLockDemo(boolean flag) {
super();
this.flag = flag;
}
public void run() {
if(flag){
synchronized (Lock.lock1) {
System.out.println(“线程1执行拿到第一把所”);
synchronized (Lock.lock2) {
System.out.println(“线程1执行拿到第二把所”);
}
}
}else{
synchronized (Lock.lock2) {
System.out.println(“线程2执行拿到第二把锁”);
synchronized (Lock.lock1) {
System.out.println(“线程2执行拿到第一把锁”);
}
}
}
}
}
在做线程开发的时候要避免出现死锁。
网络编程
1.计算机网络
是指将地理位置不同的具有独立功能的多台计算机以及外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件以及通信的协议的管理下,实现资源共享和信息传递的计算机系统。
2.网络编程
就是用来实现网络互通的不同计算机运行程序之间进行数据的交换的编程。
3.网络模型
OSI(模型):七层协议
应用层 你好
表示层
会话层
传输层
网络层
数据链路层
物理层 01010010

TCP/IP(模型)
应用层
传输层
网际层
主机至网络层

2.网络通信的三要素
1.IP地址

Ip的最大值233.255.255.255
可以设置的区间是1.0.0.0-233.255.255.255
使用docs命令来查看ip地址:
Ipconfig

如果查看要通信的主机ip是否畅通:
Ping [ip]

2.端口号
用于标识进程的逻辑地址,不同的进程端口不同。
如何查看端口号:
使用docs命令netstat –ano

如果我们要和某一个计算的应用程序通信那就必须指定这台计算机的IP地址和这个应用程序的端口号
Ip:port,如192.168.1.103:8080
端口的值的范围:0—65535,其中0—1024是系统使用的端口,我们不要使用1024之前的端口。
3.传输的协议

协议:就是计算机通信的规则。

常见的有两种协议:
TCP和UDP协议
UDP:
将数据源和目的地封装到数据包中,不需要建立连接。
每个数据包的大小限制在64k。
因为不建立连接,所以安全性差,速度快。
TCP:
建立连接形成传输数据的通道,然后再传输数据,通过三次的握手。
安全性高,效率低。
3.InetAddress类
InetAddress是用于管理IP的类
没有构造器
1.单例模式
2.根据静态的方法来返回该对象

static InetAddress
getLocalHost()
返回本地主机。
String
getHostAddress()
返回 IP 地址字符串(以文本表现形式)。
String
getHostName()
获取此 IP 地址的主机名。
static InetAddress
getByName(String host)
在给定主机名的情况下确定主机的 IP 地址。
示例代码:
package com.rl.net;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class InetAddressDemo {
public static void main(String[] args) throws UnknownHostException {
getOtherHost();
}
public static void getHost() throws UnknownHostException{
InetAddress ia = InetAddress.getLocalHost();
//返回主机的ip
String ip = ia.getHostAddress();
//返回主机名
String name = ia.getHostName();
System.out.println(“ip:”+ip);
System.out.println(“主机名:”+name);
/ip:192.168.1.103
主机名:renliang-PC
/
}
public static void getOtherHost() throws UnknownHostException{
//InetAddress ia = InetAddress.getByName(“192.168.1.104”);
InetAddress ia = InetAddress.getByName(“IGGWXT5GR5DT7WX”);
//返回主机的ip
String ip = ia.getHostAddress();
//返回主机名
String name = ia.getHostName();
System.out.println(“ip:”+ip);
System.out.println(“主机名:”+name);
/ip:192.168.1.104
主机名:IGGWXT5GR5DT7WX
/
}
}
4.Socket
Socket是网络编程提供的一种机制,通信的两端都要有socket,网络通信其实就是socket间的通信,数据在两个socket间的io流上通信

客户端 服务器端

1.UDP的socket通信
 Udp服务器端的步骤:
1.创建socket服务对象:
Udp的服务端的构造器
DatagramSocket(int port)
创建数据报套接字并将其绑定到本地主机上的指定端口。
2.接收数据:使用数据包的方式来接收,用到了DataGramPacket此类表示数据报包。
DatagramPacket(byte[] buf, int length)
构造 DatagramPacket,用来接收长度为 length 的数据包。

3.解析数据
解析数据包:

InetAddress
getAddress()
返回某台机器的 IP 地址,此数据报将要发往该机器或者是从该机器接收到的。
byte[] getData()
返回数据缓冲区。
int getLength()
返回将要发送或接收到的数据的长度。
示例代码:
package com.rl.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务端的套接字对象
DatagramSocket ds = new DatagramSocket(10000);
System.out.println(“服务端正在运行…”);
//接收数据包的字节数组
byte[] bs = new byte[1024];
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length);
//接收
ds.receive(dp);
//解析数据
InetAddress ia = dp.getAddress();
String ip = ia.getHostAddress();
//获得数据的长度
int len = dp.getLength();
//获得数据包中的数据
byte[] bs1 = dp.getData();
String result = new String(bs1, 0, len);
System.out.println(“ip地址是:”+ip+" 数据是:"+result);
//释放资源
ds.close();
}
}

4.释放资源
关闭套接字。

 upd客户端的步骤
1.创建服务端套接字
DatagramSocket()
构造数据报套接字并将其绑定到本地主机上任何可用的端口。
2.创建数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。
3.发送数据包
void send(DatagramPacket p)
从此套接字发送数据报包。
客户端代码:
package com.rl.udp;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的套接字对象
DatagramSocket ds = new DatagramSocket();
//准备数据(字节数组的方式)
byte[] bs = “你好漂亮啊”.getBytes();
InetAddress address = InetAddress.getByName(“192.168.1.103”);
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length, address, 10000);
//发送数据包
ds.send(dp);
System.out.println(“发送了:你好漂亮啊”);
//释放资源
ds.close();
}
}
把UDP代码改造成可以从键盘录入数据:
服务端:
package com.rl.udp1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务端的套接字对象
DatagramSocket ds = new DatagramSocket(10000);
System.out.println(“服务端正在运行…”);
while(true){
//接收数据包的字节数组
byte[] bs = new byte[1024];
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length);
//接收
ds.receive(dp);
//解析数据
InetAddress ia = dp.getAddress();
String ip = ia.getHostAddress();
//获得数据的长度
int len = dp.getLength();
//获得数据包中的数据
byte[] bs1 = dp.getData();
String result = new String(bs1, 0, len);
System.out.println(“ip地址是:”+ip+" 数据是:"+result);
if(“exit”.equals(result)){
break;
}
}
//释放资源
ds.close();
}
}
客户端:
package com.rl.udp1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的套接字对象
DatagramSocket ds = new DatagramSocket();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = br.readLine()) != null){
//准备数据(字节数组的方式)
byte[] bs = line.getBytes();
InetAddress address = InetAddress.getByName(“192.168.1.103”);
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length, address, 10000);
//发送数据包
ds.send(dp);
System.out.println(“发送了:”+line);
if(“exit”.equals(line)){
break;
}
}
//释放资源
ds.close();
}
}
聊天室程序:
服务端:
package com.rl.udp3;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
public class ServerThread implements Runnable{
private int port;
public ServerThread(int port) {
super();
this.port = port;
}
public void run() {
//创建服务端的套接字对象
DatagramSocket ds = null;
try {
ds = new DatagramSocket(port);
} catch (SocketException e) {
e.printStackTrace();
}
System.out.println(“服务端正在运行…”);
while(true){
//接收数据包的字节数组
byte[] bs = new byte[1024];
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length);
//接收
try {
ds.receive(dp);
} catch (IOException e) {
e.printStackTrace();
}
//解析数据
InetAddress ia = dp.getAddress();
String ip = ia.getHostAddress();
//获得数据的长度
int len = dp.getLength();
//获得数据包中的数据
byte[] bs1 = dp.getData();
String result = new String(bs1, 0, len);
System.out.println(“ip地址是:”+ip+" 说:\r\n"+result);
if(“exit”.equals(result)){
break;
}
}
//释放资源
if(ds != null)
ds.close();
}
}
客户端:
package com.rl.udp3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class ClientThread implements Runnable{
private int port;
public ClientThread(int port) {
super();
this.port = port;
}
public void run() {
//创建客户端的套接字对象
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
} catch (SocketException e) {
e.printStackTrace();
}
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
try {
while((line = br.readLine()) != null){

			//准备数据(字节数组的方式)
			byte[] bs = line.getBytes();
			
			InetAddress address =  InetAddress.getByName("192.168.1.103");
			//创建数据包
			DatagramPacket dp = new DatagramPacket(bs, bs.length, address, port);
			//发送数据包
			ds.send(dp);
			System.out.println("我:\r\n"+line);
			if("exit".equals(line)){
				break;
			}
		}
	} catch (UnknownHostException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	if(ds != null)
	ds.close();
}

}
2.TCP的socket通信
开发步骤:
TCP服务端:
1.创建服务器Socket对象,指定端口
ServerSocket(int port)
创建绑定到特定端口的服务器套接字。

2.监听并获得客户端的对象socket
Socket
accept()
侦听并接受到此套接字的连接。

3.获得输入流
InputStream
getInputStream()
返回此套接字的输入流。
4.读取数据
5.释放资源
示例代码:
package com.rl.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws IOException {
//创建服务端的套接字
ServerSocket ss = new ServerSocket(10000);
//监听客户端的请求并且接受客户端的套接字
Socket s = ss.accept();
//获得输入流
InputStream in = s.getInputStream();
//获得数据
byte[] bs = new byte[1024];
int len = in.read(bs);
String result = new String(bs, 0, len);
System.out.println(“服务端接收的数据:”+result);
//释放资源
s.close();
ss.close();
}
}
TCP客户端:
开发步骤:
1.创建客户端socket对象
Socket(String host, int port)
创建一个流套接字并将其连接到指定主机上的指定端口号。
2.获得输出流
OutputStream
getOutputStream()
返回此套接字的输出流。
3.写数据
4.释放资源
示例代码:
package com.rl.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端的套接字
Socket s = new Socket(“192.168.1.103”, 10000);
//获得输出流
OutputStream out = s.getOutputStream();
out.write(“你好”.getBytes());
out.close();
s.close();
}
}
TCP服务端的反馈
服务端代码:
package com.rl.tcp1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws IOException {
//创建服务端的套接字
ServerSocket ss = new ServerSocket(10000);
//监听客户端的请求并且接受客户端的套接字
Socket s = ss.accept();
//获得输入流
InputStream in = s.getInputStream();
//获得输出流
OutputStream out = s.getOutputStream();
//创建高效缓存区字符流
BufferedReader br = new BufferedReader(new InputStreamReader(in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
String line = null;
while((line = br.readLine()) != null){
System.out.println(“接收到数据:”+line);
bw.write(line.toUpperCase());
bw.newLine();
bw.flush();
}
bw.close();
br.close();
//释放资源
s.close();
ss.close();
}
}
客户端代码:
package com.rl.tcp1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端的套接字
Socket s = new Socket(“192.168.1.103”, 10000);
//获得输出流
OutputStream out = s.getOutputStream();
InputStream in = s.getInputStream();
//获得从控制台输入的流
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
//服务器端返回的输入流
BufferedReader br = new BufferedReader(new InputStreamReader(in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
//读取控制台的数据
String line = null;
while((line = br1.readLine()) != null){
if(“exit”.equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();

		String result = br.readLine();
		System.out.println("服务端的反馈数据:"+result);
	}
	out.close();
	s.close();
}

}

猜你喜欢

转载自blog.csdn.net/qq_35336425/article/details/82825542