java基础知识,希望大佬给出建议

第一章 java语言特点

1、java版本

①javase标准版,用来完成简单的桌面游戏,比如:扫雷、纸牌、坦克大战
②javame小型版,用来完成移动端或者嵌入式设备
③javaee企业版,,用来完成企业级的需求

2、java的特点

简单性 、高性能 、编译性、 解释性、 面向对象、 分布处理、 健壮性、 安全性、 跨平台
-----跨平台:是指java的程序可以跨系统。
–因为java的运行至依赖java虚拟机(jvm)
–所以想在不同的操作系统运行java程序,只需要提供对应版本的JVM就可以运行java程序(java能跨平台是因为jvm能跨平台)
在这里插入图片描述

3、jdk

1、介绍:
–想要使用java语言进行软件开发,必须先安装jdk软件
–jdk有很多个版本,我们使用的版本建议不要一味的追求新版本,而是使用稳定 版本jdk8
2、下载和安装:略
3、配置:
–JAVA_HOME:用来指定jdk的安装位置
–path:是用来指定jdk中工具的位置
4检查:打开DOS窗口,执行java命令
输入java -version显示了jdk版型型号即安装好了

4、Eclipse

–1、介绍:是用于java开发的平台
–2重要概念:工作空间workspace,用来存储我们自己写的java代码

5、Eclipse的使用

1、先创建Java Project
–点击File-other-java Project-next-输入工程名称-Finish
–注意:工程名称一般是小写字母和数字组成,不要出现业余的中文汉字或者大写
–Project中,目前包含两部分:第一部分JRE系统库不要动,我们的源代码放在src下
2、创建包package
–选中src-右键-new-package-输入包名cn.tedu.hello-finish
–注意:包名必须符合两个要求:公司的域名倒着写+全小写
–注意:Eclipse工具里管理包名是通过.连接,但是workspace里是一层一层的目录包含关系
3、创建类class
–选中包名-右键-new-class-输入类名HelloWorld-finish
–注意:类名规范:符合驼峰命名法
–注意:java源代码文件的后缀名是.java
–4、使用Eclipse编程:
–快捷键:alt+/
main alt+/ --自动补齐main()
Syso alt+/ --自动补齐输出语句
F2 改名称
–测试:ctrl+f11 测试时的输出数据,都在console视图里

 --代码:
            package cn.tedu.hello;
			public class HelloWorld {
				public static void main(String[] args) {
					System.out.println("hello java123");
				}
			}
       --5、代码说明
             /*
              *第一行代码总体用来声明类所在包
              *package   --java的关键字,用来定义包
              *cn.tedu.hello   --包名  --全小写+公司域名倒着写
              *;       --是java语句的结束语
              */
package cn.tedu.hello;
//单行注释
/*多行注释*/
/*
*定义一个类
*public      --java的关键字。公共的公开的,修饰类是公共的
              * HelloWorld	--类名 -- 驼峰命名法
		 * { java代码 }
		 */
		public class HelloWorld {
			/*
			 * 定义main方法/主方法/主函数
			 * public --java的关键字,公共的公开的,修饰方法是公共的
			 * static --java的关键字,修饰方法是静态的
			 * void --java的关键字,空/无,修饰方法是没有返回值的
			 * main --方法名,固定的名字!!!
			 * () -- 是方法的标志
			 * String[] args--两部分由空格隔开 --统称是方法的参数
			 * { java 代码}
			 */
			public static void main(String[] args) {
				/*
				 * 向控制台输出数据
				 * System  --发出系统指令
				 * out   --执行输出动作
				 * println --输出后,换行
				 * () -- 是方法的标志
				 * "hello java123" -- 方法的参数
				 * ; --java语句的结束符
				 */
				System.out.println("hello java123");
				System.out.println("hello java123");
			}

第二章 数据类型 +运算符(运算法则)

1、前言

	1、java是一门强类型语言,java会把平常见到的数据分成多种数据类型
	2、标识符(名字):需要定义名字的地方
		 ----只能由4部分组成:字母、数字、下划线、$
		----不能以数字开头
		----严格区分大小写
		----要见名知意
	3、关键字
	    ----某些英语单词,在java的语法中有特殊含义,这些单词就称为关键字
	    ----java里有53个关键字,关键字都是小写
	4、注释:
			----Java代码的解释说明。不影响程序的运行,用于辅助读程。
			//单行注释
			/*    多行注释   */
			/**     文档注释     */
	5、变量
		在程序中,想要记录一些一直在改变的值,就需要定义变量值
		三要素:变量类型 变量名 变量值
			int age=18;
			String name ;  
			注意:变量名不能重复!

2、数据类型

1、基本类型(八种: byte short int long float double boolean char)+引用类型
在这里插入图片描述
2、变量如果是引用类型:String 、Car 、Person、Student、Teacher等
3、变量都有默认值:怎么决定变量的默认值是啥?要看变量的类型,
如果是八大基本类型,每种类型都有自己的默认值。
如果是引用类型,默认值都是null。
4、比如:Student s = new Student();
//s是引用类型的变量。默认值是null,但是现在保存的是对象的地址值。
5、变量使用时有一个原则是:就近原则。也就是说,当局部变量名和成员变量名相同时,会一直使用局部变量。
6、关键字
在这里插入图片描述

这个是伪代码,不能运行,知识作为说明
	class Test1{
			int sum ;//在类里方法外,是成员变量,默认值是0
			public void show(){
				int sum = 10;//在方法里,是局部变量
				sout(sum);//10,使用的是哪个sum?--就近原则,使用局部变量	
				//this相当于,在底层帮你完成一行代码 Test1 this = new Test1();
				sout(this.sum);//如果变量名相同时,用this调用成员变量
			}
		}

----练习1:求基本类型的取值范围:

package cn.tedu.basic;
		//这个类用来测试基本类型的取值范围
		public class Test1_Scope {

			public static void main(String[] args) {
				//需求:整型byte short int long	//变量三要素:变量类型 变量名 变量值
				byte max = Byte.MAX_VALUE ; //定义变量,记录byte最大值
				byte min = Byte.MIN_VALUE ; //定义变量,记录byte最小值
		//		System.out.println("max");//错,只能打印固定的三个字母max
				System.out.println(max);//127,打印变量的值
				System.out.println(min);//-128
				 
				short smax = Short.MAX_VALUE ;//定义变量,记录short最大值
				short smin = Short.MIN_VALUE ;//定义变量,记录short最小值
				System.out.println(smax);//打印变量的值
				System.out.println(smin);//打印变量的值

		//TODO	byte	  short   int	    long	        float	     double  char
		//工具类:Byte  Short 	 Integer	Long 	Float     Double  character
					int imax = Integer.MAX_VALUE ;
					int imin = Integer.MIN_VALUE ;
					System.out.println(imax);//2147483647
					System.out.println(imin);//	-2147483648
					
					long lmax = Long.MAX_VALUE ;
					long lmin = Long.MIN_VALUE ;
					System.out.println(lmax);//9223372036854775807
					System.out.println(lmin);//-9223372036854775808
					 
					//单精度,对小数位运算不精确
					float fmax = Float.MAX_VALUE ;
					float fmin = Float.MIN_VALUE ;
					System.out.println(fmax);//3.4028235E38
					System.out.println(fmin);//1.4E-45
					
					//双精度,对小数位运算非常精确
					double dmax = Double.MAX_VALUE ; 
					double dmin = Double.MIN_VALUE ; 
					System.out.println(dmax);//1.7976931348623157E308
					System.out.println(dmin);//4.9E-324
					
					//布尔型boolean    -- Boolean
					boolean b = true;
					boolean b2 = false;
					
					//字符型char,只能保存一个,而且用一对单引号引起来
					char c = 'a';//可以保存一个字母
					char c2 = '0';//可以保存一个数字
					char c3 = '中';//可以保存一个汉字!!!
					char c4 = 97;//可以保存一个数字
					System.out.println(c);
					System.out.println(c2);
					System.out.println(c3);
					
//char类型可以存储一个数字,但是,在使用时,还是会把数字  转成 字符 来使用字符本身。
//在使用时,底层会查询  ascii码表 ,查询到数字 对应 着的字符,然后使用字符
// ascii码表  只规定了数字0-127对应着的字符。128-65535默认对应的字符通通都是?
					System.out.println(c4);//a
				}
				
			}

----练习2:输入个人信息

package cn.tedu.basic;

			//这个类用来测试输入个人信息
			public class Test2_Info {
				public static void main(String[] args) {
					//我们需要把程序中的动态数据提取,形成变量来记录值
					String name = "蔡徐坤";
					int age = 10;
					String desc = "java培优";
					/*String name=new Scanner(System.in).nextLine();
					*int age =new Scanner(System.in).nextInt();
					*String study =new Scanner(System.in).nextLine();  
					*/ (动态接受键盘输入)
					//分析:哪些是动态数据,哪些是静态数据
			//		System.out.println("大家好,我叫渣渣辉,今年20岁,正在学习java");
					//如果想要完成拼接字符串的过程 ,用+ 完成。  "+?+"
					System.out.println("大家好,我叫"+name+",今年"+age+"岁,正在学习"+desc);
					
					//+拼接字符串
					System.out.println(name+"会唱跳rap");
					System.out.println("大家好,我叫"+name);
					System.out.println("大家好,我叫"+name+",今年20岁");
				}
			}

----练习3:圆形面积

package cn.tedu.basic;
			import java.util.Scanner;
			//这个类用来计算圆形面积
			//面积: 3.14 * r * r
			public class Test3_Area {

				public static void main(String[] args) {
			//		double r = 5.5 ; //定义变量,记录半径,值都被写死了,太不灵活了!!
			//		System.out.println( 3.14 * r * r  );
					
					//!!  动态接收键盘输入的值
					double r = new Scanner(System.in).nextDouble(); 
					
					double result = 3.14 * r * r ;//带入公式运算结果并打印
					System.out.println( result );
					
					//TODO 求圆的周长并打印
					double result2 = 2 * 3.14 * r;
					System.out.println(result2);
				}
			}

---- 练习4:变量交换
在这里插入图片描述

package cn.tedu.basic;

		//这个类用来测试变量交换
		//假设a=1,b=2,将a和b的值做交换
		public class Test4_Exchange {

			public static void main(String[] args) {
				int a = 1 ;
				int b = 2 ;

				// 交换值
				int c = a; // 把a的值交给c
				a = b; // 把b的值交给a
				b = c; // 把c的值交给b

				// +拼接字符串
				System.out.println("a=" + a + ",b=" + b);

				int m = 10;
				int n = 20;
				int t = m;
				     m = n;
				     n = t;
				System.out.println(m);
				System.out.println(n);

3、基本类型的字面值(5条)

1、整数字面值是int类型
–说明:整型类型有4种,但是你写了一个整数,默认是什么类型呢?–int类型
–注意:如果你的整数在int范围内,直接写就行,但是如果超出了int范围就会报错
2、浮点数的字面值是double类型
//报错,因为右面的9.9字面值就是double类型,左面的float是4个字节double是8字节,存不下。
//float b = 9.9 ;
3、byte,short,char三种比int小的整数可以用范围内的值直接赋值
byte c = 127;//c在byte范围内,可以直接赋值(-128~127)
//byte d = 128;//d超出了byte范围内,报错,由于已经超出了byte范围,右侧的128字面值是int类型
4、字面值后缀lfd / LFD
–说明:L 是可以把整数转成long类型
–说明:F 是可以把小数转成float类型
–说明:D 是可以把整数转成double类型
– long a = 99999999999L ;//把右侧的超出了int范围的这么大的整数,转成long类型
float b = 9.9F ;//把右侧的9.9从字面值的double类型 转成 float

		double x = 3D ;//把右侧的3从字面值int类型  转成了  double类型
		System.out.println(x);//3.0

5、进制前缀
–二进制:由0和1组成,数据的标志是有前缀0b开始的,如:0b0011
–十六进制:由0-9和a-f组成,数据的标志是有前缀0x开始的,如:0x99ac
在这里插入图片描述

4、基本类型间的互相转换

在这里插入图片描述
1、小转大:拿着小类型给大类型赋值,可以直接赋值也叫隐式转换
–byte short int long
–小 大
-float double
2、大转小:拿着大类型给小类型赋值,需要强转也叫显式转换
3、测试

		package cn.tedu.basic;
		import java.util.Scanner;
		//这个类用来计算圆形面积
		//面积: 3.14 * r * r
		public class Test3_Area {

			public static void main(String[] args) {
		//		double r = 5.5 ; //定义变量,记录半径,值都被写死了,太不灵活了!!
		//		System.out.println( 3.14 * r * r  );
				  
				//!!  动态接收键盘输入的值
				double r = new Scanner(System.in).nextDouble();        
				
				double result = 3.14 * r * r ;//带入公式运算结果并打印
				System.out.println( result );
				
				//TODO 求圆的周长并打印
				double result2 = 2 * 3.14 * r;
				System.out.println(result2);
			}
		}

5、 运算法则

一、 运算规则(5条)
1、计算结果的数据类型,与最大类型一致

package cn.tedu.basic;
		//这个类用来测五条运算规则
		public class Test1_Rule {
			public static void main(String[] args) {
				System.out.println( 3.14 * 5 );//结果和大类型double一致
				System.out.println( 3 / 2 );  //1,int/int得到的结果也是int类型
				System.out.println( 3D / 2 );//1.5 ,只要保证结果的类型是double类型
			}
		}

2、byte,short,char三种比int小的整数,运算时会先自动转换成int

package cn.tedu.basic;

		//这个类用来测五条运算规则
		public class Test1_Rule {
			public static void main(String[] args) {
				byte a = 1;
				byte b = 2;
				
		//报错,原因是右侧的两个值运算后的整体结果已经自动提升成int类型大类型了,给小类型byte类型的c赋值,需要强转
		//		byte c = a+b;
				byte c = (byte)(a+b) ;
	}
		}

3、整数运算溢出
–说明:类似于钟表。计算到最大值后,回到最小值重新开始运算。原因是运算的数据太大

--计算光速运行1年能运行多少米。3亿米/s
		package cn.tedu.basic;
		//这个类用来测五条运算规则
		public class Test1_Rule {
			public static void main(String[] args) {
				//秒-年
				//659193856,已经发生了整数运算溢出现象。为什么?--计算的整数已经远远的超出int范围
				//解决方案是,需要把整数运算从字面值的int类型扩大范围变成long类型。加后缀L
				System.out.println( 300000000L * 60 * 60 * 24 * 365);
			}
		}

4、浮点数运算不精确

package cn.tedu.basic;
		//这个类用来测五条运算规则
		public class Test1_Rule {
			public static void main(String[] args) {
				System.out.println(1-0.9);//0.09999999999999998
			}
		}

5、浮点数的特殊值

package cn.tedu.basic;
		//这个类用来测五条运算规则
		public class Test1_Rule {
			public static void main(String[] args) {
				System.out.println( 3.14/0 );//Infinity 无穷大
				System.out.println( 0/0.0 );//NaN
			}
		}

6、运算符

在这里插入图片描述
1、算数运算符
– ±*/ % ++ –
2、比较运算符 (结果是boolean类型)
== !=
3、逻辑运算符 (结果是boolean类型)
逻辑与:是并且的关系
单与:&
1 & 2 , 如果结果想要是true,要求1 和 2 都是true
双与/短路与:&& ,高效,是指可以把2短路掉,省去执行2的过程
1 && 2 , 如果1是false,此时,结果必然会是false,2就会被短路。
逻辑或:是或者的关系
单或:|
1 | 2 ,如果结果想要是true,要求1 或者 2 有一个为true就可以
双或/短路或:||,高效,是指可以把2短路掉,省去执行2的过程
1 || 2 , 如果1是true,此时,结果必然会是true,2就会被短路
4、三元运算符
– 1 ? 2 : 3
–说明:结果可能是2也可能是3,要看1了,如果1成立结果是2,如果1不成立,结果是3
5、赋值运算符
=
+=
-=
*=
/=
<<=左移赋值
>>>= 右移赋值

 a=a+4和a+=4的区别
       byte a = 1;
	// a=(byte) (a+4);//右侧int,左侧byte,大转小,强转。
	// a=(byte) (a+4);//右侧int,左侧byte,大转小,强转。
       a+=4;//会自动完成数据类型的转换 
       //注意:a=a+4和a+=4是有区别的!!
       System.out.println(a);

6、运算符练习
练习1:平年闰年
输入年号,判断是否是闰年。两个条件:
1、能被4整除,并且不能被100整除
2、或者能被400整除

package cn.tedu.basic;

		import java.util.Scanner;

		//这个类用来测试平年闰年
		public class Test4_RunNian {
			public static void main(String[] args) {
				//1、接收用户输入的年号int
				int year = new Scanner(System.in).nextInt();
				
				//2、判断,年号是平年还是闰年
				String desc ="平年";//设置默认是平年
				
				//开始判断,如果是闰年,需要修改desc的值
				//if( 判断条件 ){ 满足条件的代码 }
				//if( 判断条件1    ||    判断条件2 ){ 满足条件的代码 }
				//if( 小判断条件1 &&  小判断条件2   ||    能被400整除 ){ 满足条件的代码 }
				//if( ( 能被4整除 &&  不能被100整除 )  ||    能被400整除 ){ 满足条件的代码 }
				if( ( year % 4 == 0 &&  year % 100 != 0 )  ||    year % 400 == 0 ){ 
					desc = "闰年";//想要修改desc的值
				}
				System.out.println( year+"年是"+desc );
			}
		}

练习2:自增、自减
总结:1、符号在后,先使用再变化;2符号在前,先变化再使用

package cn.tedu.basic;
		//这个类用来测试 自增++、自减--
		public class Test2_Zizeng {
			public static void main(String[] args) {
				//自增++
				int a = 1;
				//符号在后,先使用再变化
				System.out.println(a++);//1
				
				int  b  = 1;
				//符号在前,先变化再使用
				System.out.println(++b);//2
				
				System.out.println(++a+b+a++); // 3+2+3=8
				
				//TODO 自减--
				int c = 0;
				//符号在后,先使用再变化
				System.out.println(c--);//0
				
				int d = 0;
				//符号在前,先变化再使用
				System.out.println(--d);//-1
				
				System.out.println(--c-d-c--); // -2+1+2=1
				
			}
			
		}

练习3:求两个数的最大值、三个数的最大值

package cn.tedu.basic;
		import java.util.Scanner;
		//这个类用来测试 获取最大值
		public class Test3_Max {
			public static void main(String[] args) {
				//定义两个变量
				int a = new Scanner(System.in).nextInt();
				int b = new Scanner(System.in).nextInt();
				int c = new Scanner(System.in).nextInt();
				
				//取大值  -- 三元运算符 
				//1 ? 2 : 3  -- 结果是2或者是3,如果1成立,结果就是2。如果1不成立,结果就是3
				int max = a > b ? a : b ;//比较两个数里的大值
				System.out.println("a和b中的大值是:"+max);//记录着两个数里的大值
				
				int result =  max >  c  ? max  :  c  ;//比较三个数里的大值
				System.out.println("a  b  c中的大值是:"+result);//记录的是三个数里的大值
				
				
			}
		}

第三章 结构+变量

1、if 分支机构(2种)

一、if 分支结构:相对于顺序结构而言,想要完成先判断再执行时,就需要使用分支结构
1、形式
单分支:适用于只有一个条件时
if(判读条件){
满足了判断条件后,进来执行的代码
}
多分支:适用于有两个条件时
if(判断条件){
满足条件的代码
}else{
不满足条件的代码
}
嵌套分支:适用于多个条件时
if(判断条件1){
满足条件的代码1
}else if(判断条件2){
满足条件的代码2
}else if(判断条件3){
满足条件的代码3
}else if(判断条件4){
满足条件的代码4

}else{
谁都不满足的代码5…
}
练习:商品打折
接收用户输入的原价。满1000打9折。满2000打8折。满5000打5折。

package cn.tedu.ifdemo;
		import java.util.Scanner;
		//这个类用来测试商品打折
		public class Test5_If {
			public static void main(String[] args) {
				//1,接收用户输入的原价 double
				double price = new Scanner(System.in).nextDouble();
				
				//2,分析:原价属于哪个档,并把折后价输出
				double discount = price ; //定义变量,记录折后价
				
				if( price > 5000 )  {//满5000
					discount = price * 0.5 ;//打5折
				}else if( price > 2000 )  {//满2000
					discount = price * 0.8;//打8折
				}else if( price > 1000 )  {//满1000打9折
					discount = price * 0.9;//打9折
				}esle{
				System.out.println("您输入的有误,请重新输入");
				}
				
				System.out.println("原价是:"+price);
				System.out.println("折后价是:"+discount);
				System.out.println("您的原价是"+price+",您的折后价是"+discount);
				
			}
		}

练习:统计学员分数

--接收用户输入的分数
			90分以上 优秀
			80~89 良好
			70~79 中等
			60~69 及格
			60分以下 不及格
		--测试
		package cn.tedu.ifdemo;
		import java.util.Scanner;
		//这个类用来测试  统计学员得分
		public class Test6_If2 {

			public static void main(String[] args) {
				//1,接收用户输入的分数
				int score = new Scanner(System.in).nextInt();
				//提高程序的健壮性,让程序无懈可击
				if(score >100  ||   score<0  ) {
					System.out.println("请您输入0~100以内的整数!");
					return ;//结束程序
				}
				if( score>=90 && score<=100  ) {//90分以上 优秀
					System.out.println("优秀");
				}else if(score>=80 && score<=89) {//80~89 良好
					System.out.println("良好");
				}else if(score>=70 && score<=79) {//70~79 中等
					System.out.println("中等");
				}else if(score>=60 && score<=69) {//60~69 及格
					System.out.println("及格");
				}else if(score<60) {	//60分以下 不及格
					System.out.println("不及格");
				}
				System.out.println("程序执行完毕!");
			}
		}

[了解]分支结构2:switch**
**1、概述:**也可以完成先判断后执行的业务
[switch语句后的控制表达式只能是short、char、int、long整数类型和枚举类型,不能是float,double和boolean类型。String类型是java7开始支持。
2、形式:
switch(只能接收整型类型的表达式){//byte short char int String
case 情况1:执行满足的代码1;
case 情况2:执行满足的代码2;
case 情况3:执行满足的代码3;
default 执行代码
}
练习:匹配数字

package cn.tedu.ifdemo;
		//这个类用来测试switch语法
		public class Test7_Switch {
			
			public static void main(String[] args) {
				int num = 200 ;
				switch(num) {//byte short int char String
				
					case 'a' : System.out.println("jack") ;  break;
					case 0 : System.out.println(0) ;  break;
					case 1 : System.out.println(1) ;  break;
					//如果找到了case,会继续向后执行掉所有case
					//怎么找到正确的就让程序停下来!!--break关键字用来结束程序
					case 2 : System.out.println(2) ;  break;
					case 3 : System.out.println(3) ;  break;
					case 4 : System.out.println(4) ;  break;
					
					default : System.out.println(99); //当上面的情况都不匹配时,就会来到default模块
				}
			}
		}

2、for 循环结构(3种)

一、循环结构1:for
1、概述
通常用来解决程序中的 重复的干一件事情 需求
2、形式
for(循环的开始位置;循环条件;更改条件){
循环体;
}

练习:打印0到10在这里插入图片描述

package cn.tedu.fordemo;

		//这个类用来测试for循环
		public class Test1_For {
			
			public static void main(String[] args) {
				//打印0到10
		//		for( 开始位置  ;  循环条件  ; 更改条件 ) {
				// int i = 0 定义变量,设置默认值从0开始
				//i 代表的是 当前获取到的值
				//i <= 10  表示i的最大值就是10,所以i的取值范围是01234...10
				//i++  每次都去修改i的值,依次递增 -- 自增
				for( int i = 0  ;  i <= 10  ; i++ ) {
					System.out.println(i);//输出当前获取到的值
				}
			}
		}

练习:打印10到0

package cn.qdm.qdm;

public class PangZi {

	public static void main(String[] args) {

		for (int i = 10; i >= 0; i--) {
			System.out.println(i);
		}
	}

}

练习:打印8,88,888,8888

package cn.qdm.qdm;

public class PangZi {

	public static void main(String[] args) {

		for (int i = 8; i <= 8888; i = i * 10 + 8) {
			System.out.print(i + " ,");
		}
	}

}

二、嵌套for循环
1、概述
在for循环里面,再套一个for循环,外面的for叫外循环,里面的for叫内循环,
外循环控制行,内循环控制列
2、形式
for(循环的开始位置;循环条件;更改条件){
循环体;
for(循环的开始位置;循环条件;更改条件){
循环体;
}
}
入门案例:

package cn.tedu.fordemo;
		//这个类用来测试嵌套for的入门案例
		public class Test2_For2 {
			public static void main(String[] args) {
				//当i=1时,输出i的值1  和   j的值 1 2 3 4 5
				//当i=2时,输出i的值2  和   j的值 1 2 3 4 5
				//当i=3时,输出i的值3  和   j的值 1 2 3 4 5
				//此时,用i表示外循环,j表示内循环
				//--特点1:外循环执行1次,内循环执行多次
				for(int i = 1; i<=3 ; i++ ) {//外循环,执行3次,i=1 2 3
					System.out.println(i);
					for(int j = 1; j<=5 ; j++) {//内循环,执行5次,j=1 2 3 4 5
						System.out.println(j);
					}
				}
				//-- 特点2:外循环控制行,内循环控制列
				for(int i =1 ; i <= 2 ; i++) {//外循环,执行2次
					for(int j = 1; j <= 3 ; j++) {//内循环,执行3次
						System.out.print("*");//同行展示
					}
					System.out.println();//换行
				}
			}
		}

练习:打印正方形

package cn.tedu.fordemo;
		//这个类用来测试 嵌套for练习
		public class Test3_For3 {
			public static void main(String[] args) {
				//打印正方形,五行五列*
				for(int i = 1 ; i <= 5 ; i++ ) {//外循环,控制行
					for(int j = 1 ; j<=5 ; j++ ) {//内循环,控制列
						System.out.print("*");//同行展示
					}
					System.out.println();//换行
				}
				
				
			}
		}	

练习:打印左直角三角形

*
		**
		***
		****
		*****
		//打印左直角三角形,五行,列不固定
		//i=1时,准备打印第一行,内循环j=1,j<=1,打印*,换行
		//i=2时,准备打印第二行,内循环j=1,j<=2,打印**,换行
		//i=3时,准备打印第三行,内循环j=1,j<=3,打印***,换行
		//i=4时,准备打印第四行,内循环j=1,j<=4,打印****,换行
		//i=5时,准备打印第五行,内循环j=1,j<=5,打印*****,换行
		for( int i = 1 ; i <= 5 ; i++) {
			for( int j = 1 ; j<=i ; j++ ) {//列一直在跟随行改变
				System.out.print("*");//同行展示
			}
			System.out.println();//换行
		}

练习:九九乘法表

        这个是伪代码,不能运行,知识作为说明
        1*1=1
		2*1=2 2*2=4
		3*1=3 3*2=6  3*3=9
		4*1=4 4*2=8  4*3=12 4*4=16
		5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
		6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
		7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
		8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
		9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
			for( int i = 1 ; i <= 9 ; i++) {
			for( int j = 1 ; j<=i ; j++ ) {
			//				System.out.print("3*2=6");//同行展示
			//				System.out.print("行*列=乘积");//同行展示
			//				System.out.print("i*j=i*j");//同行展示
							System.out.print(i+"*"+j+"="+i*j+"	");
						}
						System.out.println();//换行

三、break和continue
1、概述:用来结束循环!!
break:非常简单粗暴,在循环结构中使用,只要遇到了break,整个循环都要被结束
continue : 在循环结构中使用,结束当前循环,还能继续下一次循环
练习:找88
接收用户输入的100次数字,如果不是88继续输入,找到88就返回

package cn.tedu.breakcontinue;

		import java.util.Scanner;

		//这个类用来测试结束循环的方式
		public class Test4_Break {

			public static void main(String[] args) {
				for (int i = 0; i < 100; i++) {
					
					// 1、接收用户输入的100次数字
					int input = new Scanner(System.in).nextInt();

					// 2、如果不是88继续输入,找到88就返回
					if (input != 88) {// 不是88
						continue;// 继续输入,continue语句后,不允许出现代码,否则都是不可到达的代码!!
					} else if (input == 88) {// 是88
						System.out.println("中了");
						break;// 结束程序,break语句后,不允许出现代码,否则都是不可到达的代码!!
					}
					
				}
			}
		}

四、循环结构2while --先判断再执行
–1、格式
while(循环的判断条件){
循环体;
}
练习:猜数字 :产生一个随机数,和用户一直在输入的数字比较。

package cn.tedu.breakcontinue;

		import java.util.Random;
		import java.util.Scanner;

		//这个类用来测试while循环 -先判断再执行的循环结构
		public class Test5_While {
			public static void main(String[] args) {
				// 1、产生一个随机数-nextInt(m)-m是指产生m以内的随机数从0开始
				int random = new Random().nextInt(100);
				System.out.println(random);

				// while ( random >80 ) {// 要求循环条件永远成立,while(true) -- 叫死循环,必须给死循环设置出口!!
				//for(int i = 0 ; i>=0 ; i++) //for也能死循环,只不过写着麻烦一些
				while (true) {// 要求循环条件永远成立,while(true) -- 叫死循环,必须给死循环设置出口!!
					// 2、接收用户输入的数字
					int input = new Scanner(System.in).nextInt();

					// 3、比较
					if (input > random) {
						System.out.println("大了");
					} else if (input < random) {
						System.out.println("小了");
					} else if (input == random) {
						System.out.println("中了");
						break;// 设置死循环的出口!!
					}
				}

			}

		}

五、循环结构3do…while --先执行再判断–保证循环体代码最少执行1次
–1、格式
do{
循环体;
}while(循环的判断条件);
练习:猜数字

package cn.tedu.breakcontinue;

		import java.util.Random;
		import java.util.Scanner;

		public class Test6_DoWhile {
			public static void main(String[] args) {
				// 1、产生一个随机数-nextInt(m)-m是指产生m以内的随机数从0开始
				int random = new Random().nextInt(100);
				System.out.println(random);
				
				do {// 要求循环条件永远成立,while(true) -- 叫死循环,必须给死循环设置出口!!
					// 2、接收用户输入的数字
					int input = new Scanner(System.in).nextInt();

					// 3、比较
					if (input > random) {
						System.out.println("大了");
					} else if (input < random) {
						System.out.println("小了");
					} else if (input == random) {
						System.out.println("中了");
						break;// 设置死循环的出口!!
					}
				}while (random>90);

			}

		}

3、变量

1、概念:可以改变的数,称为变量。一般通过三部分来描述一个变量。变量类型,变量名,变量值。其中三部分都是可以改变的,根据需要来确定即可。

变量的使用原则:就近原则。尽量控制到最小范围。。
2、局部变量
位置:是在局部位置(在方法里)
注意:必须手动初始化,来分配内存。如:int i=5;
作用域是方法中,出了方法就不能用

3、成员变量
位置:是在成员位置(类里方法外)
注意:不用初始化,也会自动被初始化成默认值。默认值规则和数组一样
作用域是整个类中,类消失了,变量才释放。
在这里插入图片描述在这里插入图片描述
测试

package cn.tedu.variable;

		//这个类用来测试变量的使用:使用时有就近原则
		public class Test1_Variable {
			//2、成员变量  -- 位置:在类里方法外  -- 作用范围是:整个类中   -- 初始化:不需要手动完成,都有默认值
			int age=10;
			static String name ;//成员变量,引用类型默认值都是null
			
			static byte a ;//成员变量,默认值0
			static short b ;//成员变量,默认值0
			static int c ;//成员变量,默认值0
			static long d ;//成员变量,默认值0
			static float e ;//成员变量,默认值0.0
			static double f ;//成员变量,默认值0.0
			static boolean g;//成员变量,默认值false
			static char h;//成员变量,默认值\u0000
			
			public static void main(String[] args) {
				//1、局部变量  -- 位置: 方法里  -- 作用范围是:在方法里  -- 初始化:必须手动完成
				int age=8;//赋值--初始化
				System.out.println(age);//3、当局部变量名和成员变量名相同时,在使用时,变量遵循就近原则,8。
				String name="rose";
				System.out.println(name);//rose,就近原则
				
				System.out.println(a);
				System.out.println(b);
				System.out.println(c);
				System.out.println(d);
				System.out.println(e);
				System.out.println(f);
				System.out.println(g);
				System.out.println(h);
				
				//判断条件中,g默认值是false,--!是运算符,用来对布尔值取反 - !true就是false - !false 就是true
				if(!g) System.out.println(666);
				
			}
		}

第四章 方法(方法调用、传参、返回值、重载)

方法概念:被命名的代码块,方法可以含参数可以不含参数,可以提高代码的复用性

1、方法调用

1、形式:方法修饰符 方法返回值 方法名([参数列表]){
java代码/方法体
}
在这里插入图片描述
练习:方法调用

package cn.tedu.method;

		//这个类用来测试方法的使用
		public class Test2_Method {
			public static void main(String[] args) {
				System.out.println(1);
				method() ; // 1、去调用了指定的方法
				System.out.println(2);// 1 3 4 5 2
			}
			
			//创建method()
			//方法修饰符  方法返回值  方法名([参数列表]){	java代码/方法体	}
			public static void method() {
				System.out.println(3);
				System.out.println(4);
				System.out.println(5);
			}
			
		}

2、方法传参

形式:方法修饰符 方法返回值 方法名([参数列表]){
java代码/方法体
}
练习:方法传参

package cn.tedu.method;
		//这个类用来测试  方法传参
		public class Test3_Method2 {
			public static void main(String[] args) {
				method(10);
				method2(5,10);//多个参数之间逗号隔开
				method3(1,2,"jack");
			}
			// 创建method3(),如果需要接收多个参数,用逗号隔开,java会自动匹配位置,注意:类型必须匹配
			public static void method3(int x,int y,String z) {
				//+ 如果是在整数间就做加法运算,如果是和字符串相加就做字符串拼接动作
				System.out.println(x+y+z);//3jack
			}
			// 创建method2(),如果需要接收多个参数,用逗号隔开,java会自动匹配位置,注意:类型必须匹配
			public static void method2(int m,int n) {
				System.out.println("m="+m);
				System.out.println("n="+n);
			}
			// 创建method()
			// public static void method(参数类型 参数名) {  // 注意:参数类型  必须和  传入的参数的类型 匹配!!
			public static void method(int a) {
				System.out.println("method()..."+a);
			}

		}

3、方法返回值

形式:方法修饰符 方法返回值 方法名([参数列表]){
java代码/方法体
}
返回值什么时候需要?
①需要计算,并且返回结果
②谁调用就返回给谁


返回值什么时候不需要?
①只是进行打印而已,不需要进行计算,也没有结果,用void
在这里插入图片描述
练习:方法返回值

package cn.tedu.method;

		//这个类用来测试 方法返回值
		public class Test4_Method3 {
			public static void main(String[] args) {
				int sum = method(5,10) ;//sum交给方法处理,结果是多少,告诉sum
				System.out.println(sum) ;
				
				String result = method2(1,2,"jack");//result的值,交给method2()决定
				System.out.println(result);//3jack
			}
			//TODO 创建method2()
			//方法的返回值类型  和  result变量  的类型一致
			public static String method2(int a,int b,String c) {
				return a+b+c;//把结果通过return关键字返回给调用位置
			}
			//创建method()
			//方法的返回值类型  和  sum变量  的类型一致
			public static int method(int a,int b) {
				//return关键字,用来把结果返回给 调用位置,并交给sum保存
				return a+b;
			}
			
		}

4、方法重载

1、概念:方法重载是指在一个类中定义多个同名的方法,但要求每个方法具有不同的参数列表(也就是说参数的个数和类型不同)。
重载的意义/好处:为了提高程序的灵活性,提高用户的体验;
方法重载需要满足以下几个条件:
在同一个类中
方法的名称相同
参数列表不同
方法重载有以下特点:
与访问修饰符和返回值类型无关
与异常无关

重载(Overload)和重写(Override)的区别

1、重载的规则:

①必须具有不同的参数列表。

②可以有不同的访问修饰符。

③可以抛出不同的异常。
2、重写方法的规则:

①参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重知载。

②返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。

③访问修饰符的限制一定要大于被重写方法的访问修饰符。

④重写方法一定不能抛出新的检查异常或道者比被重写方法申明更加宽泛的检查型异常。

三、类的关系上的区别:

重写是子类和父类之间的关系,是垂直关系;重载是同一个类中方法之间的关系,是水平关系。
练习:数值求和

package cn.tedu.overload;
		//这个类用来测试 方法重载现象:在同一类中,方法名相同+参数列表不同!!!!
		public class Test5_Overload {
			public static void main(String[] args) {
				add(1,2);
				add(10,"jack");
				add(10,5,"jack");
				add("jack",10,5);
			}
			//TODO  提供重载的add()
			public static void add(String a,int b,int c) {
				//a+b的+ 用来做字符串拼接,+c仍然拼成大串!
				System.out.println(a+b+c);//jack105
			}
			public static void add(int a,int b,String c) {
				//a+b其中+用来做加法运算。+c是用来做字符串拼接形成大串!
				System.out.println(a+b+c);//15jack
			}
			public static void add(int a,String b) {
				System.out.println(a+b);//10jack
			}
			public static void add(int a,int b) {
				System.out.println(a+b);//3
			}
		}

练习:数据打印

		package cn.tedu.overload;

		//这个类用来测试 方法重载现象:在同一类中,方法名相同+参数列表不同!!!!
		//重载的意义/好处:为了提高程序的灵活性,提高用户的体验。
		public class Test6_Overload2 {
			public static void main(String[] args) {
				print(10);//匹配int参数的print()
				print("10");//匹配String参数的print()
				print(10.0);//匹配double参数的print()
				print(true);//匹配boolean参数的print()
			}
			//TODO  提供重载的print()
			public static void print(boolean a) {
				System.out.println(a);
			}
			public static void print(double a) {
				System.out.println(a);
			}
			public static void print(String a) {
				System.out.println(a+1);//101
			}
			public static void print(int a) {
				System.out.println(a+1);//11
			}
		}

第五章 数组+数组工具类Arrays

1、数组

注意:
①:数组要先创建才能使用
②:所有引用类型变量,都可以赋值为一个null。但是代表其中什么也没有

  例如:
 	int[ ] a=null;//因为数组是引用类型,引用类型的默认值都是null,但是代表的是一个空数组
	//如果只是赋值为null,没有对数组进行new创建,会发生空指针异常。解决方案:补上new

1、概念:数组Array是用于储存多个相同类型数据的集合。想要获取数组中的元素值,可以通过元素的下标来获取,下标是从0开始的。
在这里插入图片描述
2、创建数组
---- 动态初始化(指定长度)
数字类型 [] 数组名称 =new 数组类型 [ 数组长度 ];
int[] a = new int[5];
----静态初始化(指定内容 )
数字类型 [] 数组名称 =new 数组类型 []{元素1,元素2,…};

数字类型 [] 数组名称 ={元素1,元素2,…};
int[] b = new int[]{1,2,3,4,5};
int[] c = {1,2,3,4,5};
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
练习:数组中存入hello

		package cn.tedu.array;
		//这个类用来测试  数组 入门
		//数组中存入hello
		public class Test7_Array {
			public static void main(String[] args) {
				//静态初始化
				char[] c = new char[] {'h','e','l','l','o'};
				char[] c2 =  {'h','e','l','l','o'};
				
				//动态初始化
				char[] c3 = new char[5];//数组有数据,只不过都是默认值\u0000
				c3[0]='h'; //修改下标为0的数据
				c3[1]='e'; //修改下标为1的数据
				c3[2]='l'; //修改下标为2的数据
				c3[3]='l'; //修改下标为3的数据
				c3[4]='o'; //修改下标为4的数据
				
				//目前,数组长度是5,下标从0开始,也就是下标最大值是4,那么有没有下标为5的元素呢?--没有!!
				//数组下标越界异常:java.lang.ArrayIndexOutOfBoundsException: 5
		//		c3[5]='x';//修改下标为5的数据
				
				System.out.println(c);
				System.out.println(c2);
				System.out.println(c3);
				
			}
		}

3、数组的长度
----length属性获取数组长度
----数组一旦创建,长度不可变
----允许0长度的数组
一、数组遍历(相当于for循环)
1、形式
for(下标的开始位置;<=数组的长度-1;下标递增){
//for(int i = 0 ; i <= a.length-1 ; i++ ){
代码;
}
练习:输出每个月的天数

		package cn.tedu.array;
		//这个类用来测试数组的遍历
		public class Test1_Array 31{
			public static void main(String[] args) {
				method1();//创建method调用,目的就是不想把所以的都写着main方法里面     输出每个月的天数
			}
			
			//创建method1()
			public static void method1() {
				//静态?动态?
				int[] a = {31,28,31,30,31,30,31,31,30,31,30,31} ;
				
				//for(下标的开始位置;<=数组的长度-1;下标递增){}
				//i就代表了数组的下标,从0开始,到最大值11结束,依次递增
				for(int i = 0 ; i <= a.length -1 ; i++) {
		//			System.out.println("1月有31天");
					//i+1 是指 把下标的值从0-11,变成从1-12
					//a[i]是指,根据下标i获取对应的数据
					System.out.println(i+1+"月有"+a[i]+"天");
				}
				
			}
			
		}

练习:遍历数组,存入1到10

		package cn.tedu.array;
		//这个类用来测试数组的遍历
		public class Test1_Array {
			public static void main(String[] args) {
		//		method1();//输出每个月的天数
				method2();//遍历数组,存入1到10
			}
			
			//创建method2()
			public static void method2() {
				//1,创建数组,动态
				int a[] = new int[10] ;//刚创建好的数组有值,都是默认值0
				//2,遍历数组
				//for(下标的开始位置;<=数组的长度-1;下标递增){}
				//i就代表了数组的下标,从0开始,到最大值11结束,依次递增
				for(int i = 0 ; i < a.length ; i++ ) {
					a[i] = i+1 ; //根据下标,修改默认值
				}
				
				//3,查看数组里的数据
				System.out.println(a);//[I@15db9742,是数组在内存中的地址值
				
				//4,遍历数组并打印数据
				for(int i = 0 ; i < a.length ; i++) {
					System.out.println(a[i]);
				}
			}
				//创建method1()
			public static void method1() {
				//1,创建数组,静态
				int[] a = {31,28,31,30,31,30,31,31,30,31,30,31} ;
				
				//for(下标的开始位置;<=数组的长度-1;下标递增){}
				//i就代表了数组的下标,从0开始,到最大值11结束,依次递增
				for(int i = 0 ; i <= a.length -1 ; i++) {
		//			System.out.println("1月有31天");
					//i+1 是指 把下标的值从0-11,变成从1-12
					//a[i]是指,根据下标i获取对应的数据
					System.out.println(i+1+"月有"+a[i]+"天");
				}
				
			}
			
		}

练习:创建随机数组

package cn.tedu.array;
		import java.util.Random;
		public class Test1_Array {
			public static void main(String[] args) {
				method3();//创建随机数组
			}
			//创建method3()
			public static void method3() {
				//1,创建数组,动态
				int a[] = new int[5];
				
				//2,遍历数组,并修改值
				for(int i = 0 ; i < a.length ; i++) {
					a[i] = new Random().nextInt(100) ; //产生100以内的随机数,并给数组赋值
		//			System.out.println(a[i]);
				}
				
				//3,打印数组
				for (int i = 0; i < a.length; i++) {
					System.out.println(a[i]);
				}	
			}
			

2、数组工具类Arrays

1、Arrays.toString(数组)
概念:用来展示指定的数组里的所有数据,多个数据之间逗号隔开
格式:格式:[10, 14, 20, 46, 51]
2、Arrays.sort(数组)
概念:对数组进行排序
在这里插入图片描述

public static void main(String[] args) {
        int[] a = {57,20,64,82,2};
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
    }

在这里插入图片描述
3、Arrays.copyOf(数组,新的长度)
对数组进行复制

注意:sort没有返回值 ;copyOf有返回值
①sort()–是在不改变长度的前提下,把数据的位置进行交换,所以不需要返回值。又没改长度。
②是要进行数组的复制,复制时可能会改变数组长度(扩容/缩容),此时数组长度不能改,只能提供一个新数组作为返回值
测试:

package cn.tedu.array;
		import java.util.Arrays;
		//这个类用来测试数组工具类 Arrays
		//copyOf()有返回值    sort()没返回值   ?
		//原因是:数组一旦创建,长度不能变!!!但是数据是可以变换!!
		//sort()--是在不改变长度的前提下,把数据的位置进行交换,所以不需要返回值。又没改长度。
		//copyOf()--是要进行数组的复制,复制时可能会改变数组长度(扩容/缩容),此时数组长度不能改,只能提供一个新数组作为返回值
		public class Test2_Arrays {
			public static void main(String[] args) {
		//		method();//toString()
		//		method2();//sort()
				method3();//copyOf()
			}
			//copyOf() 用来完成数组的复制
			public static void method3() {
				//创建原数组
				int[] old = {1,2,3,4,5};
				
				//复制数组
				//copyOf(m,n)-m是原数组名,n是新数组的长度 
				//扩容: 是指新数组的长度  > 原数组长度时,会把数据复制完后,在末尾处扩充新的位置
				//缩容: 是指新数组的长度  < 原数组长度时,会把数据进行截取
				int[] now = Arrays.copyOf(old,8);
				int[] now2 = Arrays.copyOf(old, 3);
				
				//打印新数组
				System.out.println(Arrays.toString(now));//[1, 2, 3, 4, 5, 0, 0, 0]
				System.out.println(Arrays.toString(now2));//[1, 2, 3]
			}
			//sort()给无序数组进行排序
			public static void method2() {
				//1,创建无序的数组
				int[] a = {100,3,78,56,25};
				
				//2,给数据排序,从小到大
				Arrays.sort(a);		
				
				//3,展示数组中的数据 [3, 25, 56, 78, 100]
				System.out.println(Arrays.toString(a));
			}
			//toString()展示数组中的数据
			public static void method() {
				//1,创建数组,静态
				double a[] = {1.1,2.2,3.3,4.4,5.5};
				
				//2,查看数组里的数据
				//以前for循环遍历并打印
		//		for (int i = 0; i < a.length; i++) {
		//			System.out.println(a[i]);
		//		}
				//toString()用来展示指定的数组里的所有数据,多个数据之间逗号隔开
				//[1.1, 2.2, 3.3, 4.4, 5.5]
				System.out.println( Arrays.toString(a) );
			}
		}

第六章 面向对象oop

1、概念及三大特征

1、概念
面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的执行者变成了指挥者,面向对象是基于面向过程而言的。
在这里插入图片描述
2、三大特征:
1、 封装性,把相关的数据封装成一个“类”组件
2、 继承性,是子类自动共享父类属性和方法,这是类之间的一种关系
3、 多态,增强软件的灵活性和重用性

2、 类和对象

1、类
1、 Java语言最基本单位就是类,类似于类型。
2、 类是一类事物的抽象。
3、 可以理解为模板或者设计图纸。
2、对象
每个对象具有三个特点:对象的状态,对象的行为和对象的标识
1、 对象的状态用来描述对象的基本特征。
2、 对象的行为用来描述对象的功能。
3、 对象的标识是指对象在内存中都有一个唯一的地址用来和其他对象区分开来。
4、 类是一类事物的抽象,对象是具体的实现。
3、 类
成员变量(属性):表示是什么?
成员方法(行为):表示能做什么?

在这里插入图片描述
4、类和对象的创建和使用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
练习:

public class Test3_Object {
			public static void main(String[] args) {
				//4、创建对象测试
		//		new Phone();//匿名对象
				//5、通过new关键字,创建对象。引用类型的变量p就保存了一个地址值
				Phone p = new Phone();
				//p对象能调用.模板里的属性和行为吗?
				p.call();
				p.message();
				p.music();
				
				//6、设置属性的值
				p.color="red";
				p.size=7;
				p.pinpai="HUAWEI";
				p.price=5899.5 ;
				
				//7、打印属性的值
				System.out.println(p.color);//null--red
				System.out.println(p.size);//0--7
				System.out.println(p.pinpai);//null--HUAWEI
				System.out.println(p.price);//0.0--5899.5
			}
		}
		//1、通过class关键字创建类,Phone类,用来描述手机事物:属性+行为
		class Phone {
		//2、属性:颜色,尺寸,品牌,价格  -- 用成员变量/成员属性 描述
			String color ;//引用类型,默认值是null
			int size ;
			String pinpai ;
			double price ;
		//3、行为:打电话,发短信,听音乐  -- 用成员方法 描述
			//方法的修饰符 方法的返回值 方法名(参数列表){方法体}
			public void call() {
				System.out.println("正在打电话...");
			}
			public void message() {
				System.out.println("正在发短信...");
			}
			public void music() {
				System.out.println("正在听音乐...");
			}
		}
	

5、创建多个对象
在这里插入图片描述
练习:

	package cn.tedu.oop;
		//这个类用来测试创建多个对象
		public class Test1_Object {
			public static void main(String[] args) {
				//2、创建汽车对象测试
				//new Car().fly();//匿名对象,一个对象只干一个事情
				Car c = new Car();
				//调用模板里的功能
				c.fly();
				c.run();
				c.color="black";
				c.pinpai="Audi";
				c.model="Q7";
				c.price=70;		
				System.out.println(c.color);
				System.out.println(c.pinpai);
				System.out.println(c.model);
				System.out.println(c.price);
				
				//创建多个对象
				System.out.println();//换行
				Car c2 = new Car();
				c2.fly();
				c2.run();
				c2.color="red";
				c2.pinpai="BMW";
				c2.model="X6";
				c2.price=60;
				System.out.println(c2.color);
				System.out.println(c2.pinpai);
				System.out.println(c2.model);
				System.out.println(c2.price);
				
				Car c3 = c2;//把c2记录着的地址值,交给c3保存,都是引用类型的变量,所以都存地址值
			}
		}
		//1、创建汽车类,用来描述汽车事物
		class Car{
			//成员变量/成员属性  -- 特征
			String color;
			String pinpai;
			String model;
			double price;
			//成员方法  -- 行为
			public void run() {
				System.out.println("正在开车...");
			}
			public void fly() {
				System.out.println("正在飞...");
			}
		}

3、面向对象的特点(封装、继承、多态)

一、封装
概述
封装是指隐藏对象的属性和实现细节,仅仅对外提供公共的访问方式。
2、private关键字
是一个权限修饰符,用于修饰成员变量、成员方法和成员函数、,被私有化的成员只能在本类中访问。

注意:如果被封装后想要修改只能,对外提供公共的,get和set方法
练习:封装学生类

package cn.tedu.privatedemo;

		//这个类用来测试封装
		public class Test2_Private {
			public static void main(String[] args) {
				//TODO 创建学生对象测试
				Student s = new Student();
		//		s.study();//study()已经被private了,除了本类,其他类都访问不了。
				s.chiji();
				//设置属性值
		//		s.name="张三";//报错,因为name被私有了,不能直接赋值
				s.setName("蔡徐坤");
				//s.age=20;//报错,因为name被私有了,不能直接赋值
				s.setAge(10);
		//		s.xueke="java";
				s.setXueke("java");
				//获取属性值
		//		System.out.println(s.name);//报错,因为name被私有了,不能直接获取
		//		String result = s.getName();
		//		System.out.println(result);
				System.out.println(s.getName());
		//		System.out.println(s.age);
				System.out.println(s.getAge());
		//		System.out.println(s.xueke);
				System.out.println(s.getXueke());
			}
		}
		//创建学生类:属性+行为
		//工具自动生成set()/get()  -- 右键--source-- generate setters() and getters()--select all -ok
		class Student{
			//1、通过private关键字,实现封装
			//2、如果被private私有化了,成员只能在本类中访问,其他类看不到更用不了
			private String name ;
			//给外界提供全局的访问点--set() / get()
			//3、外界还想要给name属性设置值--公共的setXxx()
			public void setName(String n){
				name = n ; //把你想要设置的值给n保存,拿着n的值,给name属性赋值 
			}
			//4、外界还想要给name属性获取值--公共的getXxx()
			public String getName(){
				return name;//通过return关键字,把name属性的值,返回给外界的调用位置!
			}
			private int age ;
			public void setAge(int a){
				age = a ;
			}
			public int getAge(){
				return age;
			}
			private String xueke ;
			public void setXueke(String x) {
				xueke = x ;
			}
			public String getXueke(){
				return xueke ;
			}
			//3、private可以修饰成员变量或者成员方法
			private void study() {
				System.out.println("正在学习");
			}
			public void chiji() {
				study();//4、study()被private了,外界无法直接访问,但是,可以访问chiji()实现间接访问!!
				System.out.println("正在吃鸡");
			}
		}

二、继承
1、概念
继承是面向对象最显著的一个特性。

继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

Java继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功 能,也可以用父类的功能,但不能选择性地继承父类/超类/基类。
2、特点

1、 使用extends关键字

2、 相当于子类把父类的功能复制了一份

3、 java只支持单继承

4、 继承可以传递(爷爷,儿子,孙子的关系)

5、 不能继承父类的私有成员

6、 继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能拓展

7、 像是is a 的关系

入门案例

package cn.tedu.extendsdemo;
		//这个类用来测试继承的入门案例
		public class Test3_Extends {
			public static void main(String[] args) {
				//创建父类对象测试
				Fu f = new Fu();
				f.show();
				System.out.println(f.sum);
				System.out.println();
				
				//3、创建子类对象测试  能使用父类的功能吗--可以
				//6、继承的传递性
				Zi zi = new Zi();
				zi.show();  //使用了父类的show()
				System.out.println(zi.sum);//使用了父类的sum
				zi.play();//使用了爷爷类的play()
				System.out.println(zi.age);//使用了爷爷类的age
			}
		}
		class Yeye{
			int age;
			public void play() {
				System.out.println("下象棋");
			}
		}
		class Fu extends Yeye{//父类
			//5、父类的私有成员,子类无法继承
		//	private int sum =10 ;
			int sum =10 ;
			public void show() {
				System.out.println("show()...");
			}
		}
		//1、子类 想要 使用父类的功能,必须发生继承关系extends
		//4、java只支持单根继承/单继承
		class Zi extends Fu {//7、继承是is  a的关系,是子类和父类发生了强制的依赖关系 ---- 强耦合!(不建议)
			//2、当子类继承了父类后,就相当于把父类的功能,复制了一份,可以随时使用父类的所有功能
			//6、继承的传递性,不仅能用父类的,还能用爷爷类的功能
		}

3、super关键字
1、 通过super关键字可以使用父类的内容
2、 super代表父类的一个引用对象
3、 如果用在构造方法中,必须出现在调用位置的第一条语句!!(类似于this)

4、继承中的用法
①1、成员变量的使用

package cn.tedu.extendsdemo;

		//这个类用来测试 继承的 成员变量的使用
		public class Test4_UseExtends {
			public static void main(String[] args) {
				//TODO  创建子类对象测试
				Son s = new Son();
				s.study();
			}
		}
		class Father{//父类
			int count = 5;
			int sum = 30;
		}
		class Son extends Father{//子类
			
			int sum =20;
			
			public void study() {
				int sum  = 10;
				System.out.println(sum);//10,就近原则
				System.out.println(this.sum);//20,this调用了成员变量
				
				//1、使用super关键字,可以在子类中,调用父类的功能
		//		System.out.println(count);//5,子类又没有,只能用父类的count
				System.out.println(super.count);
				System.out.println(super.sum);//在子类中使用了父类的成员变量
			}
			
		}

②成员方法的使用

package cn.tedu.extendsdemo;
		//这个类用来测试  继承中 成员方法的使用
		//1、方法重写的意义:当业务发生了改变时,我们不能修改源代码,只能发生继承关系后,修改功能。
		//2、重写的前提: 继承关系   +    子类方法声明和父类一模一样
		//3、子类必须  有权限  重写父类的方法,子类权限  >= 父类权限
		public class Test5_UseExtends2 {
			public static void main(String[] args) {
				//TODO 创建子类对象 测试
				Erzi erzi = new Erzi();
				erzi.eat();//重写前用的是父类的,重写后,用的是子类的!!但是父类源代码并没有影响!!
				erzi.sleep();//父类的
				erzi.coding();//子类特有的
			}
		}
		class Baba{//父类
			public void eat() {
				System.out.println("爸爸正在吃肉");
			}
			public void sleep() {
				System.out.println("正在睡觉");
			}
		}
		class  Erzi extends Baba{
		//3、需要修改原有功能时,为了不修改源代码。子类可以方法重写:继承关系+子类的方法声明和父类一样
			public void eat() {
		//		super.eat();//4、在子类中,测试父类的eat()真的没影响吗?--真的没有,没有影响父类的源代码
				System.out.println("儿子在吃菜");
			}
			//1、子类可以使用父类的所有功能(除了private)
			//2、子类可以使用父类的同时,还是自己扩展
			public void coding() {
				System.out.println("正在敲代码");
			}
		}

5、final关键字
1、概念:
①是java提供的一个关键字

②final是最终的意思

③final可以修饰类,方法,成员变量

初衷是因为:java出现了继承后,子类可以更改父类的功能,当父类功能不许子类改变时可以利用final关键字修饰父类。
2、特点
①被final修饰的类,不能被继承

②被final修饰的方法,不能被重写

③被final修饰的变量是个常量,值不能被更改

④常量的定义形式: final 数据类型 常量名 = 值
练习:入门案例

package cn.tedu.finaldemo;
		//这个类用来测试final关键字
		public class Test1_Final {
			public static void main(String[] args) {
				//TODO 创建子类对象测试
				Zi zi = new Zi();
		//		zi.sum=20;//The final field Zi.sum cannot be assigned
				System.out.println(zi.SUM);
				System.out.println(Zi.SUM);
			}
		}
		//创建父类
		//final class Fu{//1、被final修饰的类,是最终类,不能被继承。The type Zi cannot subclass the final class Fu
		class Fu{
		//	final public void eat() {//2、被final修饰的方法,是最终方法,不能被重写。Cannot override the final method from Fu
			public void eat() {
				System.out.println("爸爸在吃肉");
			}
		}
		//创建子类
		class Zi extends Fu{
			//是子类的特有功能,只能创建子类对象才能调用
			//3、final修饰的变量是常量。常量的值不能被修改!!The final field Zi.sum cannot be assigned
			//4、变量前加了final是说变量变成了一个常量。加了static是为了方便通过类名来直接调用
			static final int SUM = 10 ;
			@Override
			public void eat() {
				System.out.println("儿子在喝汤");
			}
		}

三、多态
在这里插入图片描述
1、 概念
多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征。

主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态。

好处是可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准。

例如:水,在不同时刻可以有多种形态,包括水蒸气,冰,水。

Java怎么体现多态呢?狗有两种形态:狗和小动物
2、 特点
1、 多态的前提是继承
2、 要有方法的重写
3、 父类引用指向子类对象,如:Animal a = new Dog(); – 小到大,向上转型
4、 多态中,编译看左边,运行看右边
3、方法重写override
1、 继承后,子类就拥有了父类的功能
2、 那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能
3、 子类中方法签名与父类完全一样(包括方法的返回值,方法名和参数列表,完全一致)时,会发生覆盖/复写操作,相当于修改功能
注意:
1、父类中的私有方法不能被重写
2、子类重写父类方法时,修饰符要大于等于父类修饰符的权限
3、修饰符:public > protected > default > private
在这里插入图片描述
入门案例

ackage cn.tedu.multi;
		//这个类用来测试多态 multiple
		public class Test2_Multi {
			public static void main(String[] args) {
				//3、创建父类对象测试
				Animal a = new Animal();
				a.study();//正在学习
				//4、创建子类对象测试
				Dog d = new Dog(); 	
				d.study();//重写前,使用的肯定是父类的。重写后,使用的是子类的。
				
				//5、创建多态对象测试
				Animal an = new Dog() ;//口诀1:父类引用  指向 子类对象	  -- 多态/向上转型
				//口诀2:编译看左边,运行看右边
				//编译看左边:想要保存成功,只能调用左边(父类)的功能!!   ----  统一调用标准!!标准就是父类!!
				//运行看右边:运行结果看子类的功能!!
				an.study();
			}
		}
		//1、多态的前提:		继承 + 重写
		class Animal{
			public void study() {
				System.out.println("正在学习");
			}
		}
		class Dog extends Animal{
			//2、重写:子类的方法声明  和  父类  一模一样
			@Override//标志着这是在重写父类的方法
			public void study() {
				System.out.println("汪汪汪");
			}
		}

3、多态的好处
①多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法。

②提高了程序的扩展性和可维护性

特点
1、成员变量:使用的是父类的
2、成员方法:由于存在重写现象所以使用的是子类的
3、静态成员:随着对象而存在,谁调用的就返回谁的(静态资源static不能重写)
练习1:

package cn.tedu.multi;

		//这个类用来测试  多态的使用
		public class Test3_UseMulti {
			public static void main(String[] args) {
				Sharp s = new Circle();//口诀1:父类引用  指向 子类对象
				//1、多态中的成员方法怎么用?
				s.draw();//1.1、编译看左边,用了父类提供的 方法声明部分
							  //1.2、运行看右边,用了子类提供的  方法体---多指方法重写现象
				//2、多态中的成员变量怎么用?--父类的
				System.out.println(s.sum);
				//3、多态中的静态资源怎么用?--谁调用就使用谁的,s是父类类型,所以使用父类的
				System.out.println(s.name);
				System.out.println(Sharp.name);
				//4、静态方法能不能重写??--不可以重写,谁调用就使用谁的,因为静态资源是跟随类存在
				s.show();
				Sharp.show();
			}
		}
		//多态的前提:  继承  +  重写
		class Sharp{
			int sum = 10;
			static String name="jack";
			public void draw() {
				System.out.println("正在画图");
			}
			static public void show() {
				System.out.println("Sharp..show()");
			}
		}
		class Circle extends Sharp{
			int sum = 20;
			static String name="rose";
			@Override
			public void draw() {
				System.out.println("正在画圆");
			}
			static public void show() {
				System.out.println("Circle..show()");
			}
		}

练习2:

package cn.tedu.multi;
		public class Test4 {
			public static void main(String[] args) {
				Teacher t = new CgbTeacher() ; //父类引用 指向 子类对象
				//成员变量,成员方法,静态资源
				System.out.println(t.sum);//使用了父类的成员变量,因为编译看左边
				t.teach();//使用了父类的方法声明  , 使用了子类的方法体(因为发生了方法重写,所以运行看右边)
				
				//如果,你非要用 子类的特有功能,多态对象不可能!!此时,只能创建子类对象。
		//		t.name//报错,因为t是多态对象,只能使用父类的功能,对于子类特有功能,多态对象无能为力!
				CgbTeacher ct = new CgbTeacher();
				System.out.println(ct.name);
				
				//向下转型--多态叫做向上转型---使用向下转型的目的:是为了使用子类的特有功能
				CgbTeacher ct2 =(CgbTeacher) t ;//右侧的t是父类 类型,给左侧的子类类型 ct2赋值时,--需要强转
				System.out.println(ct2.name);
			}
		}
		//准备父类 
		class Teacher{
			int sum = 10 ;
			public void teach() {
				System.out.println("正在上课");
			}
		}
		//准备子类   
		class CgbTeacher extends Teacher{
			String name="hanmeimei";
			
			int sum = 20 ;
			@Override
			public void teach() {
				System.out.println("正在讲基础");
			}
		}

4、构造方法(创建对象才用构造)

1、概念
构造方法是一个特殊方法,特殊在方法名和类名相同。

主要用来完成对象的创建和初始化。

构造方法也可以重载。

构造方法不能继承 和重写
2、形式
修饰符 类名([参数列表]){
方法体;
}
注意:构造方法的方法名与类名必须一样,父子类不能同名,故不能继承 更不可能被重写 可以重载-----某些情况对象的初值不同

练习1:构造方法创建对象

package cn.tedu.constructor;

		//这个类用来测试 构造方法
		public class Test3_Cons {
			public static void main(String[] args) {
				//3、无参创建对象 ,底层会自动触发  无参的 构造方法
				Person p = new Person();
				
				//5、怎么才能触发含参构造?使用含参的方式创建对象
				Person p2 = new Person("蔡徐坤"); 
			}
		}
		//创建Person类
		class Person{
			//1、提供构造方法:修饰符 类名([参数列表]){    方法体;    }
		//2、默认会存在  无参 构造方法!  -- 前提是,没有提供含参构造。如果类中,只提供了含参构造,无参构造就真没了!
			public Person() {
				System.out.println("无参构造方法");
			}
			
			//4、构造方法的重载形式:方法名相同+参数列表不同!
			public Person(String name) {
				System.out.println("含参构造方法"+name);
			}
			
		}

练习2:构造方法赋值

	package cn.tedu.constructor;
		//这个类用来测试 构造方法 赋值
		public class Test4_Cons2 {
			public static void main(String[] args) {
				//3、创建对象测试
				Animal a = new Animal();//自动触发 无参 构造
				Animal a2 = new Animal("大黄");//自动触发 含参 构造
			}
		}
		//创建类
		class Animal{
			
			String name;
			
			//修饰符 类名([参数列表]){方法体}
			public Animal() { }//1、空着也得有,是为了方便外界创建对象
			
			//2、重载形式的构造方法
			public Animal(String n) {//n-是形参,也是局部变量
				//4、拿着 局部变量 n给 成员变量 name赋值
				name = n;
				System.out.println("含参构造"+n);
			}
			
		}

3、构造方法的使用----构造方法不能被继承!!!
练习:构造方法不能被继承

package cn.tedu.extendsdemo;
		//这个类用来测试  继承中 构造方法的使用
		public class Test6_UseExtends3 {
			public static void main(String[] args) {
				//创建子类对象测试
				//2、子类创建对象时,会触发子类的无参构造,但是第一行隐藏着supre()会主动去找父类无参构造
				Sub s = new Sub();//自动匹配无参构造
			}
		}
		class Babby{
		//	public Babby() {  }  //5、如果没提供无参构造,子类使用会麻烦,所以最好提供!
			public Babby(int a) {
				System.out.println("Babby...无参构造方法"+a);
			}
		}
		class Sub extends Babby{
			public Sub() {
				//1、默认就存在,隐藏了,会自动调用父类的无参构造
		//		super();  //3、目前父类没有无参 构造了,会报错
				super(8);  //4、我们只能调用父类的含参构造,而且位置必须是第一条语句 
				System.out.println("Sub...无参构造方法");
			}
		}

5、 静态代码块、构造代码块、局部代码块

一、静态(static)代码块
随着类的加载而加载,并且只被加载一次,一般用于项目的初始化
形式
static{…}
概述
1、 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化
2、 构造代码块:在调用构造方法前会自动调用,每次创建对象都会被调用
3、 局部代码块:方法里的代码块,方法被调用时才会执行
4、 静态代码块:static{ },位置:在类里方法外
5、顺序: 静态代码块 - 构造代码块 - 构造方法 - 局部代码块

静态块是类加载的时候就会被执行到的,静态执行顺序是按照在类中出现 的先后顺序执行。

测试

package cn.tedu.staticdemo;

 

public class Test4 {

    public static void main(String[] args) {

       Car c = new Car();c.show();

       Car c2 = new Car();

    }

}

class Car{

    //静态代码块

    //1,在类第一次加载时就加载到内存中并一直驻存,

    //并全局共享,直到类消失静态资源才消失

    //2,并且静态资源只被加载一次

       static {

           System.out.println(1);

       }

      

       //构造代码块

       {

           System.out.println(2);

       }

      

       //  构造方法

       public Car() {

           System.out.println(3);

       }

      

       public void show() {

//     局部代码块

           {

              System.out.println(6);

           }

           System.out.println(4);

           System.out.println(5);

       }

}

三、构造代码块
位置:在成员位置:在类里,方法外
作用:提取构造方法的共性
优先级:构造代码块 > 构造方法
四、局部代码块
位置:在方法里
作用:控制变量的作用范围
练习:

package cn.tedu.block;
		//这个类用来测试 代码块 的使用
		//构造代码什么时候触发 -- 在创建对象时触发
		//局部代码什么时候触发 -- 在方法被调用时
		//1、在创建对象时做了两件事:执行了构造代码块 + 构造方法
		//2、在调用方法时:执行了局部代码块
		//执行顺序: 构造代码块  >  构造方法  > 局部代码块
		public class Test5_Block {
			public static void main(String[] args) {
				//创建Teacher对象测试
				//2、创建对象时,一定会触发对应的构造方法。
				//3、如果有构造代码块,执行顺序: 构造代码块  >  构造方法
				Teacher t = new Teacher();//触发无参构造
				Teacher t2 = new Teacher(18);//触发含参构造
				
				//6、触发局部代码块
				t.show();
			}
		}
		//创建类
		class Teacher{
			//1、位置:如果在类里方法外,是构造代码块
			//4、构造代码块通常用于  提取 构造方法的共性,提高了代码的复用性
			String country;
			{
				country = "中国人";//提取了共性,只不过,变量的作用范围只在代码块中有效
				System.out.println("构造代码块");
			}
			//提供构造方法
			public Teacher() {
		//		String country = "中国人";
				System.out.println("无参构造方法"+country);
			}
			//提供构造方法的重载形式
			public Teacher(int a) {
		//		String country = "中国人";
				System.out.println("含参构造方法"+a+country);
			}
			//5、局部代码块:位置是在方法里,作用是控制变量的作用范围
			public void show() {
				{
					int sum = 10;
					System.out.println("局部代码块"+sum);
				}
			}
		}

3、this关键字
1、概念
this代表本类对象的一个引用对象。
2、形式
this.name=name;
练习1:

package cn.tedu.thisdemo;
		//这个类用来测试  this的使用
		//总结1:当变量名相同时,通过this使用成员变量!
		public class Test1_This {
			public static void main(String[] args) {
				Person p = new Person("xiongda");	//触发含参构造
				System.out.println(p.name);//xiongda
			}
		}
		class Person{
			String name ;
			
			//提供构造方法
			public Person() {}
			public Person(String name) {
				//变量使用时,有个就近原则。所以,等号左右两侧使用的都是局部变量name,左侧根本没找到成员变量
		//		name = name ;
				//1、当 成员变量   和  局部变量  同名时,优先使用局部变量,可以通过this关键字调用本类的成员变量。
				//2、this代表的是本类的对象的引用。相当于底层帮你写了一行代码:Person this = new Person();
				//3、this能调用的是本类的  成员!!  可以是成员变量  或者 成员方法。
				this.name = name;
			}
		}	

练习2:构造方法间的调用

package cn.tedu.thisdemo;

		//这个类用来测试 this的使用:构造方法间的调用
		//总结1:this 可以单向的  在构造方法间使用  ,而且位置上,必须是第一条语句!
		public class Test2_This2 {
			public static void main(String[] args) {
				Person2 p = new Person2();// 触发无参构造方法
		//		Person2 p2 = new Person2(20);// 触发含参构造方法
			}
		}
		class Person2{
			public Person2() {
				//2、在 无参构造方法中  使用 含参构造方法
		//		this(10);
				System.out.println("无参构造方法");
			}
			public Person2(int age) {
				//1、在含参构造方法中  使用  无参构造方法
				this();	
				System.out.println("含参构造方法"+age);
			}
		}

4、static关键字
在这里插入图片描述
特点
1、 可以修饰成员变量,成员方法
2、 随着类的加载而加载,优先于对象加载
3、 只加载一次,就会一直存在,不再开辟新空间
4、 全局共享,可以被多个对象共享
5、 可以直接被类名调用
6、 静态只能调用静态,非静态可以随意调用(静态资源static不能重写)
7、 static不能和this或者super共用,因为有static时可能还没有对象
8、静态方法不能重写
练习1:入门案例

package cn.tedu.staticdemo;
			//这个类用来测试 静态入门案例
			public class Test7_Static {
				public static void main(String[] args) {
					//测试
					//2、加载顺序:静态资源   早于  对象
					StaticDemo.game();//3、静态资源 可以直接被类名调用
					
					StaticDemo demo  = new StaticDemo();
					demo.show();
					System.out.println(demo.age);
					
					//4、全局共享,可以被多个对象共享
					demo.name = "jack";
					StaticDemo demo2  = new StaticDemo();
					System.out.println(demo2.name);//已经看到了demo对象改之后的效果了,确实是共享数据,不然不会看到的
					System.out.println(StaticDemo.name);
				}
			}
			//创建类
			class StaticDemo{
				//TODO 提供  静态  资源
				//1、 static可以修饰成员变量,成员方法
				static String name ;
				static public void game() {
					System.out.println("game()...");
				}
				//提供   普通资源
				int age;
				public void show() {
					System.out.println("show()...");
				}
			}

练习2:静态调用关系

		package cn.tedu.staticdemo;
		//这个类用来测试 静态的调用关系
		//总结1:静态资源  只能  调用 静态资源!! , 而普通资源   可以随意调用
		public class Test8_Static2 {
			public static void main(String[] args) {
			}
		}
		class StaticDemo2{
			//提供 普通资源
			int age;
			public void eat() {
				//1、普通资源  调用  静态资源 ?--   可以
				coding();
				System.out.println(name);
				System.out.println("eat()...");
			}
			
			//提供 静态资源
			static String name ;
			static public void coding() {
				//2、静态资源  调用  普通资源 ? --   不可以,静态 只能 调用 静态
		//		eat();
		//		System.out.println(age);
				System.out.println("coding()...");
			}

6、异常

1、概述
用来封装错误信息的对象。
组成结构:类型,提示,行号。
2、异常的继承结构
在这里插入图片描述
3、异常处理
程序中遇到了异常,通常有两种处理方式:
①捕获
②向上抛出。
在这里插入图片描述
当调用了一个抛出异常的方法时,调用位置可以不做处理继续向上抛出也可以捕获异常。
练习:测试

package cn.tedu.exception;

		import java.util.InputMismatchException;
		import java.util.Scanner;

		//这个类用来测试 异常的暴露
		public class Test5_Exception {
			public static void main(String[] args)  {
				// method();//暴露异常
				// method2();// 捕获异常
				try {
					method3();// 抛出异常
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();//通常用来调错
					System.out.println("执行失败!");//项目上线时直接给出的方案
				}
			}
			// 抛出异常:在会出错的方法上添加代码  throws 异常类型1,异常类型2
		//	public static void method3() throws ArithmeticException,InputMismatchException{
			//2、直接抛出Exception也是体现了多态,因为根本不关心具体的子类类型,会把子类当做父类来看,写出通用代码
			public static void method3() throws Exception{
				int a = new Scanner(System.in).nextInt();
				int b = new Scanner(System.in).nextInt();
				System.out.println(a / b);
			}

			// 1、捕获异常: try{ 有可能发生异常的代码 } catch(异常类型 异常名){ 给出的解决方案 }
			public static void method2() {
				try {
					int a = new Scanner(System.in).nextInt();
					int b = new Scanner(System.in).nextInt();
					System.out.println(a / b);
				} catch (ArithmeticException a) {// 2、当try里的代码发生ArithmeticException异常时,捕获并给出方案
					System.out.println("第二次输入必须是>0的值!!");
				} catch (InputMismatchException a) {// 3、当try里的代码发生InputMismatchException异常时,捕获并给出方案
					System.out.println("请输入两次整数!!");
				} catch (Exception a) {// 4、当try里的代码发生任意异常时,都会被当做父类类型Exception处理,给出方案
					// 5、Exception就是多态的体现,好处是不关心具体的子类类型,会把子类当做父类来处理,写出通用代码
					System.out.println("请输入正确的数值!!");
				}
			}

			// 暴露异常
			public static void method() {
				// 1、接收用户输入的两个整数
				int a = new Scanner(System.in).nextInt();
				int b = new Scanner(System.in).nextInt();
				// 2、做除法运算
				System.out.println(a / b);
			}
		}

在这里插入图片描述

第七章 抽象类

1、概念

一、概念
Java中可以定义没有方法体的方法,该方法由其子类来具体的实现。该没有方法体的方法我们称之为抽象方法,含有抽象方法的类我们称之为抽象类。抽象类可以理解为是一个只有方法声明没有方法体的特殊类。

二、特点
1、 通过java关键字abstract实现
2、 可以修饰方法或者类
3、 抽象类中可以没有抽象方法(由子类去实现)
4、 如果类中有抽象方法,那该类必须定义为一个抽象类
5、 子类继承了抽象类以后,要么还是一个抽象类,要么就把所有抽象方法都重写
6、 抽象类不可以被实例化
7、 多用于多态中

入门案例

package cn.tedu.abstractdemo;
		//这个类用来测试 抽象类的 入门案例
		public class Test1_Abstract {
			public static void main(String[] args) {
		//		Animal a = new Animal();//6、抽象类不可以被实例化
				Animal a = new Cat();//父类引用指向子类对象,多态-向上转型
				//编译看左边,只能用父类提供的功能,父类就是标准!
				a.eat();//7、子类重写了抽象方法,使用了子类的方法体
				a.game();
				a.sleep();
				//存在方法重写,运行看右边,也就是结果向子类看齐
			}
		}
		//把子类的共性功能,向上提取,形成父类,来提高复用性。
		//2、如果一个类中,包含抽象方法,那么,这个类必须声明为抽象类
		abstract class Animal{
		//	public void eat() {  System.out.println("吃啥都行");    }//1、子类发生了方法重写,也就是把父类的方法体改掉了!!
			abstract public void eat() ;//1、此时,父类干脆不提供方法体了!!-- 叫抽象方法,用关键字abstract描述
			abstract public void game() ;
			public void sleep() {
				System.out.println("正在睡觉");
			}
		}
		//5、子类继承了一个抽象类以后,如果想当普通子类,需要重写所有抽象方法
		class Cat extends Animal{
		//	abstract public void eat() ;
			public void eat() {
				System.out.println("猫吃鱼");
			}
		//	abstract public void game() ;
			 public void game() {
				 System.out.println("猫玩耗子");
			 }
		}
		//创建子类,并修改eat()
		//3、子类继承了一个抽象类以后,可以是抽象的子类,也可以是普通的子类(需要把所有抽象方法都重写)
		abstract class Dog extends Animal{
			//4、Dog已经把父类的所有方法都继承过来了,此时包含抽象方法。
		}

2、抽象类的用法(构造函数/方法、成员变量、成员方法)

一、构造函数/方法
抽象类也有构造方法,但是不能本身实例化(不能new)。

那抽象类的构造函数有啥用?一般用于给子类实例化(就是给子类去创建对象)。

测试:

package cn.tedu.abstractdemo;
		//这个类用来测试  抽象类的 构造方法使用
		public class Test2_UseAbstract {
			public static void main(String[] args) {
				//3、创建子类对象时,为什么会触发父类的无参构造?? -- 因为子类无参构造中,隐藏着super()
				AbstractDemo demo = new AbstractDemo2();//TODO 创建多态对象测试
				
				//4、抽象类是不能创建对象的,那还提供构造方法干什么呢?--不是为了自己创建对象,而是为了子类创建对象用
		//		AbstractDemo demo2 = new AbstractDemo();
			}
		}
		//创建抽象类
		abstract class AbstractDemo{
			//1、构造方法--修饰符 类名(【参数列表】){ ... } -- 创建对象时调用
			public AbstractDemo() {
				System.out.println("AbstractDemo...无参构造");
			}
			//2、如果抽象类中,没有抽象方法也就是都是普通方法,那这个类修饰成普通类就可以,为什么还是被修饰成抽象类?
			//---目的就是不让外界创建对象
		}
		//创建子类,继承抽象类
		class AbstractDemo2  extends AbstractDemo{
			public AbstractDemo2() {
				//3.1、子类的无参构造中,第一条语句隐藏着super();
				super();
				System.out.println("AbstractDemo2...无参构造");
			}
		}

二、抽象类的成员变量
既可以有变量,也可以有常量。

测试

package cn.tedu.abstractdemo;

		//这个类用来测试  抽象类的 成员变量的使用
		public class Test3_UseAbstract2 {
			public static void main(String[] args) {
				//创建多态对象测试
				AbstractDemo3 demo = new AbstractDemo4();
				System.out.println(demo.sum);
				System.out.println(demo.MIN_VALUE);
				System.out.println(AbstractDemo3.MIN_VALUE);
			}
		}
		//创建抽象类
		abstract class AbstractDemo3{
			//1、抽象类中,可以包含变量,也可以包含常量!!
			int sum = 10 ;
			static final int MIN_VALUE = -128 ;//常量
		}
		class AbstractDemo4 extends AbstractDemo3{
		}

三、抽象类的成员方法
抽象类中可不可以都是普通方法? – 可以,目的是不让外界new

抽象类中可不可以都是抽象方法? – 可以,要求子类全都重写抽象方法,否则就是个抽象的子类

测试

package cn.tedu.abstractdemo;
		//这个类用来测试  抽象类的 成员方法的使用
		public class Test4_UseAbstract3 {
			public static void main(String[] args) {
				//3、创建多态对象测试
				AbstractDemo5 demo = new AbstractDemo6();
				demo.eat();
				demo.play();
				demo.study();
			}
		}
		//1、抽象类是一个特殊的类,特殊在哪儿?--抽象类里可以有普通方法,也可以有抽象方法
		abstract class AbstractDemo5{
			//4、抽象类中可不可以都是普通方法?  -- 可以,目的是不让外界new
			//5、抽象类中可不可以都是抽象方法?  -- 可以,要求子类全都重写抽象方法,否则就是个抽象的子类
			abstract public void eat() ;
			abstract public void play()  ;  //因为大家玩的都不一样,我提供了方法体也要被改,那就不提供了---抽象方法
			abstract public void study(); //因为大家学的都不一样,我提供了方法体也要被改,那我就不提供了--抽象方法
		}
		//2、如果子类继承了抽象的父类,子类有几条路?把所有抽象方法都重写 + 抽象的子类(因为仍然包含没重写的抽象方法)
		//abstract class AbstractDemo6 extends AbstractDemo5{
		class AbstractDemo6 extends AbstractDemo5{
			@Override
			public void play() {
				System.out.println("正在玩耍");
			}
			@Override
			public void study() {
				System.out.println("正在学习");
			}
			@Override
			public void eat() {
				System.out.println("正在吃饭");
			}
		}

3、接口

一、概念

Java里面由于不允许多重继承,所以如果要实现多个类的功能,则可以通过实现多个接口来实现。

Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现。OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程,正确地使用接口、抽象类这些太有用的抽象类型做为java结构层次上的顶层。

二、特点

1、 接口中都是抽象方法
2、 通过interface关键字创建接口
3、 通过implements让子类来实现
4、 可以理解成,接口是一个特殊的抽象类
5、 接口突破了java的单继承的局限性
6、 接口和实现类之间可以多实现,接口和接口之间可以多继承
7、 接口是对外暴露的规则,是一套开发规范
8、 接口提高了程序的功能扩展,降低了耦合性
9、接口是一种只含有抽象方法或常量的一种特殊的抽象类,因为接口不包括任何实现,所以与存储空间没有任何关系

入门案例

package cn.tedu.interfacedemo;
		//这个类用来测试  接口的入门案例
		public class Test5_Interface {
			public static void main(String[] args) {
		//		Inter1 in = new Inter1(); //5、接口不能实例化
				Inter1 in = new Inter1Impl();//多态
				in.save();
				in.update();
			}
		}
		//1、定义接口,interface关键字
		//interface 接口名
		interface Inter1{
			//2、接口是一个特殊的抽象类,特殊在哪儿?-- 特殊在接口里都是抽象方法,没有普通方法
			abstract public void save() ;
			abstract public void update() ;
		}
		//3、通过implements,使用接口的功能
		//4、接口是一个特殊的抽象类,接口实现类的用法和继承时子类的用法一样?-- 有几条路呢?
				//实现类还是两条路---要么是抽象的实现类 -- 要么重写所有抽象方法
		//abstract class Inter1Impl  implements   Inter1{
		class Inter1Impl  implements   Inter1{
			@Override
			public void save() {
				System.out.println("正在保存数据");
			}
			@Override
			public void update() {
				System.out.println("正在更新数据");
			}
		}

三、接口的用法

1、构造方法--------不能有,因为接口里都是没有方法体的抽象方法,但是构造方法有方法体,所以接口中没有构造方法

2、成员变量--------没有!!!接口里都是静态的常量,会为变量自动拼接public static final

3、成员方法-------有抽象方法,不能是普通方法!!都是抽象方法,会为方法自动拼接public abstract

测试

package cn.tedu.interfacedemo;
		//这个类用来测试 接口的使用
		public class Test6_Interface2 {
			public static void main(String[] args) {
				Inter2 in = new Inter2Impl();
		//		in.age = 20;//证明变量是final的
				System.out.println(in.age);
				System.out.println(Inter2.age);//证明变量是static的
			}
		}
		interface Inter2{
			//1、接口里的构造方法?--- 不可以!!
		//	public Inter2() {  }
			//2、接口里真的有成员变量?--- 没有!!!接口里都是静态的常量,会为变量自动拼接public static final
		// public static final int  age = 30 ;
			int  age = 30 ;//简写
			//3、接口里的成员方法?--不能是普通方法!!都是抽象方法,会为方法自动拼接public abstract
		//	public  abstract  void save() ;
			void save() ;//简写
		}
		class Inter2Impl implements  Inter2{
			@Override
			public void save() {
				System.out.println("正在保存数据");
			}
		}

四、接口的复杂用法

1、多实现:是指实现类和接口的关系,实现类可以同时使用多个接口,多个接口间逗号隔开
实现类需要重写多个接口里的所有抽象方法,否则就是一个抽象的 实现类。

测试

		package cn.tedu.fuza;
		//这个类用来测试 接口的   多实现:是指实现类和接口的关系,实现类可以同时使用多个接口
		public class Test1_ManyExtends {
			public static void main(String[] args) {
				
			}
		}
		//创建接口
		interface Inter1{
			void save();
			void delete();
		}
		interface Inter2{
			void get();
		}
		//1、创建实现类,同时使用1号2号接口,多个接口间逗号隔开。
		//2、实现类需要重写多个接口里的所有抽象方法,否则就是一个抽象的 实现类。
		//abstract class InterImpl implements Inter1,Inter2{
		class InterImpl implements Inter1,Inter2{
			@Override
			public void get() {
				System.out.println("get()...");
			}
			@Override
			public void save() {
				System.out.println("save()...");
			}
			@Override
			public void delete() {
				System.out.println("delete()...");
			}
		}

2、多继承:突破了java单继承的局限性,是指接口和接口间的关系

接口和接口间,可以发生继承关系,还可以多继承–只需要逗号隔开

测试

	package cn.tedu.fuza;
		//这个类用来测试 接口的   多继承:突破了java单继承的局限性,是指接口和接口间的关系
		public class Test2_ManyExtends2 {
			public static void main(String[] args) {
				Inter4 a=new InterImpl2();
			}
		}
		//创建父接口
		interface Inter3{
			void get();
			void delete();
		}
		interface Inter5{
			void select();
		}
		//2、接口和接口间,可以发生继承关系,还可以多继承--只需要逗号隔开
		//创建子接口
		interface Inter4  extends  Inter3 , Inter5{
			void update();
			//1、此时,Inter4接口到底有几个功能?--3个,从Inter3继承过来的两个 还有自己的一个
		}
		//创建实现类
		class InterImpl2 implements Inter4{
			@Override
			public void get() {
				System.out.println("get()..");
			}
			@Override
			public void delete() {
				System.out.println("delete()..");
			}
			@Override
			public void update() {
				System.out.println("update()..");
			}
			@Override
			public void select() {
				System.out.println("select()..");
			}
		}

3、实现类 可以 单继承的同时多实现

测试

package cn.tedu.fuza;
		//这个类用来测试 实现类 可以  单继承的同时多实现
		public class Test3_ManyExtends3 {
			public static void main(String[] args) {
				Inter6 in = new Zi();
				in.save();//多态中,编译看左边。
			}
		}
		interface Inter6{
			void save();
		}
		interface Inter7{
			void delete();
		}
		//TODO  把父类设置成抽象类
		abstract class Fu{
			abstract public void eat();
			public void get() {
				System.out.println("get()..");
			}
		}
		//作为实现类,可以单继承的同时多实现
		class Zi extends Fu implements Inter6 , Inter7{
			@Override
			public void delete() {
				System.out.println("delete()...");
			}
			@Override
			public void save() {
				System.out.println("save()...");
			}
			@Override
			public void eat() {
				System.out.println("eat()...");
			}
		}

总结

总结
1、类和类之间的关系:继承,而且是单继承
①class Zi extends Fu

Zi是子类 单继承 Fu是父类
让子类继承父类,子类就拥有了父类的所有功能(除了private)

方法重写override,要求是子类的方法声明和父类一样,改的是方法体,super可以在子类中使用,用来调用父类的功能,代表的是父类对象的引用

②接口和接口之间的关系: 继承,而且可以多继承(逗号隔开)
interface Inter1 extends Inter2
其中,Inter1子接口 , inter2父接口,此时Inter1拥有inter2的所有功能

interface inter3 extends Inter2 , Inter1
其中,inter3也是接口,可以同时使用Inter2 和 Inter1 的功能,为了突破java单继承的局限性而来

③实现类和接口之间的关系:实现,而且可以多实现(逗号隔开)

class InterImpl implements Inter1
其中,InterImpl是实现类,Inter1是接口
此时,InterImpl拥有接口里的所有功能,并且需要重写所有抽象方法,否则就是抽象类

class InterImpl implements Inter1 , Inter2
其中,InterImpl实现了Inter1和Inter2的所有功能,重写所有抽象方法,否则还是抽象类

class InterImpl extends Fu implements Inter1 , Inter2
其中,InterImpl继承了Fu类的功能,同时拥有了Inter1和Inter2的所有功能,要求InterImpl重写所有抽象方法,否则就是抽象类

接口和抽象类的区别

抽象类是一个特殊的类,特殊在抽象类中可以有普通方法和 抽象方法

接口是一个特殊的抽象类,特殊在接口里都是 抽象方法

语法上的区别:

接口里没有构造方法,抽象类里有

接口里没有变量,抽象类里有

接口里的常量和方法都可以简写,抽象类不能简写

接口和实现类是实现关系,抽象类和子类是继承关系

定义接口和定义抽象类用的关键字不同

第八章 API手册

1、概念

Application Programming Interface应用编程接口,一切可以调用的东西都是API。

2、Object

一、概念
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类(父类)。所有对象(包括数组)都实现这个类的方法。

二、常用方法

toString()返回该对象的字符串表示。
hashCode()返回该对象的哈希码值。
equals(Object obj)指示其他某个对象是否与此对象“相等”。

测试

package cn.tedu.api;

//这个类用来测试 Object工具类
//总结1:
//toString():默认使用的是Object里的,也就是打印地址值,如果想查看属性值,就需要重写toString()
//hashCode():获取对象在内存中的哈希码值
//equals()如果比较地址值,直接使用默认的Object提供的就可以,如果需要比较属性值,就需要重写
public class Test4_Object {

	public static void main(String[] args) {
		// 给属性设置值,两种方式:调用set() +创建对象时利用构造方法
		Student s = new Student("胖子", 20, "牛逼", 5.5);
//2、想要查看属性的值	
//	System.out.println(s.getName());
//	System.out.println(s.getAge());
//	System.out.println(s.getAddr());
//	System.out.println(s.getScore());
		// 3、能不能简化,查看属性值---在打印对象时,底层会自动调用toString()
//		默认使用Object父类提供的,就相当于直接打印对象在内存中的地址值
		System.out.println(s.toString());// cn.tedu.api.Student@15db9742
		System.out.println(s.hashCode());// 5、返回对象在内存中的哈希码值--编号366712642
		System.out.println("对象的地址值:" + Integer.toHexString(366712642));// 模拟对象的地址值获取

//	6、equals();比较两个对象是否相等?
		Student s2= new Student("胖子", 20, "牛逼", 5.5);
		//默认使用了Object提供的equals(),使用==比较
//		==比较引用类型变量时,比较的都是地址值
//		==比较基本类型变量时,比较的是值本身
		System.out.println(s.equals(s2));//false,因为拿着s和s2比较地址值
	}

}

//创建学生了
class Student extends Object {// 这是继承了Object作为父类,这个实际是隐藏了extends Object,写不写都可以
//	构造方法 快捷键:右键 source 倒数第三个   OK
	// 构造方法只要牵涉构造对象,就必须写,空着也要空着,目的就是为了创建对象
	public Student() {

	}

	public Student(String name, int age, String addr, double score) {
		super();
//	创建对象 同时给成员变量赋值
		this.name = name;
		this.age = age;
		this.addr = addr;
		this.score = score;
	}

	// 封装 属性
	private String name;
	private int age;
	private String addr;
	private double score;

//每个属性的get()用来获取值,set()用来设置值  用快捷键
	public String getName() {
		return name;
	}

	public void setName(String name) {
//	当成员变量和局部变量名相同时,通过this调用成员变量
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getAddr() {
		return addr;
	}

	public void setAddr(String addr) {
		this.addr = addr;
	}

	public double getScore() {
		return score;
	}

	public void setScore(double score) {
		this.score = score;
	}

//重写toString();
//问题:由于目前Student,没有提供toString(),如果打印对象时
//就会找Object里的toString()采用默认实现方式,来显示对象的地址值
//解决方案:不能改Object里的toString()--  我们只能重写toString()
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", addr=" + addr + ", score=" + score + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((addr == null) ? 0 : addr.hashCode());
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		long temp;
		temp = Double.doubleToLongBits(score);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		return result;
	}
//	7、重写equals():因为默认使用Object的eqals()就是比较两个对象的地址值
//	比较两个对象间的属性,就算new两次,但是两次属性一模一样,必须认为是一个对象,让equals()返回true

/*@Override
	public boolean equals(Object obj){
	要求参数obj必须是学生类型
	 * Stedent s =(Student) obj;
	 *如果两个对象间的 所有  属性值相同是  ,返回true
	 * if(this.name==s.name && this.age== s.age &&  this.addr== s.addr && this.score== s.score){
	 *  return true;
	 *  }
	 * return false;
	 * }
	*/
	//重写有快捷键
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (addr == null) {
			if (other.addr != null)
				return false;
		} else if (!addr.equals(other.addr))
			return false;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (Double.doubleToLongBits(score) != Double.doubleToLongBits(other.score))
			return false;
		return true;
	}


}

3、String(字符串对象)

一、特点
String是一个最终类,不能被继承,也不能被重写
二、创建String对象
String s = “abc”;

String(char[] value)

String(byte[] bytes)

三、常用方法

char charAt(int index)
返回指定索引处的 char 值。

String concat(String str)
将指定字符串连接到此字符串的结尾。

boolean endsWith(String suffix)
测试此字符串是否以指定的后缀结束。

boolean equals(Object anObject)
将此字符串与指定的对象比较。

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

int hashCode()
返回此字符串的哈希码。

int indexOf(String str)
返回指定子字符串在此字符串中第一次出现处的索引。

int lastIndexOf(String str)
返回指定子字符串在此字符串中最右边出现处的索引。

int length()
返回此字符串的长度。

String replace(char oldChar, char newChar)
返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。

String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串

boolean startsWith(String prefix)
测试此字符串是否以指定的前缀开始。

String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。

String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。

String toLowerCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
String toUpperCase()
使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

String trim()
返回字符串的副本,忽略前导空白和尾部空白。

static String valueOf(long l)
返回 long 参数的字符串表示形式。

String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实 现。字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。因为 String 对象是不可变的,所以可以共享。

测试

package cn.tedu.api;

		import java.util.Arrays;

		//这个类用来测试  String工具类
		//String是一个最终类,不能被继承
		//String底层维护了一个char[],会把数据存入char[],而且是个常量,值不能被改。
		public class Test5_String {
			public static void main(String[] args) {
				//1、创建字符串对象
				char[] chars = {'a','b','c'};
				String str = new String(chars);//自动匹配char[]构造
				
				byte[] bytes = {97,98,99};
				String str2 = new String(bytes);//自动匹配byte[]构造
				
				String str3 = "abc";
				
				//2、调用常见功能
				System.out.println(  str.charAt(0)  );//获取指定下标对应的字符
				System.out.println(  str.concat("皮皮霞")  );//相当于拼接字符串
				System.out.println(  str.endsWith("c")  ); //判断是否以指定元素结尾
			
				//TODO  继续测试其他方法
				System.out.println(   str=="abc" );//==比较的是引用类型的变量,比较地址值
				System.out.println(   str.equals("abc")  );//判断是否与指定数据相等,String已经重写了equals()可以比较属性值
				System.out.println(   str.getBytes()  );//用来把数据存入byte[]
				System.out.println(   str.hashCode()  );//获取对象在内存中的哈希码值,相对于一个编号
				System.out.println(   str.indexOf("a")  );//返回指定数据 在字符串 中 第一次出现的 下标
				str= "abcbca";//思考:我们真的把字符串str的值改掉了吗?
				System.out.println(   str.lastIndexOf("a")  );//返回指定数据 在字符串 中 最后一次出现的 下标
				System.out.println(   str.length() );//获取字符串的长度
				System.out.println(   str.replace('a','x')  );//把字符串中出现的所有a字符  替换  成  x字符
				str = "a0Bc";
				System.out.println(   Arrays.toString(  str.split("0")  ) );//按照指定数据切割字符串   [a, bc]
				System.out.println(   str.startsWith("a")  );//判断是否以指定数据 开始 
				System.out.println(   str.substring(1)  );//从指定下标处开始   向后截取所有字符串[1,n]
				System.out.println(   str.substring(0,2)  );//从指定下标处开始  到 指定处结束,但是含头不含尾[0,2)
				System.out.println(   str.toLowerCase() );//把字符串中的所有数据 转成 小写
				System.out.println(   str.toUpperCase() );//把字符串中的所有数据 转成 大写
				str = "       a0B    c       ";
				System.out.println(   str.trim() );//去除前导多余空格和后导多余空格
				System.out.println( String.valueOf(9.9)  +1 );//把其他类型转成String类型
			}
		}	

4、StringBuilder/StringBuffer

一、构造方法

1、StringBuilder()
构造一个不带任何字符的字符串生成器,其初始容量为 16 个字符。

二、常用方法

1、StringBuilder append(String str)
将指定的字符串追加到此字符序列。

测试

package cn.tedu.api;
//这个类用来测试
public class Test1_StringBuilder {

	public static void main(String[] args) {
		method();// 先用+拼接字符串
		method2();// 用工具类拼接
	}

	public static void method2() {
		String str = "abcdefg";
		// 创建工具类对象
		StringBuilder sb = new StringBuilder();

		long start = System.currentTimeMillis();// 计时开始ms毫秒
		for (int i = 0; i < 1000; i++) {
			sb.append(str);// +拼接
		}
		long end = System.currentTimeMillis();// 计时结束
		System.out.println(end - start);
	}

	public static void method() {
		// 1、定义字符串
		String str = "abcdefg";

		// 2、拼接1000次输出//重复干,用for循环
		String result = "  ";// 定义变量,记录结果

		long start = System.currentTimeMillis();// 计时开始ms毫秒
		for (int i = 0; i < 1000; i++) {
			result = result + str;// +拼接
		}
		long end = System.currentTimeMillis();// 计时结束
		System.out.println(end - start);
		System.out.println(result);
	}
}

5、包装类

一、概念

为了丰富基本类型的功能,提供了对应的包装类型。
基本类型 byte short int long float double boolean char
包装类型 Byte Short Integer Long Float Double Boolean Character

二、Integer --包装了基本类型的int

1、创建对象
Integer(int value)
构造一个新分配的 Integer 对象,它表示指定的 int 值。

static Integer valueOf(int i) 返回一个表示指定的 int 值的 Integer 实例。

2、常用方法

int intValue()
以 int 类型返回该 Integer 的值。

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

总结:
包装类 和 基本类型 可以互相转换

①基本类型 转 包装类:valueOf() 或者 构造方法 — 目的是 使用包装类型身上的功能 – 自动装箱

②包装类 转 基本类型:intValue() — 目的是 拿到包装类 包着的值 做运算 – 自动拆箱

补充

1、基本型和基本型封装型进行“==”运算符的比较,基本型封装型将会自动拆箱变为基本型后再进行比较,因此Integer(0)会自动拆箱为int类型再进行比较,显然返回true;

     int a = 220;

     Integer b = 220;

    System.out.println(a==b);//true

2、两个Integer类型进行“==”比较, 如果其值在-128至127 ,那么返回true,否则返回false, 这跟Integer.valueOf()的缓冲对象有关,这里不进行赘述。

    Integer c=3;
    Integer h=3;
    Integer e=321;
    Integer f=321;
    System.out.println(c==h);//true
    System.out.println(e==f);//false

3、两个基本型的封装型进行equals()比较,首先equals()会比较类型,如果类型相同,则继续比较值,如果值也相同,返回true。

    Integer a=1;
    Integer b=2;
    Integer c=3;
    System.out.println(c.equals(a+b));//true

4、基本型封装类型调用equals(),但是参数是基本类型,这时候,先会进行自动装箱,基本型转换为其封装类型,再进行3中的比较。

    int i=1;
    int j = 2;
    Integer c=3;
    System.out.println(c.equals(i+j));//true

测试

package cn.tedu.api;
		//这个类用来测试  包装类
		public class Test2_Baozhuang {
			public static void main(String[] args) {
				//包装类 和  基本类型     可以互相转换
				//基本类型 转 包装类:valueOf()   或者  构造方法     ---   目的是  使用包装类型身上的功能  -- 自动装箱
				//包装类 转 基本类型:intValue()               --- 目的是  拿到包装类  包着的值  做运算   -- 自动拆箱

				//1、创建Integer对象
				//就是拿到基本类型  的参数  5 ,经过包装,,形成了  包装类型  的
				Integer in  = new Integer(5);
			
				//静态方法valueOf 高效(-128~127范围内),如果要存相同数据,只是第一次没存时会存一次,以后还要存相同数据时就不再存了。
				Integer in2  = Integer.valueOf(5);
				Integer in3  = Integer.valueOf(5);
				System.out.println(in2==in3);//true,只存了一次,in3没有再存
				System.out.println(in == in2);//false,两种方式存储了相同数据5
				
				//2、调用常用方法
				int value = in.intValue();
				
				int sum = in.parseInt("100");//把字符串类型的数字,转成基本类型
				System.out.println(sum + 1);

				//TODO double -- Double
				//自动装箱:把基本类型 double   变成 包装类型  Double --valueOf()
				Double dou = Double.valueOf(9.9);
				
				//自动拆箱: 把 包装类型的值  变成  基本类型    --doubleValue()
				double dou3 = dou.doubleValue();
				
				double dou2 = dou.parseDouble("8.8");//把字符串类型的数字,转成基本类型
		
				
			}
		}

6、日期类Date

一、创建对象

Date() : 分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。

二、常用方法

int getDate() 已过时。
从 JDK 1.1 开始,由 Calendar.get(Calendar.DAY_OF_MONTH) 取代。

int getDay() 已过时。
从 JDK 1.1 开始,由 Calendar.get(Calendar.DAY_OF_WEEK) 取代。

int getHours() 已过时。
从 JDK 1.1 开始,由 Calendar.get(Calendar.HOUR_OF_DAY) 取代。

int getMinutes() 已过时。
从 JDK 1.1 开始,由 Calendar.get(Calendar.MINUTE) 取代。

int getMonth() 已过时。
从 JDK 1.1 开始,由 Calendar.get(Calendar.MONTH) 取代。

int getSeconds() 已过时。
从 JDK 1.1 开始,由 Calendar.get(Calendar.SECOND) 取代。

long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。

测试

package cn.tedu.api;

		import java.util.Date;

		//这个类用来测试 日期工具类
		public class Test3_Date {
			public static void main(String[] args) {
				//1、创建Date对象
				Date date = new Date();
				
				//2、常见方法
				System.out.println(   date.getYear()   );//获取现在是多少年,从1900 开始
				System.out.println(   date.getDate()   );//获取今天是每个月的第几天
				System.out.println(   date.getDay()   );//获取今天是每周的第几天
				System.out.println(   date.getHours()   );//获取现在是几点钟
				System.out.println(   date.getMinutes()   );//获取现在是每小时的多少分钟
				System.out.println(   date.getMonth()   );//获取当前是几月,= 当前月 - 1
				System.out.println(   date.getSeconds()   );//获取现在是每分钟的多少秒
				System.out.println(   date.getTime()   );//获取当前的毫秒值,从1970 年 1 月 1 日 00
				System.out.println(   date.hashCode()   );//获取哈希码值
				System.out.println(   date.toLocaleString()   );//获取当前时间 年月日 时分秒
				
			}
		}

7、日期工具SimpleDateFormat

一、概念

用来把String类型的日期 和 Date类型的日期 互转

二、创建对象

SimpleDateFormat(String pattern)
用给定的模式和默认语言环境的日期格式符号构造

三、常见方法

①Date parse(String text)
解析字符串的文本,生成 Date。

②String format(Date date)
将Date类型的日期,转成 字符串类型

测试

package cn.tedu.api;

		import java.text.ParseException;
		import java.text.SimpleDateFormat;
		import java.util.Date;
		import java.util.Scanner;

		//这个类  用来测试 日期格式化工具:计算存活天数
		public class Test4_SimpleDate {
			public static void main(String[] args) throws ParseException {
				//1、输入出生日期  -- String
				String birthday = new Scanner(System.in).nextLine();
				
				//2、把string类型的日期  转成  Date类型
				//参数中,需要指定日期的格式  y-年 M-月 d-天 
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				Date birth = sdf.parse(birthday);
				
				//3、做个时间差ms--天
				long bir = birth.getTime();//获取到出生日期对应的毫秒值
				long now = System.currentTimeMillis();//获取现在的毫秒值
				
				System.out.println(  (now-bir)/1000/60/60/24   );
			}
		}

8、BigDecimal/BigInteger

一、概念

BigDecimal用来解决java中浮点数运算不精确的现象

BigInteger用来解决java中大整数的运算

9、BigDecimal

一、概念

用来解决java中浮点数运算不精确的现象

二、创建对象

①BigDecimal(double val)
将 double 转换为 BigDecimal,后者是 double 的二进制浮点值准确的十进制表示形式。

②BigDecimal(String val)
将 BigDecimal 的字符串表示形式转换为 BigDecimal。

三、常用方法

add(BigDecimal bd): 做加法运算

subtract(BigDecimal bd) : 做减法运算

multiply(BigDecimal bd) : 做乘法运算

divide(BigDecimal bd) : 做除法运算

测试

package cn.tedu.api;

		import java.math.BigDecimal;
		import java.util.Scanner;

		//这个类用来测试 浮点数运算不精确的解决方案
		public class Test5_BigDecimal {
			public static void main(String[] args) {
		//		method();//暴露不精确的现象
				method2();//解决方案
			}
			public static void method2() {
				double a = new Scanner(System.in).nextDouble();
				double b = new Scanner(System.in).nextDouble();
				//1、把a和b变成BigDecimal类型
				//!!!构造方法不建议使用double参数的(还是不精确),我们建议使用string参数的构造方法
				BigDecimal bd = new BigDecimal(a+"");
				BigDecimal bd2 = new BigDecimal(b+"");
				
				BigDecimal bd3 ;//记录运算结果
				bd3 = bd.add(bd2);//加法运算
				System.out.println(bd3);
				
				bd3 = bd.subtract(bd2);//减法运算
				System.out.println(bd3);
				
				bd3 = bd.multiply(bd2);//乘法运算
				System.out.println(bd3);
				
		//		bd3 = bd.divide(bd2);//报错:如果除法运算不精确,会抛出异常Non-terminating decimal expansion; no exact representable decimal result.(为什么会不精确,因为有时候小数除以小数本来就除不尽,所以会不精确)
				//divide(m,n,o)-m是要做除法运算的对象名,-n是要保留几位小数,-o是舍入方式(四舍五入)
				bd3 = bd.divide(bd2,3,BigDecimal.ROUND_HALF_UP);
				System.out.println(bd3);
			}
			public static void method() {
				//1、接收用户输入的两个小数	
				double a = new Scanner(System.in).nextDouble();
				double b = new Scanner(System.in).nextDouble();
				
				//2、做+-*/运算	
				System.out.println(a+b);//不精确
				System.out.println(a-b);//不精确
				System.out.println(a*b);//不精确
				System.out.println(a/b);//不精确
			}
		}

第九章 IO

一、概述

①继承结构

②in/out相对于程序而言的输入(读取)和输出(写出)的过程。

在Java中,根据处理的数据单位不同,分为字节流字符流

③字节流:针对二进制文件

字符流:针对文本文件。读写容易发生乱码现象,在读写时最好指定编码集为utf-8

1、File文件工具

一、概述

封装一个磁盘路径字符串,对这个路径可以执行一次操作。
可以用来封装文件路径、文件夹路径、不存在的路径。

二、创建对象

File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

二、常用方法

文件、文件夹属性

length():获取文件的字节量

exists():判断文件或者目录是否存在

isFile():是否为文件,是文件返回true

isDirectory():是否为文件夹(目录),是文件夹返回true

getName():获取文件/文件夹名

getParent():获取目录的路径

getAbsolutePath():获取文件的完整路径

创建、删除
createNewFile():新建文件,文件夹不存在会异常,文件已经存在返回false

mkdirs():新建多层不存在的文件夹\a\b\c,不存在的文件返回true,如果存在返回false

mkdir():新建单层不存在的文件夹\a,不存在的文件返回true,如果存在返回false

delete():删除文件,删除空文件夹

文件列表方法–列出文件夹里的资源

list():返回String[],包含文件名

listFiles():返回File[],包含文件对象

测试

package cn.tedu.io;

		import java.io.File;
		import java.io.IOException;
		import java.util.Arrays;

		//这个类用来测试  File工具类
		public class Test1_File {
			public static void main(String[] args) throws IOException {
				//1、创建对象-- 参数是路径,可以是文件的/文件夹的/不存在的
				File file = new File("D:\\iotest\\1.txt");//这是一个文件路径
				//2、常用方法
				System.out.println(  file.length()  );//获取文件的字节量
				System.out.println(  file.exists()  );//判断文件是否存在
				System.out.println(  file.isFile()  );//判断file是文件吗
				System.out.println(  file.isDirectory()  );//判断file是文件夹吗
				System.out.println(  file.getName()  );//获取文件名
				System.out.println(  file.getParent()  );//获取父目录
				System.out.println(  file.getAbsolutePath()  );//获取完整路径
				file = new File("D:\\iotest\\2.txt");//不存在的文件
				System.out.println(  file.createNewFile()  );//创建不存在的文件返回true,如果存在返回false
				file = new File("D:\\iotest\\b");//单层不存在的文件夹
				System.out.println(  file.mkdir()  );//创建单层不存在的文件夹
				file = new File("D:\\iotest\\m\\n\\o");//多层不存在的文件夹
				System.out.println(  file.mkdirs()  );//创建多层不存在的文件夹
				file = new File("D:\\iotest\\m\\n\\o\\1.txt");
				System.out.println(  file.delete()  );//删除文件   或者  删除 空的 文件夹
				//列表方法--列出文件夹里的资源
				file = new File("D:\\iotest");
				String[] strs = file.list();//列出文件的名称放入数组
				System.out.println(Arrays.toString(strs));
				File[] files = file.listFiles();//列出文件并封装成file对象放入数组
				System.out.println(Arrays.toString(files));
			}
		}

练习:递归求目录总大小

package cn.tedu.io;

		import java.io.File;
		import java.util.Scanner;

		//这个类用来测试 递归求目录总大小  
		/*
		 * 1、列出文件夹下的所有资源
		 * 2、判断当前的资源是文件吗?如果是文件直接length()求字节量的和  
		 * 3、判断当前的资源是文件夹吗?如果是文件夹  --  重复的干1 2 3的事情
		 */
		public class Test2_File2 {
			public static void main(String[] args) {
				//接收用户输入的目录  的路径
				String path = new Scanner(System.in).nextLine();
				//把路径封装成file对象
				File dir = new File(path);
				//调用size() ---求大小
				long total = size(dir);
				System.out.println(total);
			}
			
			//求大小
			public static long size(File dir) {
				//1、列出文件夹下的所有资源
				File[] a = dir.listFiles();
				
				//获取每个资源
				long sum = 0 ;//定义变量,记录和
				for (int i = 0; i < a.length; i++) {
					//2、判断当前的资源是文件吗?如果是文件直接length()求字节量的和  
					if(  a[i].isFile()  ){
						sum = sum + a[i].length() ;//每个文件的长度相加求和
					}else if( a[i].isDirectory() ) {
						//	3、判断当前的资源是文件夹吗?如果是文件夹  --  重复的干1 2 3的事情
						sum = sum + size(a[i]) ; //递归调用  size()   求目前资源a[i]的大小
					}
				}
				return sum;
			}
		}

2、字节流读取(In)

一概述

读取:是指程序需要读取 / 输入 / in:是从磁盘读到程序中来

字节流:啥都行(啥文件都能读取)

InputStream:是字节流 读取流的父类 。是抽象类,不能创建对象(所有只能找其子类来创建对象),只能学习共性方法。

二、共性方法

void close()
关闭此输入流并释放与该流关联的所有系统资源。

abstract int read()
从输入流中读取数据的下一个字节

int read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

int read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入 byte 数组。

FileInputStream:子类,继承了父类的方法,就不重复学父类的方法了。直接学习创建对象就行

创建对象

FileInputStream(File file)

FileInputStream(String name)

BufferedInputStream:子类,继承了父类的方法,就不重复学父类的方法了。直接学习创建对象就行(具有高效率)

创建对象
BufferedInputStream(InputStream in)

字节流读取测试

package cn.tedu.in;
			import java.io.BufferedInputStream;
			import java.io.File;
			import java.io.FileInputStream;
			import java.io.IOException;
			import java.io.InputStream;
			//这个类用来测试字节流   读取
			//总结:
			//字节流的读取:普通流FileInputStream和高效流BufferedInputStream
			//效率上来讲:BufferedInputStream  >  FileInputStream
			//原因:BufferedInputStream底层维护了一个数组,把数组读满了直接给程序一次就行,减少交互提高效率
			public class Test3_In {
				public static void main(String[] args) {
			//		method();//方法调用,用普通子类FileInputStream
					method2();//用高效子类BufferedInputStream
				}
				private static void method2() {
					try {
						//1,创建字节读取流对象  
						InputStream in = new BufferedInputStream( new FileInputStream("D:\\iotest\\1.txt") ) ;//构造方法需要InputStream类型的参数,没有就new
						//2、开始读取
						int b = 0 ;//定义变量,记录读取到的数据
						while(   ( b  = in.read()  )  !=  - 1  ) {
							System.out.println(b);
						}
						//3、释放资源
						in.close();
					} catch (IOException e) {//捕获一个大点的异常,io操作中最大的就是IOException
						e.printStackTrace();
					}
				}
				public static void method() {
					try {
						//1,创建字节读取流对象
						InputStream in = new FileInputStream(new File("D:\\iotest\\1.txt")  );//触发FileInputStream(File) 构造方法
						InputStream in2 = new FileInputStream("D:\\iotest\\1.txt");//触发FileInputStream(String) 构造方法
						//2、调用父类的功能,开始读取
			//			 System.out.println(  in.read()  ); //从输入流中读取数据的下一个字节
			//			 System.out.println(  in.read()  ); 
			//			 System.out.println(  in.read()  ); 
			//			 //3、当读取到没有数据了的到时候,read()返回-1
			//			 System.out.println(  in.read()  ); 
						//读取的代码改造
						int b = 0 ; //定义变量,记录读取到的数据
						while(  (  b = in.read()  )  !=  -1 ) {//有数据才读,没数据时read()返回-1时就不读了 
							System.out.println(b);
						}
						 //4、释放资源
						 in.close();
						 in2.close();
					} catch (IOException e) {//捕获一个大的异常
						e.printStackTrace();
					}
					
				}
			}

3、字符流读取(In)

一、概述

①常用于处理纯文本数据。

②只能读取字符文件,txt

Reader:是字符流读取流的父类。是抽象类,不能创建对象(所有只能找其子类来创建对象),所以只能学共性方法。

二、共性方法

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

int read()
读取单个字符。

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

abstract int read(char[] cbuf, int off, int len)
将字符读入数组的某一部分。

int read(CharBuffer target)
试图将字符读入指定的字符缓冲区。

FileReader:子类,继承了父类的共性方法,直接学子类创建对象

创建对象
FileReader(File file)
FileReader(String fileName)

BufferedReader:子类,继承了父类的共性方法,直接学子类创建对象,(高效对象读取)

创建对象

BufferedReader(Reader in)

测试

package cn.tedu.in;
			import java.io.BufferedReader;
			import java.io.File;
			import java.io.FileReader;
			import java.io.IOException;
			import java.io.Reader;
			//这个类用来测试  字符 读取流
			//总结:
			//字符读取流:普通对象读取FileReader,高效对象读取BufferedReader
			//效率来讲:BufferedReader  > FileReader
			//原因:BufferedReader底层也维护了一个char[](默认容量是8K),读取时满了一个数组给程序一次,减少交互提高效率
			public class Test4_Reader {
				public static void main(String[] args) {
					method();//普通读取流FileReader
					method2();//高效读取流BufferedReader
				}
				private static void method2() {
					try {
						//1,创建对象
						Reader in = new BufferedReader(new FileReader("D:\\iotest\\1.txt"));
						//2,开始读取
						int b = 0;//定义变量,记录每次读取到的数据
						while( ( b = in.read()  )    !=  -1 ) {
							System.out.println(b);
						}
						//3,释放资源
						in.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				//普通读取流
				public static void method() {
					try {
						//1,创建对象
						Reader in = new FileReader("D:\\iotest\\1.txt");//触发FileReader(String)构造方法
						Reader in2 = new FileReader( new File("D:\\iotest\\1.txt") );//触发FileReader(File)构造方法
						//2,开始读取
						int b = 0;//定义变量,记录每次读取到的数据
						while( ( b = in.read()  )    !=  -1 ) {
							System.out.println(b);
						}
						//3,释放资源
						in.close();
						in2.close();
					} catch (IOException e) {// 捕获大异常
						e.printStackTrace();
					}
				}
				
			}

4、字节流写出(Out)

一、概述

写出:是指程序需要写出/输出/out:是从程序写出到磁盘中

字节流:啥都行()

OutputStream,字节输出流的父类。抽象类,不能创建对象(所有只能找其子类来创建对象),只能学习共性方法

二、共性方法

void close()
关闭此输出流并释放与此流有关的所有系统资源。

void flush()
刷新此输出流并强制写出所有缓冲的输出字节。

void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。

void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

abstract void write(int b)
将指定的字节写入此输出流。

FileOutputStream:子类,使用了父类的共性方法,只要学习创建对象

创建对象
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)

BufferedOutputStream :子类,使用了父类的共性方法,只要学习创建对象

创建对象

BufferedOutputStream(OutputStream out)

测试

package cn.tedu.out;
			import java.io.File;
			import java.io.FileOutputStream;
			import java.io.IOException;
			import java.io.OutputStream;
			//这个类用来测试  字节输出流
			public class Test5_Out {
				public static void main(String[] args) {
					method();//普通输出流
					method2();//TODO 高效输出流
					//TODO  谁是高效的?为什么?
				}

				private static void method2() {
					//1,创建对象
					//2,开始写出
					//3,释放资源
				}

				private static void method() {
					try {
						//1,创建对象
						OutputStream out  = new FileOutputStream("D:\\iotest\\1.txt");
						OutputStream out2  = new FileOutputStream(  new File("D:\\iotest\\1.txt") );
						
						//2,开始写出
						out.write(97);
						
						//3,释放资源
						out.close();
					} catch (IOException e) {//捕获大异常
						e.printStackTrace();
					}
				}
			}

5、字符流写出(Out)

一、写出文本数据

Writer:是字符写出流的父类。是抽象类,不能创建对象,只能学习他的共性方法

二、共性方法

abstract void close()
关闭此流,但要先刷新它。

abstract void flush()
刷新该流的缓冲。

void write(char[] cbuf)
写入字符数组。

abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分。

void write(int c)
写入单个字符。

void write(String str)
写入字符串。

void write(String str, int off, int len)
写入字符串的某一部分。

FileWriter:子类。 不再学习父类的共性方法,只学习创建对象

创建对象

FileWriter(File file) :根据给定的 File 对象构造一个 FileWriter 对象

FileWriter(File file, boolean append) :根据给定的 File 对象构造一个 FileWriter 对象。

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

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

BufferedWriter:子类。 不再学习父类的共性方法,只学习创建对象(高效)

创建对象

BufferedWriter(Writer out):创建一个使用默认大小输出缓冲区的缓冲字符输出流

测试

package cn.tedu.out;
			import java.io.BufferedWriter;
			import java.io.FileWriter;
			import java.io.IOException;
			import java.io.Writer;
			//这个类用来测试 字符输出流
			//总结
			//字符输出流:两种:普通流FileWriter  高效流BufferedWriter
			//效率上来讲:BufferedWriter  >   FileWriter
			//原因:BufferedWriter底层维护了一个缓冲数组char[] ,默认大小8K,减少给磁盘的次数,提高效率
			public class Test1_Writer {
				public static void main(String[] args) {
			//		method();//普通对象FileWriter
					method2();//高级流
				}
				private static void method2() {
					Writer out = null ;
					try {
						//1,创建对象
						out = new BufferedWriter (  new FileWriter("D:\\iotest\\1.txt",true)   )  ;
						//2,开始写出
						out.write(50);
						out.write("信你个鬼啊");//字符流可以写出字符串
						
						out.flush();  //把缓冲区的数据,刷到磁盘里 显示
					} catch (IOException e) {
						e.printStackTrace();
					}finally {
						try {
							//3,释放资源
							out.close();   //两个功能:先把数据从缓冲区刷出去  后  释放资源
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}

				private static void method() {
					Writer out = null ;
					try {
						//1,创建对象
						out = new FileWriter("D:\\iotest\\1.txt");
						//2,开始写出
						out.write(49);
						out.write("我爱java");//字符流可以写出字符串
					} catch (IOException e) {
						e.printStackTrace();
					}finally {
						try {
							//3,释放资源
							out.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}

IO练习:文件复制

package cn.tedu.io;
		import java.io.BufferedInputStream;
		import java.io.BufferedOutputStream;
		import java.io.BufferedReader;
		import java.io.BufferedWriter;
		import java.io.File;
		import java.io.FileInputStream;
		import java.io.FileOutputStream;
		import java.io.FileReader;
		import java.io.FileWriter;
		import java.io.IOException;
		import java.io.InputStream;
		import java.io.OutputStream;
		import java.io.Reader;
		import java.io.Writer;

		//这个类用来测试  文件复制
		//1、读取源文件
		//2、把数据写出到 目标文件中
		public class Test2_Copy {
			public static void main(String[] args) {
				File from = new File("D:\\iotest\\1.jpg");// 源文件
				File to = new File("D:\\iotest\\2.jpg");// 目标文件
				// copy(from,to);//完成复制 -- 字节流---什么类型的文件都可以操作
				copy2(from, to);// 完成复制 -- 字符流--只能操作字符文件
			}
			// 字符流操作  --  只能操作字符文件 
			private static void copy2(File from, File to) {
				try {
					// 1、读取源文件 -- 字节流 高效流
					Reader in = new BufferedReader(new FileReader(from));
					// 2、把数据写出到 目标文件中
					Writer out = new BufferedWriter(new FileWriter(to));
					// 3、边读边写
					int b = 0; // 定义变量,记录读取到的数据
					while ((b = in.read()) != -1) {// 只要有数据就一直读
						out.write(b);// 读一个写一个
					}
					// TODO 4、释放资源
					in.close();
					out.close();
				} catch (IOException e) {// 捕获大点的异常
					e.printStackTrace();
				}
			}

			// 字节流操作
			private static void copy(File from, File to) {
				try {
					// 1、读取源文件 -- 字节流 高效流
					InputStream in = new BufferedInputStream(new FileInputStream(from));
					// 2、把数据写出到 目标文件中
					OutputStream out = new BufferedOutputStream(new FileOutputStream(to));
					// 3、边读边写
					int b = 0; // 定义变量,记录读取到的数据
					while ((b = in.read()) != -1) {// 只要有数据就一直读
						out.write(b);// 读一个写一个
					}
					// TODO 4、释放资源
					in.close();
					out.close();
				} catch (IOException e) {// 捕获大点的异常
					e.printStackTrace();
				}
			}
		}

IO练习:批量读写

package cn.tedu.io;
		import java.io.BufferedInputStream;
		import java.io.BufferedOutputStream;
		import java.io.BufferedReader;
		import java.io.BufferedWriter;
		import java.io.File;
		import java.io.FileInputStream;
		import java.io.FileOutputStream;
		import java.io.FileReader;
		import java.io.FileWriter;
		import java.io.IOException;
		import java.io.InputStream;
		import java.io.OutputStream;
		import java.io.Reader;
		import java.io.Writer;

		//这个类用来测试  批量读写
		//1、读取源文件
		//2、把数据写出到 目标文件中
		public class Test2_Copy {
			public static void main(String[] args) {
				File from = new File("D:\\iotest\\1.txt");// 源文件
				File to = new File("D:\\iotest\\2.txt");// 目标文件
				copy2(from, to);// 完成复制 -- 字符流--只能操作字符文件
			}
			// 字符流操作  --  只能操作字符文件 
			private static void copy2(File from, File to) {
				try {
					// 1、读取源文件 -- 字符流 高效流(可以用字节流)
					Reader in = new BufferedReader(new FileReader(from));
					// 2、把数据写出到 目标文件中
					Writer out = new BufferedWriter(new FileWriter(to));
					// 3、边读边写
					
					//批量读写,数组的容量到底多大是比较合适的?8*1024=8K
					char[] cs = new char[8*1024]  ;
					int b = 0; // 定义变量,记录读取到的数据
					while ((b = in.read(cs)) != -1) {// read(char[]) --按照数组的容量读取数据--批量读取
						out.write(cs,0,b);//write(char[]) --按照数组的容量写出数据-- 批量写出
				//write(m,n,o);--m是你要写出的数组名--n是你要从数组的哪个位置开始向后写出--o是你要写出多少数据(有多少写多少)
					}
					// TODO 4、释放资源
					in.close();
					out.close();
				} catch (IOException e) {// 捕获大点的异常
					e.printStackTrace();
				}
			}
		}

6、序列化 / 反序列化

一、序列化:是指把java程序中的对象,永久存储到磁盘的过程。–out

二、构造方法

ObjectOutputStream(OutputStream out) :传入一个你要写到磁盘文件的哪个路径

三、常用方法

void writeObject(Object obj) :将指定的对象写入 ObjectOutputStream

四、反序列化:是指把磁盘中的已经 序列化好的文件 恢复到 java程序中来。-- in

五、构造方法

ObjectInputStream(InputStream out):传入一个反序列化文件的路径

六、常用方法

Object readObject():从 ObjectInputStream 读取对象。

七、 特点/应用场景

1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。

2、 不需要序列化的数据可以被修饰为static的,由于static属于类,不随对象被序列化输出。

3、 不需要序列化的数据也可以被修饰为transient临时的,只在程序运行期间,在内存中存在不会被序列化持久保存。

4、 在反序列化时,如果和序列化的版本号不一致时,无法完成反序列化。

5、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。

6、 常用于服务器之间的数据传输,序列化成文件,反序列化读取数据。

7、 常用于使用套接字流在主机之间传递对象。

测试

package cn.tedu.seria;

		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.io.Serializable;

		//这个类用来测试  对象的序列化
		public class Test3_Serializ {
			public static void main(String[] args) {
				method();  //完成序列化
				method2();  //完成反序列化
			}
			//反序列化:磁盘中 -- > java对象 ---ObjectInputStream
			private static void method2() {
				try {
					ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\iotest\\1.txt"));
					//反序列化方法
					Object obj = in.readObject();
					//Student [name=皮皮霞, age=18, score=99.9]
					System.out.println(obj);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			//序列化:java对象 -- > 磁盘中---ObjectOutputStream
			private static void method() {
				try {
					//1、创建对象
					Student s = new Student("皮皮霞",18,99.9);
					ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream( "D:\\iotest\\1.txt" ) ) ;
					//2、完成序列化,序列化文件我们看不懂!!
					out.writeObject(s);
					//3、释放资源
					out.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}	
		//4、创建学生类  ,如果想要完成序列化,必须实现序列化接口,否则java.io.NotSerializableException
		class Student  implements  Serializable{
			//5、实现序列化接口后,要生成唯一的版本号id值作为文件的标志
			private static final long serialVersionUID = 1L;
			//构造方法
			public Student() {}
			public Student(String name, int age, double score) {
				this.name = name;
				this.age = age;
				this.score = score;
			}
			private String name;
			private int age;
			private double score;

			//set()/get()
			public String getName() {
				return name;
			}
			public void setName(String name) {
				this.name = name;
			}
			public int getAge() {
				return age;
			}
			public void setAge(int age) {
				this.age = age;
			}
			public double getScore() {
				return score;
			}
			public void setScore(double score) {
				this.score = score;
			}
		//	toString()为了方便查看对象的属性值而不是地址值
			@Override
			public String toString() {
				return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
			}
		}

7、编码转换流

一、概念

用来作为桥梁,把字节流转成字符流的桥梁。
用来解决字符流读写乱码问题。

OutputStreamWriter:转换流,把字节输出流 转成 字符 输出流

构造方法

继承自Writer
–OutputStreamWriter(OutputStream out)
–OutputStreamWriter(OutputStream out, String charsetName)

InputStreamReader:转换流,把字节读取流 转成 字符 读取流

构造方法

继承自Reader
–InputStreamReader(InputStream in)
–InputStreamReader(InputStream in, String charsetName)

测试

package cn.tedu.io;

		import java.io.BufferedReader;
		import java.io.FileInputStream;
		import java.io.FileOutputStream;
		import java.io.InputStream;
		import java.io.InputStreamReader;
		import java.io.OutputStream;
		import java.io.OutputStreamWriter;
		import java.io.Reader;
		import java.io.Writer;

		//这个类 用来测试 编码转换流
		// 字节流   ---  >  字符流
		public class Test4_Encoding {
			public static void main(String[] args) {
				try {
		//			//1、创建字节流
					OutputStream out = new FileOutputStream("1.txt");
					//2、创建字符流,OutputStreamWriter 用来把字节输出流 转换成 字符输出流
		//OutputStreamWriter(m,n)--m是要写出的字节流对象,n是要使用的编码表
					Writer out2 = new OutputStreamWriter(out,"gbk")  ;  
					//3、写出字符串
					out2.write("大家好,我叫渣渣辉");
					//4、释放资源
					out2.close();
					
					System.out.println();
					
					InputStream in = new FileInputStream("1.txt");
					//5、读取时乱码,也可以设置编码表来解决乱码现象
					BufferedReader reader = new BufferedReader ( 
																		new InputStreamReader(in,"gbk")   );
					//打印读取到的一整行数据
					System.out.println(  reader.readLine()   );
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

第十章(泛型、集合)

1、泛型

一、概述

标志是<> ,通常配合集合一起使用

好处:可以进行数据类型检查。还可以把报错时机提前到编译期。

泛型传入的必须是包装类型,或者是自定义的类,不能传入基本类型例如int ,必须要传包装类型如Integer

好处1:编译时类型检查

测试

package cn.tedu.generic;
		import java.util.ArrayList;

		//这个类用来测试  泛型
		public class Test5_Generic {
			public static void main(String[] args) {
				int[] a = new int[3];
				//1、泛型就想模拟  数组,在编译时期,就检查数据的类型有没有符合要求
		//		a[0] = 9.9 ;
		//		a[1] = "jack" ;
				a[2] = 10 ;
				
				//创建集合
				//2、来意:是约束集合中的元素的  类型。
		//		ArrayList list = new ArrayList();//没有约束
				//3、泛型中,只能写 引用类型,不能是基本类型。
				ArrayList<Integer> list = new ArrayList<>();//有约束
				
				//向集合中存放元素
				//4、在编译期就会报错,提前了报错时机。
		//		list.add(9.9);   //报错,不符合泛型的类型检查。
		//		list.add("rose");   //报错,不符合泛型的类型检查
				list.add(10);
				
			}
			
			
		}

好处2:代码通用性更强

知识点:高效for循环 foreach循环 语法: for(数据的类型 变量名 : 要遍历的数据)

package cn.tedu.generic;

		//这个类用来 测试  泛型的通用性
		public class Test1_Generic {
			public static void main(String[] args) {
				Integer[] a = { 1, 2, 3, 4, 5 };
				Double[] b = {1.1,2.2,3.3,4.4,5.5};
				String[] c = {"a1","a2","a3","a4"};
				print(a);
				print(b);
				print(c);
			}
			//1、泛型可以使用在类(接口)上,也可以使用在方法上(返回值前+参数列表)
			//2、约束了参数类型是泛型类型
			private static <E> void print(E[] a) {
				//普通for   foreach :效率上foreach>普通for。语法上foreach简洁。
				//用处:普通for可以按照下标获取元素,foreach不可以。
				// for (int i = 0; i < a.length; i++) { syso(a[i]); }//低效
				// 高效for循环 foreach循环 语法: for(数据的类型 变量名 : 要遍历的数据)
				for (E in : a) {
					System.out.println(in);//打印获取到的数据
				}
			}
		}

2、集合(Collection、Map接口)

一、概述

1、现在的程序中,怎么存放多个数据? – 数组
数组缺点:只能存放相同类型的数据。长度不可变。遍历方式单一。

2、由于数组存在缺点,所以产生了多种集合。(跟数组类似)
优点:长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法

在这里插入图片描述
二、Collection接口

1、Collection是根接口。既然是接口就不能创建对象,我们只能学习他的共性方法。创建对象用实现类ArrayList(多态创建对象)(java.util.这个工具包里面)

2、共性方法

boolean add(E e): 添加元素

void clear() :清空元素

boolean contains(Object o) :判断集合中是否包含指定元素

boolean equals(Object o) :判断集合是否和指定元素相等

int hashCode() :返回集合对象在内存中的哈希码值

boolean isEmpty() :判断集合是否为空

boolean remove(Object o) :判断是否删除成功

int size() :获取集合的长度

Object[] toArray() :适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。

集合与集合间的操作

boolean addAll(Collection<? extends E> c) :向一个集合添加另一个集合的元素

boolean containsAll(Collection<?> c) :判断一个集合中是否包含另一个集合中的元素

boolean removeAll(Collection<?> c) :移除此 集合中那些也包含在指定集合 中的所有元素

boolean retainAll(Collection<?> c) : 仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。

测试


		package cn.tedu.collection;

		import java.util.ArrayList;
		import java.util.Arrays;
		import java.util.Collection;
		import java.util.Iterator;

		//这个类用来测试 Collection 接口
		public class Test2_Collection {
			public static void main(String[] args) {
				// 1、创建对象
				Collection<String> col = new ArrayList();
				// 2、常用方法
				col.add("jack");// 添加元素
				col.add("rose");
				col.add("hanmeimei");
				// col.clear();//清空集合
				System.out.println(col.contains("jack"));//判断集合中是否包含指定元素
				System.out.println(col.equals("韩梅梅"));//判断集合是否和指定元素相等
				System.out.println(col.hashCode());//返回集合对象在内存中的哈希码值
				System.out.println(col.isEmpty());//判断集合是否为空
				System.out.println(col.remove("rose"));//返回是否删除成功
				System.out.println(col.size());//获取集合的长度
				System.out.println(   Arrays.toString(  col.toArray()  )   );//把集合转成Object[]
				// 集合间的操作
				Collection<String> col2 = new ArrayList();
				col2.add("1");
				col2.add("2");
				col2.add("3");
				System.out.println(col.addAll(col2));//向col集合中添加col2集合的元素
				System.out.println(col.containsAll(col2));//判断col中是否包含col2的元素
		//		System.out.println(col.removeAll(col2));//删除col2的元素
		//		System.out.println(col.retainAll(col2));//删除col集合的元素

				// 迭代器:迭代/遍历集合中的元素
				Iterator it = col.iterator();
				while( it.hasNext()  ) {//hasNext()判断集合中有下一个元素吗
					System.out.println(  it.next()  ); //next()获取遍历到的元素
				}
				
			}
		}

3、List接口

一、概述

不能创建对象,由实现类ArrayList和LinkedList来创建对象

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数(下标值)索引(在列表中的位置)访问元素,并搜索列表中的元素

二、特点

1、 数据有序
2、 允许存放重复元素
3、 元素都有索引(下标值)

三、常用方法

1、省略从Collection接口继承过来的方法

2、List接口特有方法:

void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。

boolean addAll(int index, Collection<? extends E> c)
E get(int index)
返回列表中指定位置的元素。

int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。

int lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。

ListIterator listIterator()
返回此列表元素的列表迭代器(按适当顺序)。

E remove(int index)
移除列表中指定位置的元素(可选操作)。

E set(int index, E element)
用指定元素替换列表中指定位置的元素(可选操作)。

List subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。

boolean addAll(Collection<? extends E> c) :在指定下标处 添加集合
测试

package cn.tedu.collection;
		import java.util.ArrayList;
		import java.util.Iterator;
		import java.util.List;
		import java.util.ListIterator;
		//这个类用来测试   List接口
		public class Test3_List {
			public static void main(String[] args) {
				//1、创建对象
				List<String> list  = new ArrayList();
				
				//2、常用方法
				//从Collection接口继承过来的方法  - 略,同Test2_Collection.java。
				list.add("xiongda");
				list.add("xionger");
				list.add("guangtouq");
				list.add("xionger");
				list.add("guangtouq");
				
				//List接口特点:元素都有序   +  允许存放重复元素   
				System.out.println(list);//[xiongda, xionger, guangtouq]
				
				System.out.println();
				//3、List接口的特有方法---都是可以按照索引操作的方法
				System.out.println(list);
				list.add(3,"钢铁侠");//在指定下标处添加元素
				System.out.println(list);
				System.out.println(   list.get(2)  );//获取指定下标对应的元素
				System.out.println(   list.indexOf("xionger")  );//获取指定元素  第一次 出现的 下标值
				System.out.println(   list.lastIndexOf("guangtouq")  );//获取指定元素  最后一次 出现的 下标值
				System.out.println(   list.remove(1)  );//删除指定下标的元素,并返回
				System.out.println(   list.set(0,"hanmeimei") );//把指定下标  的元素  替换成指定元素
				System.out.println(list);
				
				List<String> newList = list.subList(1, 3);//截取子List,含头不含尾[1,3)
				System.out.println(newList);
				
				List<String> list2  = new ArrayList();
				list2.add("99");
				list2.add("98");
				list2.add("97");
				System.out.println(  list.addAll(2, list2)    );//在指定下标处  添加集合
				System.out.println(list);
				
				//4、迭代器
				//普通for循环  for( 1; 2; 3){ ?  }
				for(int i = 0 ; i< list.size()   ; i++) {
					System.out.println(  list.get(i) );//根据下标i获取元素
				}
				//foreach
				for( String str : list ) {
					System.out.println(str);
				}
				//继承Collection接口iterator()
				Iterator<String> it = list.iterator() ;
				while(  it.hasNext() ) {//hasNext() 判断有没有下个元素
					String s = it.next();//next()获取元素
					System.out.println(s);
				}
				//Collection接口 iterator()  ---      返回值 Iterator (父接口)
				//List接口           listIterator()  ---返回值  ListIterator(子接口)--继承了父接口的所有功能的同时,又有功能扩展
				ListIterator<String> it2 = list.listIterator();
				while( it2.hasNext() ) {  // 判断后面有没有元素
					String str = it2.next() ;//获取元素
					System.out.println(str);
				}
				
			}
		}

4、ArrayList(实现类)

一、特点

1、特点
底层维护了一个数组,默认初始容量是10。

初始容量不够会自动按照1.5倍的方式扩容。

ArrayList底层维护很多操作的方法,本质上就是对数组的操作。

适合用于查询多增删少的场景。

存在于java.util包中。

内部用数组存放数据,封装了数组的操作,每个对象都有下标。

2、创建对象
ArrayList() :构造一个初始容量为 10 的空列表。

5、LinkedList(实现类)

一、特点

底层维护了一个链表结构。

适用于增删多而查询少的场景。

对于链表中的节点操作效率并不高,但是对于首尾两个节点操作效率高。

二、创建对象’

LinkedList() :构造一个空列表。

三、常用方法

void addFirst(E e) :将指定元素插入此列表的开头。

void addLast(E e) :将指定元素添加到此列表的结尾。

E getFirst() :返回此列表的第一个元素。

E getLast() : 返回此列表的最后一个元素

E removeFirst() : 移除并返回此列表的第一个元素。

E removeLast() :移除并返回此列表的最后一个元素。

boolean offer(E e) :将指定元素添加到此列表的末尾(最后一个元素)。

boolean offerFirst(E e) :在此列表的开头插入指定的元素。

boolean offerLast(E e) :在此列表末尾插入指定的元素。

E peek() :获取但不移除此列表的头(第一个元素)。

E peekFirst() :获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。

E peekLast() :获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。

E poll() :获取并移除此列表的头(第一个元素)

E pollFirst() :获取并移除此列表的第一个元素;如果此列表为空,则返回 null。

E pollLast() : 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。

测试

package cn.tedu.collection;

		import java.util.LinkedList;

		//这个类用来测试 LinkedList
		public class Test5_LinkedList {
			public static void main(String[] args) {
				//1,创建对象
				//特点:和List一样,元素有序,可以重复
				LinkedList<Integer> list = new LinkedList<>();
				
				//2,常用方法
				list.add(100);
				list.add(200);
				list.add(300);
				list.add(null);
				list.add(null);
				
				list.addFirst(0);//添加首元素
				list.addLast(99);//添加尾元素
				System.out.println(list);
				
				System.out.println(  list.getFirst()  );//获取首元素
				System.out.println(  list.getLast()  );//获取尾元素
				
				System.out.println(  list.removeFirst()  );//移除首元素
				System.out.println(  list.removeLast()  );//移除尾元素
				System.out.println(list);
				
				//迭代(遍历)
				for(Integer n:list) {
				System.out.println(n);//获取集合中的每一个元素
				}
				
				
			}
		}

6、set接口

一、特点

元素无序,不可重复,没有索引。

常用方法:
略。同Collection接口一样

测试

Set集合给自定义--测试对象去重!!
	--如果想利用set集合给自定义对象去重,需要同时重写hashCode()equals()
	--测试
		package cn.tedu.collection;

		import java.util.HashSet;

		//这个类用来测试  Set集合自定义对象去重!
		//总结:
		//!!如果想要使用set集合,给你的自定义  对象  去重的话  ,,需要同时重写hashCode()  和equals()
		//重写hashCode():原来的实现方式是:只要new就会给计算一个新的哈希码值。
									//现在需要按照对象的属性值计算哈希码值,就算new两次,属性值一样时也必须产生相同哈希码值
		//重写equals():原来比的是两个对象间的地址值,现在要去比较两个对象间的属性值,如果属性值都一样,必须相同
		public class Test1_Set {
			public static void main(String[] args) {
				HashSet<Student> set = new HashSet<>();
				// 创建元素
				Student s1 = new Student("西门庆", 20);
				Student s2 = new Student("武大郎", 19);
				Student s3 = new Student("潘金莲", 21);
				Student s4 = new Student("小龙女", 23);

				set.add(s1);
				set.add(s2);
				set.add(s3);
				set.add(s4);
				
				Student s5 = new Student("潘金莲", 21);
				Student s6 = new Student("小龙女", 23);
				//!!!往set中添加重复元素--属性值完全相同的两个对象没给去重!!
				set.add(s5);
				set.add(s6);
				System.out.println(s3.hashCode());
				System.out.println(s5.hashCode());
				//满足以下的判断条件,才能给自定义对象去重!!
		        // if ( p.hash == hash &&  ((k = p.key) == key || (key != null && key.equals(k))))
				//条件1:p.hash == hash --判断两个对象的hash值一样吗?不一样!
				//需求1:就算new两次,只要两个对象间的属性值完全一样,给我产生一样的哈希码值就好了 -  重写hashCode()
				//条件2:key.equals(k)--让两个对象间的equals()返回true  -  重写equals()
				System.out.println(set);
			}
		}
		class Student {
			public Student() {
			}
			public Student(String name, int age) {
				this.name = name;
				this.age = age;
			}
			private String name;
			private int age;
			public String getName() {
				return name;
			}
			public void setName(String name) {
				this.name = name;
			}
			public int getAge() {
				return age;
			}
			public void setAge(int age) {
				this.age = age;
			}
			@Override
			public String toString() {
				return "Student [name=" + name + ", age=" + age + "]";
			}
			@Override
			public int hashCode() {
				final int prime = 31;
				int result = 1;
				result = prime * result + age;
				result = prime * result + ((name == null) ? 0 : name.hashCode());
				return result;
			}
			@Override
			public boolean equals(Object obj) {
				if (this == obj)
					return true;
				if (obj == null)
					return false;
				if (getClass() != obj.getClass())
					return false;
				Student other = (Student) obj;
				if (age != other.age)
					return false;
				if (name == null) {
					if (other.name != null)
						return false;
				} else if (!name.equals(other.name))
					return false;
				return true;
			}
			
		}

7、HashSet(实现类)

一、特点

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

二、创建对象

HashSet() :构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75

三、常用方法

略,同Collection接口的方法

测试

package cn.tedu.collection;

		import java.util.HashSet;
		import java.util.Set;

		//这个类用来测试 HashSet
		public class Test6_HashSet {
			public static void main(String[] args) {
				//1,创建对象
				Set<Integer> set = new HashSet<>();
				
				//2,常用方法
				set.add(10);//添加元素
				set.add(2);
				set.add(3);
				set.add(4);
				set.add(5);
				set.add(null);
				
				set.add(4);
				set.add(5);
				
				//set集合的特点:元素无序。 元素不能重复。
				//HashSet底层维护一个哈希表/散列表。
				System.out.println(set);
			
				//TODO 测试 常用方法
				
				
			}
		}

8、Map接口

一、概述

接口 Map<K,V>
类型参数: K - 此映射所维护的键的类型V - 映射值的类型。
也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复.(实现类HashMap)

二、特点

可以根据键 提取对应的值

键不允许重复,如果重复值会被覆盖

存放的都是无序数据

初始容量是16,默认的加载因子是0.75

三、常用方法

V put(K key, V value)
将指定的值与此映射中的指定键关联(可选操作)。

V remove(Object key)
如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

V get(Object key)
返回指定键所映射的值

void clear()
从此映射中移除所有映射关系

boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。

boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。

boolean equals(Object o)
比较指定的对象与此映射是否相等。

int hashCode()
返回此映射的哈希码值。

boolean isEmpty()
如果此映射未包含键-值映射关系,则返回 true。

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

void putAll(Map<? extends K,? extends V> m)
从指定映射中将所有映射关系复制到此映射中(可选操作)。

Collection values()
返回此映射中包含的值的 Collection 视图。

Set keySet()
返回此映射中包含的键的 Set 视图。

Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射关系的 Set 视图。
在这里插入图片描述

测试

package cn.tedu.collection;

		import java.util.Collection;
		import java.util.HashMap;
		import java.util.Iterator;
		import java.util.Map;
		import java.util.Map.Entry;
		import java.util.Set;

		//这个类用来测试  Map接口
		public class Test2_Map {
			public static void main(String[] args) {
				// 1,创建map对象
				// map集合中,需要同时约束键和值的 元素 类型
				Map<Integer, String> map = new HashMap();

				// 2,常用方法
				// 向map中添加数据时,需要同时指定key和value的值
				map.put(9529, "秋香姐");
				map.put(9527, "唐伯虎");
				map.put(9528, "如花");
				map.put(9528, "石榴姐");
				
				// 特点:数据无序 + 当key相同时value会被覆盖
				System.out.println(map);

				// map.clear();
				System.out.println(map.containsKey(9527));// 是否包含指定的key
				System.out.println(map.containsValue("如花"));// 是否包含指定的value
				System.out.println(map.equals("石榴姐"));// 判断两者是否相等
				System.out.println(map.get(9528));// 根据指定的key找对应的value
				System.out.println(map.hashCode());// 计算map在内存中的哈希码值
				System.out.println(map.isEmpty());// 判断集合是否为空
				System.out.println(map.size());// 返回集合的长度
				System.out.println(map.remove(9527));// 根据key删除元素
				Collection<String> c = map.values();// 把map中的所有值获取到并存入collection中
				System.out.println(c);

				// 迭代map集合 -- set
				// 1、把所有的key放入set中,遍历set   --  两种方式:iterator()  foreach 
				Set<Integer> set = map.keySet();
				
				//foreach可以用在数组遍历时,或者List遍历时或者Set遍历时
				for (Integer in : set) {
					System.out.println("key:"+in);
					String value = map.get(in);
					System.out.println("value:"+value);
				}
				
				Iterator<Integer> it = set.iterator();
				while (it.hasNext()) {
					Integer key = it.next();// 获取set中的元素,也就是每个key

					String value = map.get(key); // 拿着key去map里找对应的value
					System.out.println(key + "===" + value);
				}

				// 2、把key和value封装成Entry对象,并放入set中,遍历set
				Set<Entry<Integer, String>> set2 = map.entrySet();
				Iterator<Entry<Integer, String>> it2 = set2.iterator();
				while (it2.hasNext()) {
					Entry<Integer, String> entry = it2.next();//遍历set得到每个entry对象
					
					Integer key = entry.getKey();//获取每个key
					String value = entry.getValue();//获取每个value
					System.out.println(key+"---"+value);
				}
				
			}
		}

9、HashMap(实现类)

一、概述
在这里插入图片描述
原理

当需要向map中存储元素时,底层会根据hash算法计算对象的存储位置。

如果这个位置上没有存过元素,就直接存放,就相当于直接作为数组的元素存在。

如果这个位置上存过数据,就会形成链表的结构–hash碰撞/冲突

我们尽量要让每个对象拥有自己的哈希值,尽量放在数组结构上。避免链表的形成,因为链表查询效率低。

测试

package cn.tedu.collection;

		import java.util.HashMap;
		import java.util.Map;
		import java.util.Map.Entry;
		import java.util.Set;

		//这个类用来测试Map接口的方法
		public class Test3_HashMap {
			public static void main(String[] args) {
				//1、创建对象
				Map<String,String> map = new HashMap<>();
				
				//2、存数据
				map.put("1", "jack");
				map.put("2", "rose");
				map.put("3", "tom");
				map.put("4", "jerry");
				
				//TODO  3、迭代map集合  --   keySet()     entrySet()
				Set<String> set = map.keySet();//把key都放set里
				for (String key : set) {//遍历set得到每个key
					String value = map.get(key);
					System.out.println( key + " ::::"+value);
				}
				
				Set<Entry<String,String>> set2 = map.entrySet();//把map里的每条记录封装成Entry对象存入set
				for (Entry<String, String> entry : set2) {//遍历set得到每个Entry对象
					System.out.println(  entry.getKey()  +"===="+  entry.getValue() );
				}
				
			}
		}

练习:统计字符串中字符的出现次数

package cn.tedu.collection;

		import java.util.HashMap;
		import java.util.Scanner;

		//统计字符串中字符的出现次数
		public class Test4_Map2 {
			public static void main(String[] args) {
				//1,接收用户输入的字符串
				String input = new Scanner(System.in).nextLine();
				//定义map存数据,数据的格式类似于:a=1,b=2,c=3
				HashMap<Character, Integer> map = new HashMap<>(); 
				//2,遍历字符串,获取每个字符  i < input.length()  下标最大值是字符串长度-1
				for(int i = 0 ; i < input.length()  ; i++) {
					
					//根据下标,获取对应的字符
					char key = input.charAt(i);
					
					//3,统计字符出现过几次--map里的value是多少?
					Integer value = map.get(key);
					if( value == null ) {//如果之前没存过字符,value存的就是默认值null
						map.put(key, 1);//把value的默认值null改成1,说明第一次统计这个字符的次数
					}else {//如果value不是默认值,也就是以前就统计过了
						map.put(key, value+1);//把value的值改成原来的数字+1就行
					}
				}
				System.out.println(map);//打印map里存的数据{a=1,b=2,c=3}
			}
		}

第十一章 多线程

1、进程

一、概念

就是正在运行的程序。也就是代表了程序锁占用的内存区域

二、特点

独立性:进程是系统中独立存在的实体,它可以拥有自己的独立的资源,每一个进程都拥有自己私有的地址空间。在没有经过进程本身允许的情况下,一个用户进程不可以直接访问其他进程的地址空间。

动态性:进程与程序的区别在于,程序只是一个静态的指令集合,而进程是一个正在系统中活动的指令集合。在进程中加入了时间的概念,进程具有自己的生命周期和各种不同的状态,这些概念在程序中都是不具备的。

并发性:多个进程可以在单个处理器上并发执行,多个进程之间不会互相影响

2、进程和线程的区别

进程和线程的区别

一个软件的运行最少需要一个进程支撑,一个进程又可以启动多个线程来执行。

线程是进程的实际单位。也是操作系统可调度的最小单位。

如果一个进程,,只包含一个线程 — 单线程程序

如果一个进程,,包含多个线程 — 多线程程序

2、并发和并行的区别

如果只有一个CPU在干活,大家都去抢占了CPU资源,发生了资源被抢占的现象–并发

假设有多个CPU在干活,每个CPU干一个任务,只不过是多个CPU一起各干各的–并行

3、多线状态

5种:新建状态–可运行状态–运行状态–阻塞状态–终止状态

3、多线程创建:继承Thread

一、概述

这种方式实现多线程很简单,通过自己的类直接extend Thread,并重写run()方法,就可以启动新线程并执行自己定义的run()方法。

二、创建对象

Thread()
分配新的 Thread 对象。

Thread(Runnable target)
分配新的 Thread 对象。

Thread(Runnable target, String name)
分配新的 Thread 对象。

Thread(String name)
分配新的 Thread 对象。

三、常用方法

static Thread currentThread()
返回对当前正在执行的线程对象的引用。

long getId()
返回该线程的标识符。

String getName()
返回该线程的名称。

void run()

void setName(String name)
改变线程名称,使之与参数 name 相同。

static void sleep(long millis)
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),

void start()
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。

void stop()
来终止线程将释放它已经锁定的所有监视器

测试

package cn.tedu.thread;

		//这个类用来测试  多线程编程
		public class Test5_Thread {
			public static void main(String[] args) {
				//3、创建线程对象
				MyThread thread = new MyThread();//线程状态:新建状态
				//4、启动线程 + 去执行run()
				thread.start();//线程状态:可运行状态,等待CPU调度
				
				//5、实现多线程程序:一定是有1个以上的线程对象在执行任务
				MyThread thread2 = new MyThread();
				thread2.start();
				//6、start() 和run() 区别:start()可以实现多线程效果。run()只是当做一个普通的方法调用是一个顺序执行的效果。
				//thread.run();
			
				//7、程序会自动分配线程名称:命名方式类似于:Thread-0  Thread-1。。。
				thread.setName("美队");//修改线程名称
				thread2.setName("钢铁侠");
				
				/*
				 * 多线程的随机性:因为程序是交给CPU调度的,CPU的调度过程我们没法控制。
				 * 11=Thread-1 10=Thread-0 11=Thread-1
				 * 10=Thread-0 11=Thread-1 10=Thread-0 11=Thread-1 10=Thread-0
				 */
			}
		}
		//1、自定义多线程类:extends Thread
		class  MyThread extends Thread{
			//2、把你的业务,重写run()
			@Override
			public void run() {
		//		super.run();//默认使用了父类的run()
				for(int i = 0 ; i < 10 ; i++) {
					System.out.println(i+"="+getName());//线程名称
				}
			}
		}

4、多线程创建2:实现Runnable接口

一、概述

如果自己的类已经extends另一个类,就无法多继承,此时,可以实现一个Runnable接口。

二、常用方法

void run()
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。

测试

package cn.tedu.thread;

		//这个类用来测试  多线程编程2
		public class Test1_Runnable {
			public static void main(String[] args) {
				//4、创建线程对象
				MyRunnable target = new MyRunnable();
				//能不能  把  target和Thread  绑定关系--利用了Thread类的构造方法
				Thread thread = new Thread(target);
				//5、启动线程
				thread.start();
				
				//模拟多线程程序
				Thread thread2 = new Thread(target);
				//5、启动线程
				thread2.start();
				thread.setName("1号线程");
				thread2.setName("2号线程");
			}
		}
		//1、自定义多线程类  implements Runnable
		//2、实现了接口以后的实现类,有两种选择:作为一个抽象类+把所有抽象方法都重写
		class MyRunnable implements Runnable{
			//3、把你自己的业务,都放在重写的run()
			@Override
			public void run() {
				for( int i  = 0 ; i < 10 ; i++ ) {
					//Thread.currentThread()是获取正在执行任务的Thread对象。
					System.out.println(i+"==="+Thread.currentThread().getName());
				}
			}
		}

售票案例

	--需求:设计4个售票窗口,总计售票100张。
	--方案1:继承Thread
		package cn.tedu.thread;

		//这个类用来  测试 多线程售票  方式1
		public class Test2_Tickets {
			public static void main(String[] args) {
				//3、创建线程对象
				MyTicket target = new MyTicket();
				//4、启动线程
				target.start();
		//问题1:我们总共要卖100张票,但是现在卖了400张票,为什么?-- 因为每个对象初始化时都初始化了自己的ticket100张票
				//模拟多线程
				MyTicket target2 = new MyTicket();
				target2.start();
				MyTicket target3 = new MyTicket();
				target3.start();
				MyTicket target4 = new MyTicket();
				target4.start();
			}
		}
		//1、自定义多线程类
		class MyTicket extends Thread {
		//	int tickets = 100 ; //定义变量,记录票数  //成员变量 - 实例变量  ,这个资源会跟着对象存在,new几次就有几份
			//问题1的解决方案:把资源变成共享资源,不跟随对象产生,保证程序中只有这1份资源,只有100张票。
			static int tickets = 100 ; 
			
			//2、所有业务放入重写的run()
			@Override
			public void run() {
				while(true) {//一直卖票
					if( tickets>0 ) {
						try {
							//5、增加延迟性的考察。
							//问题2:程序出现了超卖的现象:0 -1 -2张票。
							//问题3:程序出现了重复卖的现象:一张票卖给多个人。
							Thread.sleep(10);//让程序休眠10ms
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						System.out.println( getName()+"="+tickets-- );
					}else 
						break;//<=0时结束死循环
				}
			}
		}


	--方案2:继承Thread
		package cn.tedu.thread;
		//这个类用来  测试 多线程售票  方式2
		public class Test3_Tickets2 {
			public static void main(String[] args) {
				//3、创建线程对象
				MyTickets2 target = new MyTickets2();
				Thread t1 = new Thread(target);
				//4、启动线程
				t1.start();
				
				//模拟多线程
				Thread t2 = new Thread(target);
				t2.start();
				Thread t3 = new Thread(target);
				t3.start();
				Thread t4 = new Thread(target);
				t4.start();
			}
		}
		//1、自定义多线程类
		class MyTickets2 implements Runnable{
			int tickets  = 100 ; 
			//2、重写run(),把业务放进来
			@Override
			public void run() {
				while(true) {//一直卖100张票
					if( tickets > 0 ) {
						//多线程的延迟访问
						try {
							//问题1:出现了超卖现象:卖出了0  -1  -2张票
							//问题2:出现了重卖现象:同一张票卖给了多个人
							Thread.sleep(10);//睡10ms
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						//Thread.currentThread().getName() 正在执行任务的线程名称
						System.out.println( Thread.currentThread().getName() +"="+ tickets-- );
					}else {
						break;
					}
				}
			}
		}

三、总结

三、总结

1、多线程安全问题是如何出现的?常见情况是由于线程的随机性 + 访问延迟sleep()。

2、以后如何判断程序有没有线程安全问题?在多线程程序中 + 有共享数据 + 多条语句操作 共享数据。

四、多线程编程数据安全隐患的解决方案:同步锁

1、同步和异步的概念:

同步是:同一时刻,只有一个人拿着钥匙在开门,也就是说,共享资源同一时刻只有一个线程在操作, 其他没有钥匙的线程在等待。

异步是:同一时刻,大家一起上。相当于,多个线程一起操作了共享数据。

2、想要解决数据安全隐患:使用关键字synchronized实现同步。是牺牲了效率提高了安全。

3、synchronized可以修饰方法称为同步方法。也可以修饰代码块称为同步代码块。

4、使用同步锁,你需要考虑两件事情: 使用锁的位置 + 使用锁的对象

5、改造代码

package cn.tedu.thread;

		//这个类用来  测试 多线程售票  方式2
		public class Test3_Tickets2 {
			public static void main(String[] args) {
				// 3、创建线程对象
				MyTickets2 target = new MyTickets2();
				Thread t1 = new Thread(target);
				// 4、启动线程
				t1.start();

				// 模拟多线程
				Thread t2 = new Thread(target);
				t2.start();
				Thread t3 = new Thread(target);
				t3.start();
				Thread t4 = new Thread(target);
				t4.start();
			}
		}

		// 1、自定义多线程类
		class MyTickets2 implements Runnable {
			int tickets = 100;
			// Object obj = new Object();
			String s = "abc";

			// 2、重写run(),把业务放进来
			@Override
			// synchronized public void run() {//8、同步方法
			public void run() {
				while (true) {// 一直卖100张票
					// 5、 同步锁的位置:是从问题发生点开始,到结束为止。
					// 6、 同步锁的对象:如果是同步代码块,根本不关心锁对象是谁,只要是同一个对象就可以。
					// synchronized (new Object()) {//每个线程有自己的对象
					// synchronized (obj) {//多个线程使用了同一个对象obj,可以解决问题
					// 7、同步可以修饰方法,如果方法里的代码都有安全隐患,直接修饰成同步方法就可以了。
					synchronized (s) {// 多个线程使用了同一个对象s,也可以解决问题
						if (tickets > 0) {
							// 多线程的延迟访问
							try {
								// 问题1:出现了超卖现象:卖出了0 -1 -2张票
								// 问题2:出现了重卖现象:同一张票卖给了多个人
								Thread.sleep(10);// 睡10ms
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							// Thread.currentThread().getName() 正在执行任务的线程名称
							System.out.println(Thread.currentThread().getName() + "=" + tickets--);
						} else {
							break;
						}
					}
				}
			}
		}

5、单例设计

一、概述

单例模式可以说是大多数开发人员在实际中使用最多的,常见的Spring默认创建的bean就是单例模式的。

单例模式有很多好处,比如可节约系统内存空间,控制资源的使用。

其中单例模式最重要的是确保对象只有一个。

简单来说,保证一个类在内存中的对象就一个。

RunTime就是典型的单例设计

测试

饿汉式
		package cn.tedu.thread;

		//这个类用来测试  单例设计模式:保证整个工程中,只有唯一的实例
		public class Test4_Singleton {
			public static void main(String[] args) {
				//4、调用了MySingleton内部创建好的对象
				MySingleton m1 = MySingleton.getSingle();
				//5、全局真的只要一个对象吗?
				MySingleton m2 = MySingleton.getSingle();
				//==比较引用类型比较的是地址值
				System.out.println(m1 == m2);
			}
		}
		//自定义单例类
		class MySingleton {
			//1、私有化构造方法,目的是不让外界随意new
			private MySingleton() {}
			//2、在类的内部 ,提供创建好的对象
			//static--因为静态只能调静态,所以想要被getSingle()调用,必须也是静态资源
			static private MySingleton single = new MySingleton();
			//3、提供公共的 ,访问方式,把single返回给外界调用位置
			static public MySingleton getSingle(){
				return single ; 
			}
		}
	--!!懒汉式
		//懒汉式:
		//延迟访问(是指没有第一时间创建对象,而是什么时候调用get()什么时候才创建)
		//线程安全隐患(有多条语句 对 共享资源 进行操作)--需要把get()变成同步方法
		class MySingleton2 {
			// 1、私有化构造方法,目的是不让外界随意new
			private MySingleton2() {
			}
			// 2、在类的内部 ,提供创建好的对象
			// static--因为静态只能调静态,所以想要被getSingle()调用,必须也是静态资源
			static private MySingleton2 single; // 懒汉式
			// 3、提供公共的 ,访问方式,把single返回给外界调用位置
			synchronized static public MySingleton2 getSingle() {// 直接把方法同步了,默认使用的锁对象是this
				// synchronized (MySingleton2.class){//如果你要锁的共享资源是静态的,此时,锁对象必须是MySingleton2的字节码对象
				if (single == null) {
					single = new MySingleton2();
				}
				return single;
				// }
			}
		}

6、注解

一、概念

注解有一个标志:@,如:@Override。

二、分类( JDK自带注解、元注解、自定义注解)

jdk提供好的5个:常用的@Override ,标志着该方法是一个重写方法

元注解5个:常用的@Target 和 @Retention

如果这10个不够用还可以自定义注解

元注解
– @Target用来描述注解可以出现的位置是哪里,如:在方法上,类上,属性上…
–值都被维护在ElementType类中。
– @Retention用来描述注解可以存在的生命周期,如:在.java文件中,在.class文件中,runtime时

@Target ElementType.class
描述注解的使用范围:

l ElementType.ANNOTATION_TYPE 应用于注释类型

l ElementType.CONSTRUCTOR 应用于构造函数

l ElementType.FIELD 应用于字段或属性

l ElementType.LOCAL_VARIABLE 应用于局部变量

l ElementType.METHOD 应用于方法级

l ElementType.PACKAGE 应用于包声明

l ElementType.PARAMETER 应用于方法的参数

l ElementType.TYPE 应用于类的元素

@Retention RetentionPolicy.class

定义了该注解被保留的时间长短,某些注解仅出现在源代码中,而被编译器丢弃;

而另一些却被编译在class文件中; 编译在class文件中的注解可能会被虚拟机忽略,而另一些在class被装载时将被读取。

为何要分有没有呢?没有时,反射就拿不到,从而就无法去识别处理。

l SOURCE 在源文件中有效(即源文件保留)

l CLASS 在class文件中有效(即class保留)

l RUNTIME 在运行时有效(即运行时保留)

自定义注解

package cn.tedu.annotation;
		import java.lang.annotation.ElementType;
		import java.lang.annotation.Retention;
		import java.lang.annotation.RetentionPolicy;
		import java.lang.annotation.Target;
		//这个类用来测试  自定义注解
		public class Test1_Annotation {
			public static void main(String[] args) {
			}
		}
		//1,创建自定义注解Test:语法:@interface 注解名
		//2、@Target指定注解的位置--ElementType.TYPE是指可以出现在类上
		//3、@Retention指定注解的生命周期--RetentionPolicy.SOURCE是指在源码中有效
		//@Target(  ElementType.METHOD )   
		@Target(  { ElementType.TYPE   , ElementType.METHOD    }  )   
		@Retention(RetentionPolicy.SOURCE)
		@interface Test {
			//5、给注解添加属性--注解的语法和java略有不同
			String name()  default "" ;
			String value() default "" ;//8、特殊属性,赋值时可以简写
		}
		//4、使用自定义的注解Test
		//6、使用Test注解时,同时给name属性赋值(没有默认值时)
		//@Test(name="hello")
		//7、如果name属性有了默认值,我们使用就可以省略赋值
		//@Test(value="hello")
		@Test("hello") //8.1、如果给value属性赋值,可以简写
		class Hello {
		//	@Test  The annotation @Test is disallowed for this location
			String name ;
			@Test
			public void method() {
				System.out.println(123);
			}
		}

7、反射、暴力反射

一、概述

Reflection(反射) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,也有称作“自省”。反射非常强大,它甚至能直接操作程序的私有属性。我们前面学习都有一个概念,private的只能类内部访问,外部是不行的,但这个规定被反射赤裸裸的打破了。

二、反射Class类对象

Class.forName(“类的全路径”);

类名.class

对象.getClass();

三、常用方法

获得包名、类名

clazz.getPackage().getName()//包名

clazz.getSimpleName()//类名

clazz.getName()//完整类名

!!成员变量定义信息

getFields()//获得所有公开的成员变量,包括继承的变量

getDeclaredFields()//获得本类定义的成员变量,包括私有,不包括继承的变量

getField(变量名)

getDeclaredField(变量名)

!!构造方法定义信息

getConstructor(参数类型列表)//获得公开的构造方法

getConstructors()//获得所有公开的构造方法

getDeclaredConstructors()//获得所有构造方法,包括私有

getDeclaredConstructor(int.class, String.class)

方法定义信息

getMethods()//获得所有可见的方法,包括继承的方法

getMethod(方法名,参数类型列表)

getDeclaredMethods()//获得本类定义的方法,包括私有,不包括继承的方法

getDeclaredMethod(方法名, int.class, String.class)

反射新建实例

c.newInstance();//创建无参构造对象

c.newInstance(6, “abc”);//创建执行有参构造对象

c.getConstructor(int.class, String.class); //执行含参构造,获取构造方法

反射调用成员变量

c.getDeclaredField(变量名); //获取变量

c.setAccessible(true); //使私有成员允许访问

f.set(实例, 值); //为指定实例的变量赋值,静态变量,第一参数给 null

f.get(实例); //访问指定实例的变量的值,静态变量,第一参数给 null

反射调用成员方法

获取方法

Method m = c.getDeclaredMethod(方法名, 参数类型列表);

m.setAccessible(true) ;//使私有方法允许被调用

m.invoke(实例, 参数数据) ;//让指定的实例来执行该方法

反射类中的资源

package cn.tedu.reflection;

		import java.lang.reflect.Constructor;
		import java.lang.reflect.Field;
		import java.lang.reflect.Method;
		import java.util.Arrays;

		import org.junit.Test;
		//这个类用来测试  反射获取学生类里的所有数据
		//Junit单元测试方法: @Test   + void  + 没有参数
		//运行:必须选中方法名,右键,run  as  , junit test...
		public class Test3_Reflection2 {
			//利用反射创建对象
			@Test
			public void showObject() throws Exception {
				//1、获取Class对象
				Class<?> clazz = Student.class;
				//2、利用反射,创建对象
				Object obj = clazz.newInstance();//触发了无参构造
				//cn.tedu.reflection.Student@443b7951
				System.out.println(obj);
				//怎么触发含参构造
				//指定你想要触发 哪个 含参构造   
		//		clazz.getConstructor(String.class);//触发string类型的含参构造
		//		clazz.getConstructor(int.class);//触发int类型的含参构造
				Constructor c = clazz.getConstructor(String.class , int.class);
				Object obj2 = c.newInstance("皮皮霞",20);//给构造方法传参
				//cn.tedu.reflection.Student@14514713
				//Student [name=皮皮霞, age=20]
				System.out.println(obj2);
			}
			
			//获取学生类中的成员变量们
			@Test
			public void showFields() {
				//1、获取Class对象
				Class<?> clazz = Student.class;
				
				//2、获取所有   公共的   的属性们  
				Field[] fs = clazz.getFields() ; 
				
				//3、遍历数组
				for (Field f : fs) {
					//4、获取变量名
					String name = f.getName() ;
					System.out.println(name);
					
					//5、获取变量的类型
					String type = f.getType().getName();
					System.out.println(type);
				}
			}
			
			//获取学生类中的构造方法们
			@Test
			public void showConstructor() {
				// 1、获取Class对象
				Class<?> clazz = Student.class;
				// 2、调用方法
				Constructor<?>[] cs = clazz.getConstructors() ;
				//3、遍历数组
				for(Constructor c : cs) {
					//4、获取方法名
					String name = c.getName();
					System.out.println(name);
					
					//5、获取参数的类型
					Class[] cls = c.getParameterTypes() ;
					System.out.println( Arrays.toString(cls)  );
				}
			}
			
			// 获取学生类中的成员方法们
			@Test
			public void showMethod() {
				// 1、获取Class对象
				Class<?> clazz = Student.class;
				// 2、调用方法
				Method[] ms = clazz.getMethods();
				// 3、遍历数组
				for (Method m : ms) {
					// 4、获取方法名
					String name = m.getName();
					System.out.println(name);
					//5、获取方法有没有参数
					Class<?>[] cls = m.getParameterTypes();
					System.out.println(  Arrays.toString(cls)  );
				}
			}
			
			@Test
			public void showClass() throws ClassNotFoundException {
				// 反射Class对象
				Class<?> clazz = Class.forName("cn.tedu.reflection.Student");
				Class<?> clazz2 = Student.class;
				Student s = new Student();
				Class<?> clazz3 = s.getClass();

				System.out.println(clazz);
				System.out.println(clazz2);
				System.out.println(clazz3);
			}

		}

暴力反射 概念:指可以将程序中的私有的属性或者方法通过反射技术,暴力的获取到资源

--1、创建Person类
		package cn.tedu.reflection;

		//这个类用来 测试暴力反射
		public class Person {
			
			private String name = "张三";
			private int age = 20 ;
			
			private void show() {
				System.out.println("show()...");
			}
			public void test(int a) {
				System.out.println("test()..."+a);
			}
			
		}

	
	--2、暴力反射
		package cn.tedu.reflection;

		import java.lang.reflect.Method;
		import java.util.Arrays;

		import org.junit.Test;

		//这个类用来 测试暴力反射Person 
		public class Test4_ReflectPrivate {
			//暴力反射成员方法
			@Test
			public void showMethod() throws Exception {
				//1、获取Class对象
				Class clazz = Class.forName("cn.tedu.reflection.Person");
				
				//2、获取所有的方法们
		//		clazz.getMethods();  //反射  公共的  资源
				
		//3、暴力反射  --  所有   方法们  ---  getDeclaredMethods()--可以获取公共的或者私有的方法
				Method[] ms = clazz.getDeclaredMethods(); 
				for (Method m : ms) {
					String name = m.getName();
					System.out.println(name);
					
					Class<?>[] cls = m.getParameterTypes();
					System.out.println(  Arrays.toString(cls) );
					
				}
				
				//4、暴力反射    --   获取    单个   方法
				//getDeclaredMethod(m,n)-m是想要执行的方法名 -n是方法需要的参数类型
				Method method = clazz.getDeclaredMethod("show", null);
				
				//5、如何执行
				//--invoke(m,n)-m是想让哪个对象执行方法-n是方法需要的参数
				
				//!!设置私有可见
				method.setAccessible(true);
				Object obj = clazz.newInstance() ;
				method.invoke(obj, null) ;
			}
			
			
			//TODO 暴力反射成员变量
			
			
			
		}

练习2

反射成员变量和方法
		package cn.tedu.reflection;

		import java.lang.reflect.Field;
		import java.lang.reflect.Method;
		import java.util.Arrays;

		import org.junit.Test;

		//这个类用来 测试暴力反射Person 
		public class Test4_ReflectPrivate {
			//暴力反射成员方法
			@Test
			public void showMethod() throws Exception {
				//1、获取Class对象
				Class clazz = Class.forName("cn.tedu.reflection.Person");
				
				//2、获取所有的方法们
		//		clazz.getMethods();  //反射  公共的  资源
				
		//3、暴力反射  --  所有   方法们  ---  getDeclaredMethods()--可以获取公共的或者私有的方法
				Method[] ms = clazz.getDeclaredMethods(); 
				for (Method m : ms) {
					String name = m.getName();
					System.out.println(name);
					
					Class<?>[] cls = m.getParameterTypes();
					System.out.println(  Arrays.toString(cls) );
					
				}
				
				//4、暴力反射    --   获取    单个   方法
				//getDeclaredMethod(m,n)-m是想要执行的方法名 -n是方法需要的参数类型
				Method method = clazz.getDeclaredMethod("test", int.class);
				
				//5、如何执行
				//--invoke(m,n)-m是想让哪个对象执行方法-n是方法需要的参数
				
				//!!设置私有可见
				method.setAccessible(true);
				Object obj = clazz.newInstance() ;
				method.invoke(obj, 5) ;
			}
			
			//暴力反射成员变量
			@Test
			public void showFields() throws Exception {
				//1、获取Class对象
				Class clazz = Person.class;
				//2、暴力获取  变量
				Field[]  fs = clazz.getDeclaredFields();//获取所有
				//获取变量类型
				Field f = clazz.getDeclaredField("name");//获取一个,传入属性名
				String type = f.getType().getName();
				System.out.println(type);
				
				//!!设置私有可见
				f.setAccessible(true);
				Object obj = clazz.newInstance() ;
				
				//设置私有属性的值
				//set(m,n)-m是要设置哪个对象名-n是你要设置的值
				f.set(obj, "皮皮霞");
				
				//获取属性的值
				Object value = f.get(obj);//参数是要获取哪个对象
				System.out.println(value);//属性的值
			}
			
		}

8、内部类

一、概述

如果B类的存在只是为了让A类使用,此时,就可以把B类作为A的内部类

形式:

class A{//外部类
			class B{//内部类:可以看做是外部类的成员
				//变量+方法
			}
		}

二、特点

内部类可以直接访问外部类中的成员,包括私有成员

外部类要访问内部类的成员,必须要建立内部类的对象

位置不同,内部类的名字和作用就不同。

如果是在成员位置(类里方法外)- 成员内部类 – 用!!

如果是在局部位置(方法里)-局部内部类 ---- 不用!!

匿名内部类 – 最常用!!

三、成员内部类:在成员位置
入门案例

定义内部类
			package cn.tedu.innerclass;
			//这个类用来 定义 内部类
			public class InnerClass {
				private int age = 10 ;
				public void save() {
					System.out.println("InnerClass.save()");
			//特点2:外部类想要使用内部类成员--必须创建内部类对象
					Inner in2 = new Inner();
					in2.get();
					System.out.println(in2.name);
				}
				//成员内部类
				class Inner{
					String name = "皮皮霞";
					public void get() {
			//特点1:内部类可以使用  所有  外部类成员
						save();
						System.out.println(age);
						System.out.println("惊雷!");
					}
				}
			}
		--测试内部类
			package cn.tedu.innerclass;

			//这个类用来 测试 内部类
			public class Test1_InnerClass {
				public static void main(String[] args) {
					//1、想办法 使用 内部类的资源 - 创建内部类对象
					//外部类.内部类 变量名=外部类对象.内部类对象
					InnerClass.Inner in = new InnerClass().new Inner();
					in.get();
					System.out.println(in.name);
				}
			}

被private修饰----定义内部类

package cn.tedu.innerclass;
			//这个类用来 定义 内部类
			public class InnerClass {
				private int age = 10 ;
				public void save() {
					System.out.println("InnerClass.save()");
			//特点2:外部类想要使用内部类成员--必须创建内部类对象
					Inner in2 = new Inner();
					in2.get();
					System.out.println(in2.name);
				}
				//成员内部类
				private class Inner{
					String name = "皮皮霞";
					public void get() {
			//特点1:内部类可以使用  所有  外部类成员
			//			save();
						System.out.println(age);
						System.out.println("惊雷!");
					}
				}
			}

测试内部类

package cn.tedu.innerclass;

			//这个类用来 测试 内部类
			public class Test1_InnerClass {
				public static void main(String[] args) {
					//1、想办法 使用 内部类的资源 - 创建内部类对象
					//外部类.内部类 变量名=外部类对象.内部类对象
			//		InnerClass.Inner in = new InnerClass().new Inner();
			//		in.get();
			//		System.out.println(in.name);
					
					//2、当内部类被private修饰后,我们无法直接访问内部类资源
					//需要访问外部类的资源来间接实现访问内部类的资源
					InnerClass in = new InnerClass();
					in.save();
					
				}
			}

被static修饰-----定义内部类

package cn.tedu.innerclass;
			//这个类用来 定义 内部类
			public class InnerClass {
				static private int age = 10 ;
				public void save() {
					System.out.println("InnerClass.save()");
			//特点2:外部类想要使用内部类成员--必须创建内部类对象
					Inner in2 = new Inner();
					in2.get();
					System.out.println(in2.name);
				}
				//成员内部类
				static class Inner{
					static int sum = 30 ;
					String name = "皮皮霞";
					public void get() {
			//特点1:内部类可以使用  所有  外部类成员
			//			save();
						System.out.println(age);
						System.out.println("惊雷!");
					}
				}
			}

		--测试内部类
			package cn.tedu.innerclass;

			//这个类用来 测试 内部类
			public class Test1_InnerClass {
				public static void main(String[] args) {
					//1、想办法 使用 内部类的资源 - 创建内部类对象
					//外部类.内部类 变量名=外部类对象.内部类对象
			//		InnerClass.Inner in = new InnerClass().new Inner();
			//		in.get();
			//		System.out.println(in.name);
					
					//2、当内部类被private修饰后,我们无法直接访问内部类资源
					//需要访问外部类的资源来间接实现访问内部类的资源
					InnerClass in = new InnerClass();
					in.save();
					
					System.out.println();
					
					//3、当内部类被static修饰后,可以直接被类名调用
					//创建内部类对象
			//		InnerClass.Inner in2 =new InnerClass().new Inner();
					InnerClass.Inner in2 =new InnerClass.Inner();
					in2.get();
					System.out.println(in2.name);
				
					//4、静态的内部类里的静态资源
					System.out.println(  InnerClass.Inner.sum  );
					
				}
			}

匿名内部类 – 经常用!!
测试

package cn.tedu.innerclass;
 
		//这个类用来测试 匿名 内部类
		public class Test2_InnerClass2 {
			public static void main(String[] args) {
				new Xin();//匿名对象
				//2、接口可以创建对象吗?--不可以!!  
				//但是, 如果同时使用了匿名对象和匿名内部类是可以直接new的,就相当于创建了接口的实现类
				//匿名的好处是:用起来方便。坏处是:一次只执行一个任务。
				new Inter1() {
					@Override
					public void save() {
						System.out.println("save()");
					}
					@Override
					public void get() {
						System.out.println("get()");
					}
				}.save();//3、触发方法的执行
				//5、抽象类直接 new可以吗?--- 不可以!!
				new AbstractDemo() {
					@Override
					public void sleep() {
						System.out.println("sleep()");
					}
				}.sleep(); //6、触发方法
			}
		}
		//4、定义抽象类
		abstract class AbstractDemo{
			public void eat() {
				System.out.println("eat()...");
			}
			abstract public void sleep()  ; 
		}
		//1、定义接口
		interface Inter1{
			void save();
			void get();
		}
		class Xin{
		}

第十二章 Socket编程/套接字编程/网络编程

1、Socket

一、概述
套接字编程,是一个抽象层
在这里插入图片描述

应用程序可以通过它发送或接收数据,可对其像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信。网络套接字是IP地址与端口与协议的组合。

Socket就是为网络编程提供的一种机制 / 通信的两端都有Socket

网络通信其实就是Socket间的通信 / 数据在两个Socket间通过IO传输

2、服务器端ServerSocket、客户端Socket

一、概述

1、服务器端
– 主要负责:接收客户端发来的连接请求 + 组织数据给客户端做出响应

2、客户端
–主要负责:不断的去连接服务器 + 接收服务器发回来的响应数据
二、创建对象、常用方法

1、服务器端ServerSocket
–创建对象
ServerSocket(int port)
–常用方法
Socket accept()
侦听并接受到此套接字的连接。
void close()
关闭此套接字。

2、客户端Socket
–创建对象
Socket(String host, int port)
创建一个流套接字并将其连接到指定主机上的指定端口号。
–常用方法
void close()
关闭此套接字。

入门案例

-- 需求:服务器端接收客户端发来的hello,并给客户端响应hello
	-- 服务器端
		package cn.tedu.net;
		import java.io.IOException;
		import java.io.InputStream;
		import java.io.OutputStream;
		import java.net.ServerSocket;
		import java.net.Socket;
		//这个类用来   表示  Socket编程的 服务器端
		public class Server {
			public static void main(String[] args) throws IOException {
				//1、创建服务器对象,表示在该端口上,等待客户端的连接请求。
				//参数是端口号:默认0~65535,其中0~1024被系统占用
				ServerSocket server = new ServerSocket(8000) ;
				
				//2、开始接受客户端的请求,并建立了数据传输通道Socket
				Socket socket = server.accept();
				System.out.println("恭喜您,连接成功!!");
				
				//3、读取客户端发来的数据  -- in
				InputStream in = socket.getInputStream();
				//客户端发来5个字节,循环读取5次
				for (int i = 0; i < 5; i++) {
		//			int b = in.read();//不能读到整数,我就要字符
					char c = (char)in.read();
					System.out.print(c);//同行展示
				}
				
				//4、服务器给客户端发送数据--out
				OutputStream out = socket.getOutputStream() ;
				
				//5、开始写出数据
				out.write("world".getBytes());
				out.flush();
				
			}
		}

	-- 客户端
		package cn.tedu.net;
		import java.io.IOException;
		import java.io.InputStream;
		import java.io.OutputStream;
		import java.net.Socket;
		//这个类用来   表示  Socket编程的 客户端
		public class Client {
			public static void main(String[] args) throws IOException {
				//1、创建客户端对象,连接指定的服务器
				//参数是服务器的ip和服务器的端口
				//ip地址如果是访问你这台电脑ip是固定值127.0.0.1   /  localhost
				//ip地址如果是在工作中,就应该写真实的服务器的ip
				Socket socket = new Socket("127.0.0.1" , 8000);
				
				//2、给服务器发送数据 -- out
				OutputStream out = socket.getOutputStream() ;
				
				//3、开始写出数据
				out.write("hello".getBytes());//参数需要的是byte[]
				out.flush();
				
				//4、客户端读取服务器发回来的数据--in
				InputStream in = socket.getInputStream() ;
				
				//5、开始正式读取数据
				for (int i = 0; i < 5; i++) {
					char c = (char)in.read();
					System.out.print(c);
				}
				
			}
		}

	-- 测试
		1、先启动服务器端
		2、在启动客户端
		3、服务器端  或者  客户端 只能启动一次。多次就会抛出端口占用异常:java.net.BindException: Address already in use: JVM_Bind
		4、注意启动顺序,如果反了,客户端无法连接服务器,会抛出异常: java.net.ConnectException: Connection refused: connect

第十三章 补充

1、冒泡排序

是给无序数组排序 – 类似于Arrays.sort()默认从小到大排序
在这里插入图片描述

测试

package cn.tedu.review;
		import java.util.Arrays;
		//这个类用来测试  冒泡排序算法:对一组无序数据排序
		//模拟Arrays.sort()的实现过程
		//1、外循环:控制轮数,如果有n个数据,只需要比较n-1次
		//2、内循环:相邻元素比较   +  交换位置
		//第一轮:相邻元素比较    4次,确定了最大值,可以不参与第二轮比较。
		//第二轮:相邻元素比较    3次,确定了二大,第一 大二大 他们可以不参与第三次比较。
		//第三轮:相邻元素比较    2次,确定了三大,第一大二大三大  他们可以不参与第四次比较。
		//第四轮:相邻元素比较    1次,确定了四大,完成排序。
		public class Test1_BubbleSort {
			public static void main(String[] args) {
				//1、定义  无序 数组
				int[]  a = {  92,34,68,6,56  };
				System.out.println("交换前:"+Arrays.toString(a));
				
				//2、开始排序
				//-1是因为,5个数字只需要比4次。
				for( int i = 0 ; i < a.length  -1  ; i++ ) {
					//-1是因为相邻元素比较时,会获取j+1的情况,不能越界
					//-i 是因为,内循环,每轮都会冒出来一个大的值,不参与比较,所以每轮要少执行1次。
					//当i=0时,第一轮循环开始,内循环j比较了4次。因为 j=0,j< 5-1-0
					//当i=1时,第二轮循环开始,内循环j比较了3次。因为 j=0,j< 5-1-1
					for( int j = 0 ; j < a.length - 1 - i ; j++) {
						//相邻元素比较,判断,
						if(a[ j]  > a[ j+1] )  {//如果前面的数字大
							//交换位置
							int t  =  a[j];
							a[j] = a[j+1] ;
							a[j+1] = t;
						}
					}
				}
				//Arrays.sort(a);工具底层已经完成了排序算法,用的快速排序算法
				System.out.println("交换后:"+Arrays.toString(a));
			}
		}

2、正则表达式regex

规定了一个字符串的正确的规则(正则表达式规定是String类型)

一、String类提供的常用方法

boolean matches(String regex)
告知此字符串是否匹配给定的正则表达式。

String replaceAll(String regex, String replacement)

String[] split(String regex)
根据给定正则表达式的匹配拆分此字符串。

二、语法表

数字: [0-9] \d

字母:[a-z] [A-Z]

组合: [A-Za-z0-9]

次数:?表示出现0次或者1次。*表示任意次。{n}表示出现固定的n次

测试

package cn.tedu.review;

		import java.util.Scanner;

		//这个类用来测试  正则表达式:专门用来约束字符串的正确规则
		public class Test2_Regex {
			public static void main(String[] args) {
				//1、接收用户输入的一串 手机号
				String tel = new Scanner(System.in).nextLine();
				
				//2、约束字符串的正确规则
				String regex = "1[0-9]{10}" ; //匹配手机号码的正则表达式
				
				String regex2 = "[0-9]{17}[0-9Xx]" ;//匹配 身份证号的 正则表达式
				
				//3、判断输入的字符串 是否匹配  正则要求
				//if( tel.matches(regex)  ) {   
				if( tel.matches(regex2)  ) {   
					System.out.println("ok .....");
				}else {
					System.out.println("格式错误,请重新输入!");
				}
				
			}
		}

总结

1、jdk新特性

一、泛型

用来检查数据类型,并在编译期报错。类似于java的语法糖。

二、foreach

提高普通for的执行效率。 语法简洁。 只能用来遍历数组 或者 Collection集合

for( 数据类型 变量名 : 数组|Collection集合 ){循环体;}

三、自动装箱与拆箱

装箱是指把基本类型包装形成包装类型。拆箱是指把包装类型的数据拆回城基本类型。

四、接口的方法

可以包含 static 或者 default 的普通方法

在catch捕获异常时,优化了catch多次的语法:

catch(异常类型1 | 异常类型2 | 异常类型3 |异常类型4 异常名)

五、可变参数
测试

package cn.tedu.review;

		import java.util.Arrays;

		//这个类用来测试  可变参数 ...
		public class Test3 {
			public static void main(String[] args) {
				add(0);
				add(1,2);
				add(1,2,3);
				add(1,2,3,4,5);
				add(1,2,3,4,5,6,7,8);
			}
			//1、可变参数的好处:自适应参数的个数。底层使用数组实现接收参数[I@4e25154f。
			//2、可变参数,必须是参数列表的最后一个
			private static void add(int m , int...k) {
				System.out.println(  Arrays.toString(k) );
				//把可变参数k[]  里的数据求和
				int b = 0 ; //定义变量记录和
				for (int i = 0; i < k.length; i++) {//遍历k[]
					b += k[i];  // k[i]根据下标i获取k数组里的数据
				}
				System.out.println(b);
			}
			
		}

六、自动资源管理:是指优化了IO操作中的释放资源
测试

package cn.tedu.review;

		import java.io.FileInputStream;
		import java.io.FileNotFoundException;
		import java.io.IOException;
		import java.io.InputStream;

		//这个类用来测试  自动资源管理
		public class Test4_Resource {
			public static void main(String[] args) {
				InputStream in = null;//3、为了让finally认识in变量,所以在try  catch finally外声明变量
				try {
					in = new FileInputStream("");
					
				} catch (IOException  e) {
					e.printStackTrace();
				}finally {//1、为了保证资源一定会被释放,所以放在finally中
					try {
						in.close();//2、释放资源时可能会有异常,进行捕获
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				
				//jdk1.7后:释放资源你不用操作,直接放在try后面的 小括号里 就行。
				try (  InputStream input = new FileInputStream("")  ) {
					
		//			input.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
				
			}
		}

2、复习(重点: 数组 + OOP + IO + 集合 )

①数组

可以存放 相同类型的 多个数据。一旦创建长度就不能改变。

①先确定数组的类型(要看数组里存啥数据) 并且 初始化数组(动态+静态)

②每个数据都有唯一的标志是下标,从0开始的。所以适合查询的场景。

for(int i = 0 ; i < a.length ; i++){ sout( a[i] ); }

②OOP

①特征:封装+继承+多态

②override(重写)和overload(重载)

overload重载:发生在一个类的现象,为了外界方便调用。要求:方法名相同,参数列表不同(参数个数不同或者参数的类型不同),与修饰符和返回值无关

override 重写:发生在父子类的现象,为了修改父类的功能。要求: 子类的方法声明必须和父类一样(修饰符>=父类,返回值与父类一致)

测试

package cn.tedu.review;

		//overload重载:发生在一个类的现象,为了外界方便调用。要求:方法名相同,参数列表不同(参数个数不同或者参数的类型不同)
		//override 重写:发生在父子类的现象,为了修改父类的功能。要求: 子类的方法声明必须和父类一样
		public class Test5_OOP {
			public static void main(String[] args) {
				//重载:为了体现程序的灵活性
				add(10);
				add(5,"java");
			}
			public static void add(int a) {
				System.out.println(a*a);
			}
			public static void add(int a,String b) {
				System.out.println(a+b);//+用来拼接字符串
			}
		}
		class Fu{
			public void eat() {
				System.out.println("Fu..eat()");
			}
		}
		class Zi extends Fu{
			@Override//重写父类的功能,修改方法体
			public void eat() {
				System.out.println("Zi...eat()");
			}
		}

③多态的好处

不关心具体的子类类型写出了通用代码 + 统一了调用的标准(父类)

equals(Object obj)

BufferedReader(Reader in)

④抽象类

①抽象层,用来抽取所有子类的共性

②定义抽象类:是一个特殊的类,特殊在类里可以有抽象方法

abstract class Demo {// 3、如果一个类中包含了抽象方法,这个类必须是一个抽象类
			public void show() {
				System.out.println("show()...");
			}

			abstract public void study(); // 1、如果方法不需要提供方法体,就是一个抽象方法
		}

⑤接口

①抽象层,用来抽取所有实现类的共性

②定义接口,是一个特殊的抽象类,因为接口里都是抽象方法,只不过可以简写

interface Demo2{
			public abstract void save();
		//	public abstract void update();
			void update();//2、简写,会自动拼接	public abstract 
		}

⑥接口突破了java单继承的局限性

①接口和接口间可以多继承,接口和实现类之间可以多实现

②定义抽象类:是一个特殊的类,特殊在类里可以有抽象方法

abstract class Demo {// 3、如果一个类中包含了抽象方法,这个类必须是一个抽象类
			public void show() {
				System.out.println("show()...");
			}
			abstract public void study(); // 1、如果方法不需要提供方法体,就是一个抽象方法
		}
		//1、定义接口,是一个特殊的抽象类,因为接口里都是抽象方法,只不过可以简写
		interface Demo2{
			public abstract void save();
		//	public abstract void update();
			void update();//2、简写,会自动拼接	public abstract 
		}
		//接口间多继承的关系
		interface Demo3 extends Demo2 , Serializable{
			//TODO 
		}
		//实现了接口后,需要重写接口里的所有抽象方法,否则就是一个抽象的实现类。
		class DemoImpl  extends Demo implements Demo2 , Demo3{
			@Override
			public void save() {
			}
			@Override
			public void update() {
			}
			@Override
			public void study() {
			}
		}

⑦IO

是指相对于java程序的IO的过程,程序需要读取就是in,程序需要写出就是out

①根据操作数据的类型不同,分为字节流和字符流

②字符流只能操作字符文件,如txt。字节流可以操作任意类型文件。

常用的工具类名      构造方法  
			File 		String pathname
		--字节流工具类名称			构造方法	
		InputStream				File file
		FileInputStream			String pathname
		BufferedInputStream		InputStream in
		OutputStream			File file
		FileOutputStream		String pathname
		BufferedOutputStream	OutputStream in
		创建对象的代码:
		InputStream in  = new FileInputStream(pathname);
		InputStream in  = new BufferedInputStream( new FileInputStream(pathname) ) ;
		OutputStream out  = new FileOutputStream(pathname);
		OutputStream out  = new BufferedOutputStream( new FileOutputStream(pathname) ) ;
		--字符流工具类名称			构造方法	
		Reader					File file
		FileReader				String pathname
		BufferedReader			Reader in
		Writer					File file
		FileWriter				String pathname
		BufferedWriter			Writer in
		创建对象的代码:
		Reader in = new FileReader(pathname);
		Reader in = new BufferedReader (  new FileReader(pathname)  );
		Writer out = new FileWriter(pathname);
		Writer in = new BufferedWriter (  new FileWriter(pathname)  );
	--4、常用方法
		read():如果使用字节流读,就是一个字节一个字节去读取。如果使用字符流读,就是一个字符一个字符去读取。
		read(byte[] bs):如果使用字节流读,就是一个字节数组一个字节数组去读取。
		read(char[] cs):如果使用字符流读,就是一个字符数组一个字符数组去读取。
		write():如果使用字节流写,就是一个字节一个字节去写出。如果使用字符流读,就是一个字符一个字符去写出。
		write(byte[] bs):如果使用字节流写,就是一个字节数组一个字节数组去写出。
		write(char[] cs):如果使用字符流写,就是一个字符数组一个字符数组去写出。
		close():释放资源

⑧八、集合

–方法都是Collection接口继承来的
–1、List Set Map 各自的特点总结好
–ArrayList LinkedList
–HashSet / HashMap 原理:hash算法+node[]+hash碰撞时就形成了链表
–1、集合和数组的区别
–2、ArrayList的LinkedList区别
–3、HashMap 原理

  • 0
    点赞
  • 0
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值