JavaSE学习笔记

JavaSE

第一章 JavaSE基础

1.1、十进制与二进制的相互转换

  • 十进制转二进制:

​ 除2 以15为例
​ 2/15 余数
​ 2/7 1
​ 2/3 1
​ 2/1 1
​ 0 1 从下往上读为:1 1 1 1

  • 二进制转十进制:乘以二的幂指数 以1 1 1 1为例
    1 1 1 1 二进制为从右向左读

​ x x x x

​ 2^3 2^2 2^1 2^0


​ 8 + 4 + 2 + 1 = 15

  • 位(bit):一个数字0或1,代表一位
  • 字节(Byte):每逢8位是一个字节,数据存储单元最小的单位,只有整数,没有0.几
  • 1 Byte=8 bit

1.2、Java各工具关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-32HIVq8d-1588690352150)(JavaSE.assets/Java工具关系.png)]

注意:添加注释或中文后需用指定编码编译:javac -encoding “utf-8” +文件名.java

1.3、关键字

关键字特点:

  1. 完全小写的英文字母

  2. 在增强版的记事本中(如notepad++)有特殊颜色

1.4、标识符

  1. 标识符是指在程序中,我们自己定义内容,比如类名字、方法的名字和变量的名字等等,都是标识符。
    HelloWorld案例中,出现的标识符有类名字HelloWorld
  2. 命名规则(硬性要求,若不遵守必会报错)
    • 标识符可以包含【英文26个字母(区分大小写)】【数字0-9】【$(美元符号)】【_(下划线)】
    • 标识符不能以数字开头。
    • 标识符不能是关键字
  3. 命名规范(软性建议)
    • 类名规范:首字母大写,后面每个单词首字母大写(驼峰式)
    • 变量名规范:首字母小写,后面每个单词首字母大写(小驼峰式)
    • 方法名规范:同变量名

1.5、常量

  1. 常量是指在程序运行期间固定不变的量(练习文件Demo01Const.java)
  2. 常量的分类:
    • 字符串常量:凡是用双引号引起来的部分,叫做字符串常量。例如:“abc”,“Hello”,“123”
    • 整数常量:直接写上的数字,没有小数点,如:100,200,0,250
    • 浮点数常量,直接写上的数字,有小数点,如:2.5,-3.14,0.0
    • 字符常量:凡是用单引号引起来的单个字符,叫做字符常量,如:‘A’,‘B’,‘9’,‘中’
    • 布尔常量:只有两种取值:true,false
    • 空常量:null,代表没有任何数据

Demo01Const.java

public class Demo01Const {
	public static void main(String[] args) {
		//字符串常量
		System.out.println("ABC");
		System.out.println("");//字符串两个双引号中间的内容为空
		System.out.println("XYZ");
		
		//整数常量
		System.out.println(30);
		System.out.println(-500);
		
		//浮点数常量(小数)
		System.out.println(3.14);
		System.out.println(-2.5);
		
		//字符常量
		System.out.println('A');
		System.out.println('6');
		System.out.println(' ');//两个单引号中间必须有且仅有一个字符,没有不行/有俩也不行
		
		//布尔常量
		System.out.println(true);
		System.out.println(false);
		
		//空常量,空常量不能直接用来打印输出。
		System.out.println(null);
	}
}

第二章 数据类型转换

2.1、数据类型

注意事项:

  1. 字符串不是基本类型,而是引用类型
  2. 浮点型可能只是一个近似值,并非精确的值
  3. 数据范围与字节数不一定相关,例如float数据范围比long更广泛,但是float是4字节,long是8字节
  4. 浮点数当中默认类型是double,如果一定要使用float类型,需要加一个后缀F
  5. 如果是整数,默认为int类型,如果一定要使用long类型,需要加上一个后缀L,推荐是用大写字母后缀/System.out.println(100L);/

2.1.1、基本数据类型(四类八种)

数据类型 关键字 内存占用
整数型 byte(字节型) 1个字节 -128~127
short (短整型) 2个字节 -32768~32767
int(短整型)(默认) 4个字节 -2的32次方~2的32次方-1
long(长整型) 8个字节 -2的63次方~2的63次方-1
浮点型 float(单精度) 4个字节 1.4013E-45~3.4028E+38(E表示为乘以10的+38/-45次方)(科学计数法)
double(双精度)(默认/更为精确) 8个字节 4.9E-324~1.7977E+308
字符型 char(字符型) 2个字节 0~65535
布尔型 boolean(布尔类型) 1个字节 true,false

2.1.2、引用数据类型(后面学)

字符串,数组,类,接口,lambda

2.2、变量

程序运行期间,内容可以发生改变的量(两种格式)(练习文件Demo02Variable.java)

创建一个变量并且使用的格式:

  1. 数据类型 变量名称; //创建了一个变量
    变量名称 = 数据值;//=代表赋值,将右边的数据值赋值交给左边的变量
  2. 数据类型 变量名称 = 数据值;// 在创建一个变量的同时,立刻放入指定的数据值(一步到位,合二为一)
  3. 注意事项:
    1. 如果创建多个变量,那么变量之间的名称不可以重复
    2. 使用float/long类型,需要加一个后缀F/L
    3. 使用byte/short类型的变量,右侧数值的范围不能超过左侧数据类型的取值范围
    4. 没有进行赋值的变量,不能直接使用;一定要赋值之后,才能使用
    5. 变量使用不能超过作用域的范围(程序执行是从上至下的,在创建变量之前不能使用变量)
      【作用域】:从定义变量的一行开始,一直到直接所属的大括号{}结束为止
    6. 可以通过一个语句来创建多个变量,但是一般情况不推荐这么写

Demo02Variable.java

//变量;程序运行期间,内容可以发生改变的量(两种格式)(练习文件Demo02Const.java)
	//创建一个变量并且使用的格式:
	//1.数据类型 变量名称; //创建了一个变量
	  //变量名称 = 数据值;//=代表赋值,将右边的数据值赋值交给左边的变量
	//2.数据类型 变量名称 = 数据值;// 在创建一个变量的同时,立刻放入指定的数据值(一步到位,合二为一)
public class Demo02Variable{
	public static void main(String[] args){		
		int num1;		//创建了一个变量,格式;数据类型 变量名称;
		num1 = 10;		//相变量当中存入一个数据;格式:变量名称 = 数据值;
		System.out.println(num1);		//打印输出变量名称的时候,显示出来的是变量的内容
		
		//改变变量中本来的数字,变成新的数字
		num1 = 20;
		System.out.println(num1);
		
		//使用一步到位的格式定义变量
		//格式:数据类型 变量名称 = 数据值;
		int num2 = 25;
		System.out.println(num2);
		
		num2 = 35;
		System.out.println(num2);
		System.out.println("<========华丽的分割线========>");
		
		byte num3 = 30; //注意;右侧数值的范围不能超过左侧数据类型的取值范围
		//byte num3 = 400; //右侧超出了byte数据范围,报错!
		System.out.println(num3);
		
		short num5 = 50;
		System.out.println(num5);
		
		long num6 = 3000000000L; //注意!使用long类型,需要加上一个后缀L
		System.out.println(num6);
		
		float num7 = 2.5F; //注意!使用float类型,需要加一个后缀F
		System.out.println(num7);
		
		double num8 = 1.2;
		System.out.println(num8);
		
		char zifu1 = 'A';
		System.out.println(zifu1);
		
		zifu1 = '中';
		System.out.println(zifu1);
		
		boolean var1 = true;
		System.out.println(var1);
		
		var1 = false;
		System.out.println(var1);
		
		//将一个变量的数据内容,赋值交给另一个变量
		//右侧的变量名称var1已经存在,里面装的是false布尔值
		//将右侧变量里面的false值,向左交给var2变量进行存储
		boolean var2 = var1;
		System.out.println(var2);
	}
}

2.3、数据类型

当数据类型不一样是,将会发生数据类型转换

2.3.1、自动类型转换

  • 自动类型转换(隐式)(练习文件Demo01DataType.java)
  • 特点:代码不需要进行特殊处理,自动完成
  • 规则:数据范围从小到大(与字节数不一定相关,与取值范围有关)
  • int–>long,符合了数据范围从小到大的要求,发生了自动转换

Demo01DataType.java

public class Demo01DataType{
	public static void main(String[] args){
			System.out.println(1024); //这就是一个整数,默认是int类型
			System.out.println(3.14); //这就是一个浮点数,默认是double类型
			
			//左边是long类型,右边是默认的int类型,左右不一样
			//一个等号代表赋值,将右侧的int常量,交给左侧的long变量进行存储
			//int-->long,符合;了数据范围从小到大的要求
			//这一行代码发生了自动类型转换
			long num1 = 100;
			System.out.println(num1);
			
			//左边是double类型,右边是float类型,左右不一样
			//一个等号代表赋值,将右侧的float常量,交给左侧的double变量进行存储
			//float-->double,符合;了数据范围从小到大的要求
			//这一行代码发生了自动类型转换
			double num2 = 2.5F;
			System.out.println(num2);
			
			//左边是float类型,右边是long类型,左右不一样
			//一个等号代表赋值,将右侧的long常量,交给左侧的float变量进行存储
			//long-->float,符合;了数据范围从小到大的要求
			//这一行代码发生了自动类型转换
			float num3 = 30L;
			System.out.println(num3);
	}
}

2.3.2、强制类型转换

  • 强制类型转换(显示)(练习文件Demo02DataType.java)
  • 特点:代码需要进行特殊格式处理,不能自动完成
  • 格式:范围小的类型 范围小的变量名 = (范围小的类型)原本范围大的数据;
  • 注意事项:
    • 强制类型转换一般不推荐使用,因为有可能发生精度损失,数据溢出
    • byte/short/char这三种类型都可以发生数学运算,例如加法“+”
    • byte/short/char这三种类型在运算的时候,都会被首先提升成为int类型,然后再计算
    • 计算机的底层会用一个数字(二进制)来代表字符A,就是65【65~90为26个大写英文字母(A-Z);小写字母与大写字母相差24;48~57为数字(0-9)】
    • 一旦char类型进行了数学运算,那么字符就会按照一定的规则翻译成为一个数字
    • Boolean(布尔类型)不能发生数据类型转换

Demo02DataType.java

public class Demo02DataType{
	public static void main(String[] args){
		int num = (int)100L;
		System.out.println(num);
		
		//long强制转换成为int类型
		int num2 = (int)6000000000L;
		System.out.println(num2); //1705032704
		
		//double强制转换为int类型
		int num3 = (int) 3.99;
		System.out.println(num3); //输出为3,这并不是四舍五入,所有的小数位都会被舍弃掉
		
		char zifu1 = 'A'; 
		System.out.println(zifu1 + 1); //输出为66,也就是大写字母被当作65进行处理
		//计算机的底层会用一个数字(二进制)来代表字符A,就是65【65~90为26个大写英文字母(A-Z)】
		//一旦char类型进行了数学运算,那么字符就会按照一定的规则翻译成为一个数字
		
		byte num4 = 40; //注意:右侧的数值大小不能超过左侧的类型范围
		byte num5 = 50;
		//byte + byte --> int+int --> int
		int result1 = num4 + num5;
		System.out.println(result1); //输出为90
		
		short num6 = 60;
		//byte + short --> int + int --> int
		//int强制转换为short;注意必须保证逻辑上真实大小本来就没有超过short范围,否则会发生数据溢出
		short result2 = (short)(num4 + num6);
		System.out.println(result2); //100
	}
}

2.4、数字和字符对照表

数字和字符对照表(编码表)(练习文件Demo03DataTypeChar.java):

  • ASCII码表:American Standard Code for Information Interchange,美国标准信息交换代码(小表)
  • Unicode码表:万国码,也是数字和符号的对照关系,开头0~127部分和ASCII完全一样,但是从128开始包含更多字符
    48 - ‘0’
    65 - ‘A’
    97 - ‘a’

Demo03DataTypeChar.java

/*
数字和字符对照表(编码表):
ASCII码表:American Standard Code for Information Interchange,美国标准信息交换代码(小表)
Unicode码表:万国码,也是数字和符号的对照关系,开头0~127部分和ASCII完全一样,但是从128开始包含更多字符

48 - ‘0’
65 - ‘A'
97 - ‘a’
*/
public class Demo03DataTypeChar{
	public static void main(String[] args){
	char zifu1 = '1';
	System.out.println(zifu1 + 0); //输出为49
	
	char zifu2 = 'A'; //其实底层保存的是65数字
	
	char zifu3 = 'C';
	//左侧是int类型,右边是插入类型
	//char-->int,是从小到大
	//发生自动类型转换
	int num = zifu3;
	System.out.println(zifu1 + 0); //输出为99
	
	char zifu4 = '中';
	System.out.println(zifu5 + 0); //输出为20013
	}
}

第三章 运算符

3.1、运算符

运算符(练习文件 Demo04Operator.java):

  • 运算符:进行特定操作的符号,如:+、
  • 表达式:用运算符连起来的式子叫做表达式,如:20+5,a+boolean(布尔类型)
  • 四则运算:

​ 加:+
​ 减:-
​ 乘:*
​ 除:/
​ 取模(取余数):%

  • 首先计算得到表达式的结果,然后再打印输出这个结果

  • 对于一个整数的表达式来说,除法用的是整除,整数除以整数,结果仍是整数,只看商,不看余数

  • 注意事项:1.一旦运算当中有不同类型的数据,那么结果将会是数据类型范围大的那种

Demo04Operator.java

public class Demo04Operator{
	public static void main(String[] args){
		//两个常量之间可以进行数学运算
		System.out.println(20 + 30);
		
		int a = 20;
		int b = 30;
		System.out.println(a - b); //输出为-10
		
		//变量和常量之间可以混合使用
		System.out.println(a * 10); //输出为200
		
		int x = 10;
		int y = 3;
		
		int result1 = x / y;
		System.out.println(result1); //输出为3
		
		int result2 = x % y;
		System.out.println(result2); //余数,模,1
		
		//int + double-->double+double-->double
		double result3 = x + 2.5;
		System.out.println(result3); //输出为12.5
	}
}	

3.2、“ + ”的三种常见的用法

四则运算当中的加号“+”常见的三种用法(练习文件Deme05Plus):

  1. 对于数值来说,那就是加法
  2. 对于字符char类型来说,在计算之前char会被提升成为int,然后再计算
    char类型字符,和int类型数字,之间的对照关系:ASCII、Unicode
  3. 对于字符串String(首字母大写,并不是关键字)来说,加号代表字符串连接操作
    任何数据类型和字符串类型进行连接的时候,结果都会变为字符串
    小括号中的东西都会最先执行

Demo05Plus

public class Demo05Plus{
	public static void main(String[] args){
		//字符串类型的变量基本使用
		//数据类型 变量名称 = 数据值;
		String str1 = "Hello";
		System.out.println(str1); //输出为Hello
		
		System.out.println("Hello" + "World"); //输出为HelloWorld

		String str2 = "Java";
		//String + int --> String
		System.out.println(str2 + 20); //输出为Java20
		
		//优先级问题
		//String + int + int --> String + int --> String
		System.out.println(str2 + 20 + 30); //输出为Java2030

		System.out.println(str2 + (20 + 30)); //输出为Java50
	}
}

3.3、自增自减运算符

自增自减运算符(练习文件Demo06Operator.java):

  • 自增运算符:++
  • 自减运算符:–
  • 基本含义:让一个变量涨一个数字1,或者让一个变量降一个数字1
  • 使用格式,写在变量名称之前,或者写在变量名称之后,例如:++num;num++
  • 使用方式(练习文件Demo06Operator.java)
    • 1.单独使用,不和其他任何操作混合,自己独立成为一个步骤
    • 2.混合使用,和其他操作混合,例如与赋值混合,或者与打印操作混合,等
  • 使用区别:
    • 1.单独使用的时候前++与后++没有任何区别
    • 2.在混合使用的时候,有重大区别:
      • A:如果是前++,那么变量立刻马上+1.然后拿着结果进行使用。【先加后用】
      • B: 如果是后++,那么首先使用变量本来的数值,然后再让变量+1。【先用后加】
  • 注意事项:只有变量才能使用自增、自减运算符,常量不可发生改变,所以不能用。

Demo06Operator.java

public class Demo06Operator{
	public static void main(String[] args){
	int num1 = 10;
	System.out.println(num1); //输出为10
	++num1; //单独使用,前++
	System.out.println(num1); //输出为11
	num1++; //单独使用,后++
	System.out.println(num1); //输出为12
	System.out.println("----------------华丽的分割线----------------");
	
	//与打印操作混合的时候
	int num2 = 20; 
	System.out.println(++num2); //混合使用,先++,变量立刻马上变成21,输出为21
	System.out.println(num2); //输出为21
	System.out.println("----------------华丽的分割线----------------");

	int num3 = 30;
	//混合使用,后++,首先使用变量本来的30,然后再让变量+1得到31
	System.out.println(num3++); //输出为30
	System.out.println(num3); //输出为31
	System.out.println("----------------华丽的分割线----------------");
	
	int num4 = 40;
	//和赋值操作混合
	int result1 = --num4; //混合使用,前++,变量立刻马上-1变成39,然后将结果39交给result1变量
	System.out.println(result1); //39
	System.out.println(num4); //39
	System.out.println("----------------华丽的分割线----------------");
	
	int num5 = 50;
	//混合使用,后--,首先把本来的数字50交给result2,然后我自己再-1变成49
	int result2 = num--;
	System.out.println(result2); //50
	System.out.println(num5); //49
	System.out.println("----------------华丽的分割线----------------");
	
	/*过于复杂不推荐使用,代码应以简洁明了为先
	int x = 10;
	int y = 20;
	//11 + 20 = 31
	int result3 = ++x + y--;
	System.out.println(result3); //31
	System.out.println(x); //11
	System.out.println(y); //19
	*/
	}
}

3.4、赋值运算符

赋值运算符分为以下几种

3.4.1、基本赋值运算符

  • 基本赋值运算符:就是一个等号“=”,代表将右侧的数据交给左侧的变量。int a = 30

3.4.2、复合赋值运算符

  • 复合赋值运算符(练习文件Demo07Operator.java):
+= a += 3 相当于 a = a + 3
-= b -= 4 相当于 b = b - 4
*= c *= 5 相当于 c = c * 5
/= d /= 6 相当于 d = d / 6
%= e %= 7 相当于 e = e % 7
  • 注意事项:
  1. 只有变量才能使用赋值运算符,常量不能进行赋值,不能写在赋值运算符的左边
  2. 复合赋值运算符其中隐含了一个强制类型转换

Demo07Operator.java

public class Demo07Operator{
	public static void main(String[] args){
	int a = 10;
	a += 5; //按照公式进行翻译:a = a + 5	a = 10 + 5	a = 15	a本来是10,现在重新赋值得到15
	System.out.println(a); //输出为15
	
	int x = 10;
	x %= 3; //x = x % 3		x = 10 % 3		x = 1		x本来是10,重新赋值为1			
	System.out.println(x); //输出为1
	
	byte num = 30;
	num += 5; //num = num + 5	num = byte + int	num = int + int		num = int	num = (byte)int	
	System.out.println(num); // 输出为35
	}
}

3.4.3、比较运算符

  • 比较运算符(练习文件Demo08Operator):
== 比较符号两边数据是否相等,相等结果是true
< 比较符号左边的数据是否小于右边的数据,如果小于结果是true
> 比较符号左边的数据是否大于右边的数据,如果大于结果是true
<= 比较符号左边的数据是否小于或者等于右边的数据,如果小于结果是true
>= 比较符号左边的数据是否大于或者等于右边的数据,如果大于结果是true
!= 不等于符号,如果符号两边的数据不相等,结果是true
  • 注意事项:
    1. 比较运算符的结果一定是一个boolean值,成立就是true,不成立就是false
    2. 如果进行多次判断,不能连这些。如数学当中的写法:1 < x < 3,程序当中不允许这种写法

Demo08Operator

public class Demo08Operator{
	public static void main(String[] args){
		System.out.println( 10 > 5 ); //true
		int num1 = 10;
		int num2 = 12;
		System.out.println( num1 < num2 ); //true
		System.out.println( num2 >= 100 ); //false
		System.out.println( num1 <= 12 ); //true
		System.out.println( num1 <= 100 ); //true
		
		System.out.println( 10 == 10 ); //true
		System.out.println( 20 != 25 ); //true
		System.out.println( 20 != 20 ); //false
	}
}

3.4.4、逻辑运算符

  • 逻辑运算符(练习文件Demo09Logic):
与(并且) && 全都是true,才是true,否则就是false
或(或者) || 至少一个是true,就是true,全都是false,才是false
非(取反) 本来是true,变成false,本来是false,变成true
  • 与“&&”、或“||”,具有短路效果;如果根据左边已经可以判断得到最终结果,那么右边的代码将不再执行,从而节省一定的性能

  • 注意事项:

    • 逻辑运算符只能用于boolean值
    • 与、或需要左右各自有一个boolean值,但是取反只要有唯一的一个boolean值即可
    • 与、或两种运算符,如果有多个条件,可以连续写
      • 两个条件:条件A && 条件B
      • 多个条件:条件A && 条件B && 条件C

Demo09Logic

public class Demo09Logic{
	public static void main(String[] args){
	System.out.println(true && false); //false
	System.out.println(true && true); //true
	System.out.println(3 < 4 && 10 > 5); //true
	
	System.out.println(true || false); //true
	System.out.println(true || true); //true
	System.out.println(false || false); //false
	
	System.out.println(true); //true
	System.out.println(!true); //false
	
	int a = 10;
	System.out.println(3 > 4 && ++a < 100); //false,3>4已为false,则不执行++a
	System.out.println(a); //10
	
	int b = 20;
	System.out.println(3 < 4 || ++b < 100); //true,3<4已为true,则不执行++b
	System.out.println(b); //20
	}
}

3.4.5、三元运算符

  • 三元运算符(练习文件Demo10Operator):

    • 一元运算符:只需要一个数据就可以进行操作的运算符,如:取反!;自增++;自减–
    • 二元运算符:需要两个数据才可以进行操作的运算符,如:加法+;赋值=
    • 三元运算符:需要三个数据才可以进行操作的运算符
    • 格式:数据类型 变量名称 = 条件判断 ? 表达式A :表达式B;
    • 流程:首先判断条件是否成立:
      • 如果成立为true,那么将表达式A的值赋值给左侧的变量;
      • 如果不成立为false,那么将表达式B的值赋值给左侧的变量;
      • 二者选其一
  • 注意事项:

    1. 必须同时保证表达式A和表达式B都符合左侧数据类型的要求
    2. 三元运算符的结果必须被使用

Demo10Operator

public class Demo10Operator{
	public static void main(String[] args){
	int a = 10;
	int b = 20;
	
	//数据类型 变量名称 = 条件判断 ? 表达式A :表达式B;
	//判断a > b是否成立,如果成立将a的值赋值给max;如果不成立将b的值赋值给max。二者选其一
	int max = a > b ? a : b; //最大的变量
	System.out.println("最大值: " +max); //输出为20
	
	//int result = 3 > 4 ? 2.5 : 10; 错误写法!
	
	System.out.println(a > b ? a : b); //正确写法!
	
	
	}
}

第四章 方法入门

4.1、方法

  • 方法(练习文件Demo11Method):

  • 概念:就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能,当我们需要这个功能的时候,就可以去调用,这样即实现了代码的复用性,也解决了代码沉余的现象。

  • 定义一个方法的格式:
    public static void 方法名称(){
    方法体
    }

  • 方法体名称的命名规则和变量一样,使用小驼峰

  • 方法体:也就是大括号当中可以包含任意条语句

  • 注意事项:

    • 方法定义先后顺序无所谓
    • 方法的定义不能产生嵌套包含关系
    • 方法定义好之后,不会执行的,如果要想执行,一定要进行方法的【调用】
  • 如何调用方法,格式:

    ​ 数据类型
    ​ 方法名称();

Demo11Method

/*	定义一个方法的格式:
		public static void 方法名称(){
			方法体
		}
		方法体名称的命名规则和变量一样,使用小驼峰
		方法体:也就是大括号当中可以包含任意条语句
*/		
public class Demo11Method{
	public static void main(String[] args){	
		farmer(); //调用农民的方法
		seller(); //调用小商贩的方法
		cook(); //调用厨子的方法
		me(); //调用我的方法
	}
	//小商贩
	public static void seller(){
		System.out.println("运输到农贸市场");	
		System.out.println("抬高价格");
		System.out.println("吆喝");	
		System.out.println("卖给厨子");	
	}
	
	//厨子
	public static void cook(){
		System.out.println("洗菜");
		System.out.println("切菜");	
		System.out.println("炒菜");
		System.out.println("装盘");
	}
	
	//我
	public static void me(){
		System.out.println("吃");	
	}

	//农民	
	public static void farmer(){
		System.out.println("播种");		
		System.out.println("浇水");	
		System.out.println("施肥");	
		System.out.println("除虫");	
		System.out.println("收割");
		System.out.println("卖给小商贩");	
	}
}

4.2、编译器

编译器的两点优化:

  • 在给变量进行赋值的时候,如果右侧的表达式当中全都是常量,没有任何变量,那么编译器javac将会直接将若干个常量表达式计算得到结果。
  • short result = 5 + 8;//等号右边全是常量,没有任何变量参与运算
    编译之后,得到的.class字节码文件当中相当于【直接就是】:
    short result = 13;
    右侧的常量结果数值,没有超过左侧范围,所以正确
    这成为“编译器的常量优化”
  • 注意:一旦表达式当中有变量参与,那么就不能进行这种优化了。如:short result = 5 + a + 8;

4.3、包机制

  • 为了更好地组织类,Java提供了包机制,用于区别类名的命名空间

  • 包语句的语法格式为:

    package pk1[. pkg2[. pkg3…]];

  • 一般利用公司域名的倒置作为包名:com.zhang.xxx/com.wang.xxx

  • 为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用“import”语句可完成次功能

    import package1[.package2…].(classname|*);

4.4、JavaDoc

注:此节开始所有练习在IDEA进行,文件位置(D:\code\JavaSE\基础语法)

  • JavaDoc命令是用来生成自己API文档的

  • JDK8帮助文档https://docs.oracle.com/javase/8/docs/api/

  • 参数信息

    • @author 作者名
    • @version 版本号
    • @since 指明需要最早使用的jdk版本
    • @param 参数名
    • @return 返回值情况
    • @throws 异常抛出情况
  • 可以通过命令行生成JavaDoc文档 【javadoc -encoding UTF-8 -charset UTF-8 Doc.java】

  • 也可以使用IDEA生成JavaDoc文档:

    • 先看一段样例代码:
//: POI/ExportConfig
/** Excel导出项配置
 * @author Mr zhang
 * @version 1.0
 * @since 1.8
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD })
public @interface ExportConfig {

	/**
	 * @return 表头显示名(如:id字段显示为"编号") 默认为字段名
	 */
	String value() default "field";

	/**
	 * @return 单元格宽度 默认-1(自动计算列宽)
	 */
	short width() default -1;

	/**
	 * 将单元格值进行转换后再导出:
* 目前支持以下几种场景:
* 1. 固定的数值转换为字符串值(如:1代表男,2代表女)
* 表达式: "s:1=男,2=女"
* * 2. 数值对应的值需要查询数据库才能进行映射(实现com.haohuo.util.poi.convert.ExportConvert接口)
* * @return 默认不启用 */ String convert() default ""; /** * @return 当前单元格的字体颜色 (默认 HSSFColor.BLACK.index) */ short color() default HSSFColor.BLACK.index; /** * 将单元格的值替换为当前配置的值:
* 应用场景:
* 密码字段导出为:"******" * * @return 默认true */ String replace() default ""; }///:~
  • 常用的注解及其作用:

  • 首先规则:以//: 开始,以///:~结束。

    • @author 作者名

    • @version 版本号

    • @since 指明需要最早使用的jdk版本

  • 当然还有一些其他注解,例如在类的方法上:

    • @param 参数名
    • @return 返回值情况
    • @throws 异常抛出情况
  • 第一步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KM4q3tjI-1588690352155)(JavaSE.assets/(1)-1587978307833.png)]

  • 第二步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xUYqDcjT-1588690352158)(JavaSE.assets/(2).png)]

  1. 选择是整个项目还是模块还是单个文件

  2. 文档输出路径

  3. Locale 选择地区,这个决定了文档的语言,中文就是zh_CN

  4. 传入JavaDoc的参数,一般这样写 -encoding UTF-8 -charset UTF-8 -windowtitle “文档HTML页面标签的标题” http://docs.Oracle.com/javase/7/docs/api

第五章 Java流程控制

5.1、用户交互Scanner

5.1.1、Scanner对象

  • 之前所学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了一个工具类,我们可以获取用户的输入。java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入
  • 基本语法:Scanner s = new Scanner(System.in);
  • 通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取我们一般需要使用hasNextLine()判断是否还有输入的数据

5.1.2、两种方法

  • next() 方法
    • 一定要读取到有效字符后才可以结束输入
    • 对输入有效字符之前遇到的空白,next()方法会自动将其去掉
    • 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符
    • next()不能得到带有空格的字符串
    • 是以空格作为结束符的

练习文件Demo01

package com.mza.Scanner;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class Demo01 {

    public static void main(String[] args) {

        //创建一个扫描器对象,用于接受键盘数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("使用next方式接收:");

        //判断用户有没有输入字符串
        if(scanner.hasNext()){
            //使用next方式接收
            String str = scanner.next();
            System.out.println("输出的内容为:"+str);
        }

        //凡是属于IO流的类如果不关闭会一直占用资源,要养成好习惯用完就关掉
        scanner.close();

    }
}
  • nextLine()方法(用的场景较多)
    • 以Enter为结束符,也就是说nextLine()方法返回的是输入回车之前的所有字符
    • 可以获得空白
    • 是以Enter作为结束符的

练习文件Demo02

package com.mza.Scanner;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class Demo02 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //创建一个扫描器对象,用于接收键盘数据
        System.out.println("使用nextLine方法接收:");

        //判断用户有没有输入字符串
        if (scanner.hasNextLine()){
            //使用nextLine接受
            String str = scanner.nextLine();
            System.out.println("输出的内容为:"+str);
        }

        //凡是属于IO流的类如果不关闭会一直占用资源,要养成好习惯用完就关掉
        scanner.close();
    }
}

练习文件Demo04

package com.mza.Scanner;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class Demo04 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //从键盘接收数据
        int i = 0;
        float f = 0.0f;

        System.out.println("请输入整数:");

        //如果...那么
        //判断用户有没有输入整数数据
        if(scanner.hasNextInt()){
            //接收输入的i
            i = scanner.nextInt();
            System.out.println("整数数据" + i);
        }else{
            System.out.println("输入的不是整数数据!");
        }

        System.out.println("请输入小数:");

        if(scanner.hasNextFloat()){
            //接收输入的i
            f = scanner.nextFloat();
            System.out.println("小数数据" + f);
        }else{
            System.out.println("输入的不是小数数据!");
        }


        scanner.close();
    }
}

练习文件Demo05//我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果

package com.mza.Scanner;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class Demo05 {
    public static void main(String[] args) {
        //我们可以输入多个数字,并求其总和与平均数,每输入一个数字用回车确认,通过输入非数字来结束输入并输出执行结果
        Scanner scanner = new Scanner(System.in);

        //和
        double sum = 0;
        //计算输入了多少个数字
        int m = 0;

        //通过循环判断是否还有输入,并在里面对每一次进行求和和统计
        while (scanner.hasNextDouble()){
            double x = scanner.nextDouble();
            m = m + 1;   //m++
            sum = sum + x;
            System.out.println("你输入了第" + m + "个数据,然后当前结果sum=" + sum);
        }

        System.out.println(m + "个数的和为" + sum);
        System.out.println(m + "个数的平均值是" + (sum / m));

        scanner.close();
    }
}

5.2、顺序结构

  • Java的基本结构就是顺序结构,除非特别指明,否则就按照顺序一句一句执行
  • 顺序结构是最简单的算法结构
  • 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,它是任何一个算法都离不开的一种基本算法结构

练习文件SequenceDemo

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/27.
 * 顺序结构
 */
public class SequenceDemo {
    public static void main(String[] args) {
        System.out.println("hello1");
        System.out.println("hello2");
        System.out.println("hello3");
        System.out.println("hello4");
        System.out.println("hello5");
    }
}

5.3、选择结构*

5.3.1、if单选择结构

  • 我们很多时候需要去判断一个东西是否可行,然后我们才去执行,这样一个过程在程序中用if语句来表示

  • 语法:

if(布尔表达式){
    //如果布尔表达式为true将执行的语句
}

练习文件IfDemo01

package com.mza.struct;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class IfDemo01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入内容");
        String s = scanner.nextLine();

        //equals:判断字符串是否相等
        if (s.equals("Hello")){
            System.out.println(s);
        }

        System.out.println("End");
        scanner.close();
    }
}

5.3.2、if双选择结构

  • 公司现在有个需求,公司要收购一个软件,成功了,给人支付100万元,失败了,自己找人开发。这样的需求单用一个if就搞不定了,我们需要有两个判断,需要一个双选择结构,所以就有了if-else结构
  • 语法:
if(布尔表达式){
    //如果布尔表达式的值为true
}else{
    //如果布尔表达式的值为false
}

练习文件IfDemo02//考试分数大于60就是及格,小于60就不及格

package com.mza.struct;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class IfDemo02 {
    public static void main(String[] args) {
        //考试分数大于60就是及格,小于60就不及格
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入成绩:");
        int score = scanner.nextInt();

        if(score>=60){
            System.out.println("恭喜,您的成绩及格!");
        }else{
            System.out.println("很遗憾,您的成绩不及格");
        }

        scanner.close();
    }
}

5.3.3、if多选择结构

  • 我们发现刚才的代码不符合实际情况,真实的情况还可能存在ABCD多种情况,存在区间多级判断。比如90-100就是A,80-90就是B…等,在生活中我们很多时候的选择也不仅仅只有两个,所以我们需要一个多选择结构来处理这类问题
  • 语法:
if(布尔表达式1){
    //如果布尔表达式1的值为true执行代码
}else if(布尔表达式2){
    //如果布尔表达式2的值为true执行代码
}else if(布尔表达式3){
    //如果布尔表达式3的值为true执行代码
}else{
    //如果以上布尔表达式的值都不为true执行代码
}
  • 注意:
    • if语句至多有1个else语句,else语句在所有的else if语句之后
    • if语句可以有若干个else if语句,它们必须在else语句之前
    • 一旦其中一个else if语句检测为true,其它的else if已经else语句都将跳过执行

练习文件IfDemo03//对各等级考试分数的判断

package com.mza.struct;

import java.util.Scanner;

/**
 * Created by Leonardo on 2020/4/27.
 */
public class IfDemo03 {
    public static void main(String[] args) {
        //对各等级考试分数的判断
        Scanner scanner = new Scanner(System.in);

        /**
         * if语句至多有1个else语句,else语句在所有的else if语句之后
         * if语句可以有若干个else if语句,它们必须在else语句之前
         * 一旦其中一个else if语句检测为true,其它的else if已经else语句都将跳过执行
         */

        System.out.println("请输入成绩:");
        int score = scanner.nextInt();

        if (score==100){
            System.out.println("恭喜,成绩满分!");
        }else if (score < 100 && score >= 90){
            System.out.println("优秀");
        } else if(score < 90 && score >= 80){
            System.out.println("良好");
        } else if(score < 80 && score >= 70){
            System.out.println("良");
        } else if(score < 70 && score >= 60){
            System.out.println("及格");
        } else if(score < 60 && score >= 0){
            System.out.println("不及格");
        } else { //单独处理边界外不合理的情况
            System.out.println("数据输入错误");
        }

        scanner.close();
    }
}

5.3.4、嵌套的if结构

  • 使用嵌套的if…else语句是合法的。也就是说你可以在另一个if或者else if语句中使用if或者if else语句。你可以像if语句一样嵌套else if…else
  • 语法:
if(布尔表达式1){
    //如果布尔表达式1的值为true执行代码
    if(布尔表达式2){
        //如果布尔表达式2的值为true执行代码
    }
}
  • 思考:我们需要寻找一个数,在1-100之间

5.3.5、switch多选择结构

  • 多选择结构还有一个实现方式就是switch case语句

  • switch case语句来判断一个变量与一系列值中某个值是否相等,每个值称为一个分支

  • switch语句中的变量类型可以是

    • byte、short、int或者char
    • JDK7的新特性,表达式结果可以是字符串
    • JavaSE7开始,switch支持字符串String类型了
    • 同时case标签必须为字符串常量或字面量
  • 语法

switch(expression){
    case value:
        //语句
        break;   //可选(最好写上)
    case value:
        //语句
        break;   //可选(最好写上)
        //你可以有任意数量的case语句
    default:   //可选
        //语句
}

练习文件SwitchDemo01

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class SwitchDemo01 {
    public static void main(String[] args) {
        //case穿透   //switch匹配一个具体的值
        char grade = 'C';

        switch(grade){
            case 'A':
                System.out.println("优秀");
                break;   //可选
            case 'B':
                System.out.println("良好");
                break;
            case 'C':
                System.out.println("及格");
                break;
            case 'D':
                System.out.println("再接再厉");
                break;
            case 'E':
                System.out.println("挂科");
                break;
            default:
                System.out.println("未知等级");
        }
    }
}

练习文件SwitchDemo02

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class SwitchDemo02 {
    public static void main(String[] args) {
        String name = "张三";
        //JDK7的新特性,表达式结果可以是字符串
        //字符的本质还是数字

        //反编译  Java---class(字节码文件)---反编译(IDEA)

        switch(name){
            case"张三":
                System.out.println("张三");
                break;
            case"李四":
                System.out.println("李四");
                break;
            default:
                System.out.println("弄啥嘞!");
        }
    }
}

5.4、循环结构

  • 三种主要的循环结构:
    • while循环
    • do…while循环
    • for循环
  • 在Java5中引入了一种主要用于数组的增强型for循环

5.4.1、while循环

  • while是最基本的循环,它的结构为:
while(布尔表达式){
    //循环内容
}
  • 只要布尔表达式为true,循环节会一直执行下去
  • 我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环
  • 少部分情况需要循环一直执行,比如服务器的请求响应监听等
  • 循环条件一直为true就会造成无限循环【死循环】,我们正常的业务编程中应该尽量避免死循环。会影响程序性能或造成程序卡死崩溃!
  • 思考:计算1+2+3+…+100=?

练习文件WhileDemo01(输出1~100)

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class WhileDemo01 {
    public static void main(String[] args) {
        //输出1~100

        int i = 0;

        while(i<100){
            i++;
            System.out.println(i);
        }
    }
}

练习文件WhileDemo02(死循环)

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class WhileDemo02 {
    public static void main(String[] args) {
        //死循环
        while (true){
            //等待客户端连接
            //定时检查
            //......
        }
    }
}

练习文件WhileDemo03(计算1+2+3+…+100=?)

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class WhileDemo03 {
    public static void main(String[] args) {
        //计算1+2+3+...+100=?

        int i = 0;
        int sum = 0;

        while(i<=100){
            sum = sum +i;
            i++;
        }
        System.out.println(sum);
    }
}

5.4.2、do…while循环

  • 对于while语句而言,如果不满足条件,则不能进入循环,但有时候我们需要即使不满足条件,也至少执行一次
  • do…while循环和while循环相似,不同的是,do…while循环至少会执行一次
  • while和do…while的区别:
    • while先判断后执行。do…while是先执行后判断
    • do…while总是保证循环体会被至少执行一次,这是它们的主要差别
  • 语法:
do{
    //代码语句
}while(布尔表达式);

练习文件DoWhileDemo01

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class DoWhileDemo01 {
    public static void main(String[] args) {
        int i = 0;
        int sum = 0;

        do {
            sum = sum + i;
            i++;
        }while (i<=100);

        System.out.println(sum);
    }
}

练习文件DoWhileDemo02

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class DoWhileDemo02 {
    public static void main(String[] args) {
        int a = 0;
        while (a<0){
            System.out.println(a);
            a++;
        }
        System.out.println("============华丽的分割线=============");
        do {
            System.out.println(a);
            a++;
        }while ( a < 0 );
    }
}

5.4.3、For循环(重点)

  • 虽然所有循环结构都可以用while或者do…while表示,但Java提供了另一种语句–For循环,使一些循环结构变得更加简单
  • For循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构
  • For循环执行的次数是在执行前就确定的
  • 语法格式:
for(初始化;布尔表达式;更新){
    //代码语句
}

//写For语句的快捷方式
100.for
  • 关于For循环有以下几点说明
    • 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句
    • 然后检测布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
    • 执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。
    • 再次检测布尔表达式。循环执行上面的过程

练习文件ForDemo01

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class ForDemo01 {
    public static void main(String[] args) {
        int a = 1;   //初始化条件

        while (a<=100){   //条件判断
            System.out.println(a);   //循环体
            a += 2;   //迭代,即每次执行a都会刷新
        }
        System.out.println("while循环结束!");

        //初始化条件;条件判断;迭代
        for (int i = 1; i <= 100; i += 2){
            System.out.println(i);
        }
        System.out.println("For循环结束!");

        /*
          关于For循环有以下几点说明
          最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句
          然后检测布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后			 面的语句。
          执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)。
          再次检测布尔表达式。循环执行上面的过程

          死循环:
          for(;;){

          }
         */
    }
}

练习1ForDemo02(计算0到100之间的奇数和偶数的和)

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class ForDemo02 {
    public static void main(String[] args) {
        //计算0到100之间的奇数和偶数的和
        
        int oddsum = 0;
        int evensum = 0;

        for (int i = 0; i <= 100; i++) {
            if (i%2!=0){
                oddsum += i;
            }else{
                evensum += i;
            }
            
        }
        System.out.println("奇数的和" + oddsum);
        System.out.println("偶数的和" + evensum);
    }
}

练习2ForDemo03(用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个)

  • println和print的区别
    • println 输出完会换行
    • print 输出完不会换行
  • \t :为“转义字符“,代表的是一个tab,也就是8个空格
  • \n :换行符
  • \r :回车符
package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class ForDemo03 {
    public static void main(String[] args) {
        //练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出3个

        for (int i = 1; i <= 1000; i++) {
            if (i % 5 == 0){
                System.out.print(i + "\t");
            }
            if (i % (5 * 3) == 0){   //换行
                System.out.println();
                //也可以写System.out.print("\n");
            }
        }
        //println   输出完会换行
        //print     输出完不会换行
    }
}

练习3ForDemo04(打印九九乘法表)

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 * 打印九九乘法表
 */
public class ForDemo04 {
    public static void main(String[] args) {
        //1.我们先打印第一列
        //2.我们打固定的1再用一个循环包起来
        //3.去掉重复项,i<=j
        //4.调整样式

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

5.4.4、增强For循环

  • 这里我们先只是见一面,做个了解,之后学数组我们重点使用
  • Java5引入了一种主要用于数组或集合的增强型for循环
  • Java增强for循环语法格式:
for(声明语句:表达式){
    //代码句子
}
  • 声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
  • 表达式:表达式是要访问的数组名,或者是返回值为数组的方法

练习文件ForDemo05

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class ForDemo05 {
    public static void main(String[] args) {
        int[] numbers = {10,20,30,40,50};   //定义了一个数组

        for (int i = 0; i < 5; i++){
            System.out.println(numbers[i]);
        }
        System.out.println("============华丽的分割线=============");
        //遍历数组的元素
        for (int x:numbers){
            System.out.println(x);
        }
    }
}

5.5、Break & Continue

5.5.1、Break

  • break在任何循环语句的主题部分,均可用break控制循环的流程。
  • break用于强行退出循环,不执行循环中剩余的语句。(break语句也在switch语句中使用)

练习文件BreakDemo

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class BreakDemo {
    public static void main(String[] args) {
        int i = 0;
        while (i<100){
            i++;
            System.out.println(i);
            if (i==30){
                break;
            }
        }
        System.out.println("123");
    }
}

5.5.2、Continue

  • continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。

练习文件ContinueDemo

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class ContinueDemo {
    public static void main(String[] args) {
        int i = 0;
        while (i < 100){
            i++;
            if (i % 10==0){
                    System.out.println();
                    continue;
            }
            System.out.print(i);
        }
    }
}

5.5.3、关于goto关键字(了解即可)

  • goto关键字很早就在程序设计语言中出现。尽管goto仍是Java的一个保留字,但并未在语言中得到正式使用;Java没有goto。然而,在break和continue这两个关键字的身上,我们仍然能看出一些goto的影子—带标签的break和continue。
  • “标签”是指后面跟一个冒号的标识符,如:label:
  • 对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。

练习文件LebalDemo

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class LabelDemo {
    public static void main(String[] args) {
        //打印101-150之间所有的质数

        //质数是指在大于1的自然数中,除了1和它本身以外不再有其它因数的自然数

        int count = 0;

        //不建议使用
        outer:for (int i = 101;i < 150;i++){
            for (int j = 2;j < i / 2;j++){
                if (i % j == 0){
                    continue outer;
                }
            }
            System.out.print(i + " ");
        }

    }
}

5.6、流程控制练习

练习1TestDemo(打印三角形)

package com.mza.struct;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class TestDemo {
    public static void main(String[] args) {
        //打印三角形   5行

        for (int i = 0; i <= 5; i++) {
            for (int j = 5; j >= i; j--) {
                System.out.print(" ");
            }
            for (int j = 1; j <= i; j++) {
                System.out.print("*");
            }
            for (int j = 1; j < i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

第六章 Java方法详解

6.1、何谓方法

  • System.out.println(); 那么它是什么呢?
    • 类.对象.方法
    • 调用系统类System里面的标准输出对象out中的方法println
  • Java方法是语句的集合,它们在一起执行一个功能
    • 方法是解决一类问题的步骤的有序组合
    • 方法包含于类或对象中
    • 方法在程序中被创建,在其它地方被引用
  • 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合,我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期的扩展
  • 回顾:方法的命名规则(驼峰式)

练习文件

package com.mza.method;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class Demo01 {
    //main方法
    public static void main(String[] args) {
//        int sum = add(1,2);      //实际参数:实际调用传递给它的参数
//        System.out.println(sum);
        test();
    }
    //加法
    //形式参数,用来定义作用的
    public static int add(int a,int b){
        return a+b;
    }
    public static void test(){
        for (int i = 1; i <= 1000; i++) {
            if (i % 5 == 0){
                System.out.print(i + "\t");
            }
            if (i % (5 * 3) == 0){   //换行
                System.out.println();
                //也可以写System.out.print("\n");
            }
        }
    }
}

6.2、方法的定义及调用

6.2.1、方法的定义

  • Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码段,一般情况下,定义一个方法包含以下语法:
    • 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
      • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型
      • 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType是关键字void
      • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名
      • 参数类型:参数像是一个占位符。当方法被调用时,传递只给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数
        • 形式参数:在方法被调用时用于接收外界输入的数据
        • 实参:调用方法时实际传给方法的数据
      • 方法体:方法体包含具体的语句,定义该方法的功能

6.2.2、方法的调用

  • 调用方法:对项目。方法名(实参列表)
  • Java支持两种调用方法的方式,根据方法是否返回值来选择
  • 当方法返回一个值的时候,方法调用通常被当作一个值。
  • 例如:
int larger = max(30,40);
  • 如果方法返回值是void,方法调用一定是一条语句
System.out.println("Hello,everyone!");
  • 课后拓展了解:值传递(Java)和引用传递

练习文件Demo02

package com.mza.method;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class Demo02 {
    public static void main(String[] args) {

        int max = max(10,20);
        System.out.println(max);

    }

    //比大小
    public static int max(int num1,int num2){

        int result = 0;

        if (num1==num2){
            System.out.println("num1==num2");
            return 0;   //终止方法
        }

        if(num1>num2){
            result = num1;
        }else{
            result = num2;
        }
        return result;
    }
}

6.3、方法的重载

  • 重载就是在一个类中,有相同的函数名称,但形参不同的函数
  • 方法的重载的规则:
    • 方法名称必须相同
    • 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等)
    • 方法的返回类型可以相同也可以不同
    • 仅仅返回类型不同不足以成为方法的重载
  • 实现理论:
    • 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。

6.4、命令行传参

  • 有时候你希望运行一个程序时候再传递给它消息,这要靠传递命令行参数给main()函数实现
package com.mza.method;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class Demo03 {
    public static void main(String[] args) {
        //args.length 数组长度
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "]: " +args[i]);
        }
    }
}

6.5、可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法
  • 在方法声明中,在指定参数类型后加一个省略号(…)
  • 一个方法中只能制定一个可变参数,它必须是方法的最后一个参数。任何普通的而参数必须在它之前声明
package com.mza.method;

/**
 * Created by Leonardo on 2020/4/28.
 */
public class Demo04 {
    public static void main(String[] args) {
        Demo04 demo04 = new Demo04();
        demo04.test(1,2,3,5,23,24,1);
    }

    public void test(int... i){
        System.out.println(i[1]);
        System.out.println(i[0]);
        System.out.println(i[2]);
        System.out.println(i[3]);
        System.out.println(i[5]);
        System.out.println(i[6]);
        System.out.println(i[4]);
        System.out.println(i[7]);
    }

}

6.6、递归

  • A方法调用B方法,这个很容易理解
  • 递归就是:A方法调用A方法!就是自己调用自己
  • 利用递归可以用简单的程序解决一下复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
  • 递归结构包括两个部分:
    • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。(递归边界)
    • 递归体:什么时候需要调用自身方法
  • 注意:主要学习递归思想,大的运算问题不要使用递归,会导致系统内存卡死

练习文件Demo06

package com.mza.method;

/**
 * Created by Leonardo on 2020/4/28.
 * 阶乘
 * 1!   1
 * 2!   2*1
 * 3!   3*2*1
 * 4!   4*3*2*1
 * 5!   5*4*3*2*1
 */
public class Demo06 {
    //递归思想
    public static void main(String[] args) {
        System.out.println(f(5));
    }

    public static int f(int n){
        if (n==1){
            return 1;
        }else{
            return n*f(n-1);
        }
    }
}
  • 作业:写一个计算器,要求实现加减乘除功能,并且能够循环接收新的数据,通过用户交互实现
    • 思路:
      • 写四个方法
      • 利用循环+switch进行用户交互
      • 传递需要操作的两个数
      • 输出结果

第七章 数组

7.1、数组概述

  • 定义:
    • 数组是相同类型的数据的有序集合
    • 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成
    • 其中,每一个数据称作一个数据元素,每个数组元素可以通过一个下标来访问它们【数组下标是从0开始的】

7.2、数组声明创建

7.2.1、数组的创建

  • 首先必须声明数组变量,才能在程序中使用数组下面是声明数组变量的语句
dataType[] arrayRefVar;		//首选的方法
dataType arrayRefVar[];		//效果相同,但不是首选方法
  • Java语言使用new操作符来创建数组,语法如下:
dataType[] arrayRefVar = new dataType[arraySize]
  • 数组的元素是通过索引访问的,数组索引从0开始
  • 获取数组长度:arrays.length

练习文件ArrayDemo01

package com.mza.array;

/**
 * Created by Leonardo on 2020/4/29.
 */
public class ArrayDemo01 {
    //变量的类型   变量的名字 = 变量的值;
    //数组类型
    public static void main(String[] args) {
        int[] nums;     //定义(java使用的方法)     //1.声明一个数组
        //int nums2[];    //定义(C++使用的方法)    //一般不用这么写
        //int[] nums2 = new int[10]     //也可以这么写,声明和创建写到一起

        nums = new int[10];     //这里面可以存放10个int类型的数字    //2.创建一个数组

        nums[0] = 1;    //3.给数组元素中赋值
        nums[1] = 2;
        nums[2] = 3;
        nums[3] = 4;
        nums[4] = 5;
        nums[5] = 6;
        nums[6] = 7;
        nums[7] = 8;
        nums[8] = 9;
        nums[9] = 10;

        //System.out.println(nums[0]);      //调用方法

        //计算所有元素的和
        int sum = 0;
        //获取数组长度:arrays.length

        for (int i = 0; i < nums.length; i++) {
            sum = sum + nums[i];
        }
        System.out.println("总和为"+sum);
    }

}

7.2.2、内存分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JSmt2OA1-1588690352162)(JavaSE.assets/内存分析.png)]

报错:java.lang.ArrayIndexOutOfBoundsException: 10(数组内存越界)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TEm5Yug7-1588690352164)(JavaSE.assets/数组.png)]

7.2.3、三种初始化

  • 静态初始化

    int[] a = {1,2,3};
    Man[] mans = {new Man(1,1),new Man(2,2)};
    
  • 动态初始化

    int[] b = new int[10];
    b[0] = 10;
    b[1] = 11;
    
  • 数组的默认初始化

    • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化

练习文件ArrayDemo02

package com.mza.array;

/**
 * Created by Leonardo on 2020/4/29.
 */
public class ArrayDemo02 {
    public static void main(String[] args) {
        //静态初始化
        int[] a = {1,2,3,4,5,6,7,8};

        Man[] mans = {new Man(),new Man()};

        System.out.println(a[0]);

        //动态初始化 : 包含默认初始化
        int[] b = new int[10];
        b[0] = 10;
        b[1] = 11;

        System.out.println(b[0]);
        System.out.println(b[1]);
        System.out.println(b[2]);
        System.out.println(b[3]);
        System.out.println(b[4]);
    }
}

7.2.4、数组的四个基本特点

  • 其长度是确定的,数组一旦被创建,它的大小就是不可以改变的

  • 其元素必须是相同类型,不允许出现混合类型

  • 数组中的元素可以是任何数据类型,包括基本类型和引用类型

  • 数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中的

  • 数组边界

    • 下标的合法区间:[0-length-1],如果越界就会报错;

    • public static void main(String[] args) {
      	int[] a = new int[2];
          System.out.println(a[2]);
      }
      
    • java.lang.ArrayIndexOutOfBoundsException: 10(数组下标越界异常)

  • 小结

    • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
    • 数组也是对象。数组元素相当于对象的成员变量
    • 数组长度的确定的、不可变的。如果越界,则会报错:ArrayIndexOutOfBoundsException

7.3、数组使用(没听明白)☢

7.3.1、For-Each循环

7.3.2、数组作方法入参

7.3.3、数组作返回值

7.4、多维数组

  • 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一堆数组,其每一个元素都是一个一堆数组
  • 二维数组语法
int a[][] = new int[2][5];
  • 解析:以上二维数组a可以看成一个两行五列的数组

练习文件ArrayDemo05

package com.mza.array;

/**
 * Created by Leonardo on 2020/4/29.
 */
public class ArrayDemo05 {
    public static void main(String[] args) {

        //定义了一个4行两列的数组
        /*
        1,2     arryay[0]
        2,3     arryay[1]
        3,4     arryay[2]
        4,5     arryay[3]
         */
        int[][] array = {{1,2},{2,3},{3,4},{4,5}};

        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                System.out.println(array[i][j]);
            }
        }
    }

    //打印数组元素
    public static void printArray(int[] arrays) {
        for (int i = 0; i < arrays.length; i++) {
            System.out.println(arrays[i] + " ");
        }
    }
}

7.5、Arryays类

  • 数组的工具类java.util.Arrays
  • 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作
  • 查看JDK帮助文档
  • Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意:是“不用”而不是“不能”)
  • 具有以下常用功能:
    • 给数组赋值:通过fill方法
    • 对数组排序:通过sort方法,按升序
    • 比较数组:通过equals方法比较数组中元素值是否相等
    • 查找数组元素:通过binarySearch方法能对排序好的数组进行二分查找法操作

练习文件ArrayDemo06

package com.mza.array;

import java.util.Arrays;

/**
 * Created by Leonardo on 2020/4/29.
 */
public class ArrayDemo06 {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,8978,1245,5262,574,5,54,12};

        System.out.println(a);      //[I@28d93b30   这是一个hashcode

        //打印数组元素Arrays.toString
        System.out.println(Arrays.toString(a));

        Arrays.sort(a);     //数组进行排序

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

    }

    public static void printArray(int[] a){
        for (int i = 0; i < a.length; i++) {
            if (i==0){
                System.out.print("[");
            }
            if (i==a.length-1){
                System.out.print(a[i]+"]");
            }else {
                System.out.print(a[i] + ", ");
            }
        }
    }
}
package com.mza.array;

        import java.util.Arrays;

/**
 * Created by Leonardo on 2020/4/29.
 */
public class ArrayDemo06 {
    public static void main(String[] args) {
        int[] a = {1,2,3,4,8978,1245,5262,574,5,54,12};

        System.out.println(a);      //[I@28d93b30   这是一个hashcode

        //打印数组元素Arrays.toString
        System.out.println(Arrays.toString(a));

        Arrays.sort(a);     //数组进行排序

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

        Arrays.fill(a,2,4,0);       //数组填充  //第2到4个元素之间的数字被0填充
        System.out.println(Arrays.toString(a));
    }

    public static void printArray(int[] a){
        for (int i = 0; i < a.length; i++) {
            if (i==0){
                System.out.print("[");
            }
            if (i==a.length-1){
                System.out.print(a[i]+"]");
            }else {
                System.out.print(a[i] + ", ");
            }
        }
    }
}

7.7、冒泡排序

  • 冒泡排序无疑是最为出名的排序算法之一,总共有八大排序!
  • 冒泡排序的代码还是相当简单的,两层循环,外层冒泡轮数,里层依次比较,江湖中人尽皆知
  • 我们看到嵌套循环,应该立马就可以得出这个算法的时间复杂度O(n2)

练习文件ArrayDemo07

package com.mza.array;

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

/**
 * Created by Leonardo on 2020/4/29.
 *冒泡排序
 *1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置
 *2.每一次比较,都会产生出一个最大,或者最小的数字
 *3.下一轮则可以少一次排序
 *4.依次循环,直到结束!
 */
public class ArrayDemo07 {
    public static void main(String[] args) {
        int[] a = {1,4,2,5,6,42,2,3,3,3,6,7,129};

        int[] sort = sort(a);     //调用完我们自己写的排序方法以后,返回一个排序后的数组

        System.out.println(Arrays.toString(sort));
    }
    public static int[] sort(int[] array) {
        //临时变量
        int temp = 0;

        //外层循环,判断我们这个要走多少次
        for (int i = 0; i < array.length-1; i++) {

            boolean flag = false;   //通过flag标识为减少没有意义的比较

            //内层循环,比价判断两个数,如果第一个数,比第二个数大,则交换位置
            for (int j = 0; j < array.length - 1 - i; j++) {
                if (array[j+1]

7.7、稀疏数组

  • 需求:编写五子棋游戏中,有存盘退出和续上盘的功能

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2vpdlkbO-1588690352165)(JavaSE.assets/稀疏数组.png)]

  • 分析问题:因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据
  • 解决:稀疏数组
  • 稀疏数组介绍:
    • 当一个数组中大部分元素为0,或者为同一值的数组时。可以使用稀疏数组来保存该数组
    • 稀疏数组的处理方式是:
      • 记录数组一共有几行几列,you多少个不同值
      • 把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模
    • 如下图:左边是原始数组,右边是稀疏数组
      • [0]6行7列共8个数值
      • [1]0行3列数值是22
      • [2]0行36列数值是15
      • 以此类推

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YggMXBXy-1588690352166)(JavaSE.assets/稀疏数组2.png)]

练习文件ArrayDemo08

package com.mza.array;

/**
 * Created by Leonardo on 2020/4/30.
 */
public class ArrayDemo08 {
    public static void main(String[] args) {
        //1.创建一个二维数组11*11   0:没有棋子      1:黑棋        2:白起
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        //输出原始的数组
        System.out.println("输出原始的数组:" );

        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }

        //转换为稀疏数组保存
        //获取有效值的个数
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (array1[i][j]!=0){
                    sum++;
                }
            }
        }
        System.out.println("有效值的个数:" + sum);

        System.out.println("--------------------华丽的分割线------------------------");

        //2.创建一个稀疏数组的数组
        int[][] array2 = new int[sum+1][3];

        array2[0][0] = 11;
        array2[0][1] = 11;
        array2[0][2] = sum;

        //遍历二维数组,将非零的值,存放稀疏数组中
        int count = 0;
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                if (array1[i][j]!=0){
                    count++;
                    array2[count][0] = i;
                    array2[count][1] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }

        //输出稀疏数组
        System.out.println("稀疏数组");

        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i][0]+"\t"+array2[i][1]+"\t"+array2[i][2]+"\t");
        }

        System.out.println("--------------------华丽的分割线------------------------");

        System.out.println("还原");

        //1.读取稀疏数组
        int[][] array3 = new int[array2[0][0]][array2[0][1]];

        //2.给其中的元素还原它的值
        for (int i = 1; i < array2.length; i++) {
            array3[array2[i][0]][array2[i][1]] = array2[i][2];
        }

        //3.打印
        System.out.println("输出还原的数组");

        for (int[] ints : array3) {
            for (int anInt : ints){
                System.out.print(anInt+"\t");
            }
            System.out.println();
        }
    }
}

第八章 面向对象编程

Java的核心思想就是OOP(Object Oriented Programming)即面向对象编程

8.1、初识面向对象

8.1.1、面向过程&面向对象

  • 面向过程思想
    • 步骤清晰简单,第一部做什么,第二部做什么······
    • 面对过程适合处理一些较为简单的问题
  • 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索
    • 面向对象适合处理复杂的问题,时候处理需要多人协作的问题
  • 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。

8.1.2、面向对象

  • 面向对象编程OOP(Object Oriented Programming)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
  • 抽象
  • 三大特性:
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是现有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板

8.2、方法回顾和加深

  • 方法的定义

    • 修饰符
    • 返回类型
    • break:跳出switch,结束循环和return的区别
    • 方法名:注意规范,见名知意
    • 参数列表:(参数类型,参数名)(…(可变长参数))
    • 异常抛出:疑问,后面讲
  • 方法的调用:递归

    • 静态方法:static void类的可以直接调用 Student.say();
    • 非静态方法:void实例化这个类 new;对象类型 对象名 = 对象值
      • 静态方法和非静态方法之间不可相互调用,因为静态方法是和类一起加载的,而非静态方法是类实例化之后才存在的。
    • 形参和实参:实际参数和形式参数的类型要对应
    • 值传递和引用传递
    • this关键字

练习文件为package com.oop.demo01文件夹下的全部文件

8.3、对象的创建分析

8.3.1、类与对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
    • 动物、植物、手机、电脑…
    • Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
  • 对象是抽象概念的具体实例
    • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
    • 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念

练习文件Student

package com.oop.demo02;

/**
 * Created by Leonardo on 2020/5/2.
 * 学生类
 */
public class Student {

    //属性;字段
    String name;    //null
    int age;    //0

    //方法
    public void study(){
        System.out.println(this.name+"在学习");
    }
}

//学程序好? 对世界进行更好的建模!

练习文件Application

package com.oop.demo02;

/**
 * Created by Leonardo on 2020/5/2.
 * 一个项目应该只存在一个main方法
 */
public class Application {
    public static void main(String[] args) {

        //类:抽象的,实例化
        //类实例化后会返回一个自己的对象!
        //student对象就是一个Student类的具体实例
        Student xiaoming = new Student();
        Student xiaohong = new Student();

        xiaoming.name = "小明";
        xiaoming.age = 3;

        System.out.println(xiaoming.name);
        System.out.println(xiaoming.age);

        xiaohong.name = "小红";
        xiaohong.age = 2;

        System.out.println(xiaohong.name);
        System.out.println(xiaohong.age);
    }
}

8.3.2、创建与初始化对象

  • 使用new关键字创建对象

  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:

    • 必须和类的名字相同
    • 必须没有返回类型,也不能写void
  • 构造器必须要掌握

  • 构造器:

    • 和类名相同
    • 没有返回值
  • 作用:

    • new 本质在调用构造方法
    • 初始化对象的值
  • 注意:

    • 定义有参构造之后,如果想使用无参构造,显示的定义一个午餐的构造

练习文件Application

package com.oop.demo02;

/**
 * Created by Leonardo on 2020/5/2.
 * 一个项目应该只存在一个main方法
 */
public class Application {
    public static void main(String[] args) {

        //new实例化了一个对象
        Person person = new Person("马子骜");

        System.out.println(person.name);    //马子骜

        //类:抽象的,实例化
        //类实例化后会返回一个自己的对象!
        //student对象就是一个Student类的具体实例
/*        Student xiaoming = new Student();
        Student xiaohong = new Student();

        xiaoming.name = "小明";
        xiaoming.age = 3;

        System.out.println(xiaoming.name);
        System.out.println(xiaoming.age);

        xiaohong.name = "小红";
        xiaohong.age = 2;

        System.out.println(xiaohong.name);
        System.out.println(xiaohong.age);*/
    }
}

练习文件Person

package com.oop.demo02;

/**
 * Created by Leonardo on 2020/5/2.
 * Java-->class
 */
public class Person {

    //一个类即使什么都不写,它也会存在一个方法
    //显示的定义构造器

    String name;

    //快捷键:alt+insert

    //实例化初始值
    //无参的
    //1.使用new关键字,必须要有构造器,本质是在调用构造器
    //2.用来初始化值
    public Person(){
        //this.name = "马子骜";
    }

    //有参构造:一旦定义了有参构造,无参就必须显示定义
    public Person(String name){
        this.name = name;
    }
}

8.3.3、创建对象内存分析

没听明白

8.3.4、小结类于对象

  • 类与对象:

    • 类是一个模板:抽象
    • 对象是一个具体的实例
  • 方法:

    • 定义,调用
  • 对像的引用

    • 引用类型:基本类型(八大基本类型)
    • 对象是通过引用来操作的:栈—>堆
  • 属性:

    • 字段Field 成员变量
    • 默认初始化:
      • 数字: 0;0.0
      • char:u0000
      • boolean:false
      • 引用类型:null
    • 修饰符 属性类型 属性名 = 属性值
  • 对象的创建和使用:

    • 必须使用new关键字创造对象,构造器 Person maziao = new Person();
    • 对象的属性 maziao.name
    • 对象的方法 maziao.sleep()
  • 类:

    • 静态的属性 属性
    • 动态的行为 方法

练习文件Pet

package com.oop.demo03;

/**
 * Created by Leonardo on 2020/5/2.
 */
public class Pet {
    public String name;
    public int age;

    //无参构造

    public void shout(){
        System.out.println("叫 了一声");
    }
}

练习文件Application

package com.oop;

import com.oop.demo03.Pet;
import com.oop.demo04.Student;

/**
 * Created by Leonardo on 2020/5/2.
 */
public class Application {

    public static void main(String[] args) {

        Pet dog = new Pet();
        dog.name = "旺财";
        dog.age = 3;
        dog.shout();

        System.out.println(dog.name);
        System.out.println(dog.age);

        Pet cat = new Pet();

        cat.name = "小白";
        cat.age = 5;
        cat.shout();

        System.out.println(cat.name);
        System.out.println(cat.age);
    }
}

8.4、面向对象三大特性

8.4.1、封装

  • 该露的露,该藏得藏

    • 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
  • 封装(数据的隐藏)

    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这成为信息隐藏
  • 记住这句话:属性私有,get/set

    • 提供一些可以操作这个属性的方法
    • 提供一些public的get、set方法
    • get:获得这个数据
    • set:给这个数据设置值
  • 封装的意义

    • 1.提高程序的安全性,可以保护数据
    • 2.隐藏代码的实现细节
    • 3.统一接口
    • 4.提高了系统的可维护性

练习文件Student

package com.oop.demo04;

/**
 * Created by Leonardo on 2020/5/3.
 * 类
 * 提供一些可以操作这个属性的方法
 * 提供一些public的get、set方法
 * get:获得这个数据
 * set:给这个数据设置值
 */
public class Student {

    //属性私有
    //名字
    private String name;
    //学号
    private int id;
    //性别
    private char sex;
    //年龄
    private int age;

    //get
    public String getName(){
        return this.name;
    }

    //set

    public void setName(String name) {
        this.name = name;
    }

    //快捷键alt+insert
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age>120 || age<0) {
            this.age = 3;
        }else{
          this.age = age;
        }
    }

    //学习()

    //睡觉()

}

练习文件Application

package com.oop;

import com.oop.demo04.Student;

/**
 * Created by Leonardo on 2020/5/2.
 * 封装的意义
 * 1.提高程序的安全性,可以保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.提高了系统的可维护性
 */
public class Application {

    public static void main(String[] args) {

        Student s1 = new Student();

        s1.setName("马子骜");

        System.out.println(s1.getName());

        s1.setAge(999);    //不合法的
        System.out.println(s1.getAge());

    }
}

8.4.2、继承

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
  • extends的意思是“扩展”。子类是父类的扩展
  • Java中类只有单继承,没有多继承。一个子类只能有一个父类,而一个父类可以有很多个子类
  • 继承是类和类之间的一种关系,除此之外,类和类之间的关系还有依赖、组合、聚合等
  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
  • 子类和父类之间,从意义上讲应该具有“is a”的关系
  • object类
  • super
  • 方法重写–>多态

练习文件package com.oop.demo05

person

package com.oop.demo05;

/**
 * Created by Leonardo on 2020/5/3.
 * 人 :父类
 * 在Java中所有的类都默认直接或者间接继承Object类
 */
public class Person {

    //public
    //protected
    //default 默认的
    //private 无法继承
    private int money = 10_0000_0000;

    public void say(){
        System.out.println("funny mud pee!");
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

Student

package com.oop.demo05;

/**
 * Created by Leonardo on 2020/5/3.
 * 学生 是 人     Student if Person
 * 子类;派生类
 * 子类继承了父类,就会拥有父类的全部方法
 */
public class Student extends Person{

    //快捷键:ctrl+H

}

Teacher

package com.oop.demo05;

/**
 * Created by Leonardo on 2020/5/3.
 * 老师 是 人     Teacher is Person
 * 子类;派生类
 */
public class Teacher extends Person {
}

Application

package com.oop;

import com.oop.demo05.Person;
import com.oop.demo05.Student;

/**
 * Created by Leonardo on 2020/5/2.
 * 封装的意义
 * 1.提高程序的安全性,可以保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.提高了系统的可维护性
 */
public class Application {

    public static void main(String[] args) {

        Person person = new Person();

    }
}
  • super注意点:
    • super调用父类的构造方法,必须在构造方法的第一个
    • super必须只能出现在子类的方法或者构造方法中
    • super和this不能同时调用构造方法
  • super和this的比较:
    • 代表的对象不同:
      • this:本身调用者这个对象
      • super:代表父类对象的应用
    • 前提
      • this:没有继承也可以使用
      • super:只能在继承条件才可以使用
    • 构造方法
      • this():本类的构造
      • super():父类的构造

练习文件package com.oop.demo05

Student

package com.oop.demo05;

/**
 * Created by Leonardo on 2020/5/3.
 * 学生 是 人     Student if Person
 * 子类;派生类
 * 子类继承了父类,就会拥有父类的全部方法
 */
public class Student extends Person{

    //隐藏的代码:调用了弗雷德无参构造
    //调用父类的构造器,必须要在子类构造器的第一行
    public Student(){
        super();
        System.out.println("Student无参执行了");
    }

    //快捷键:ctrl+H
    private String name = "Leonardo";

    public void print(){
        System.out.println("Student");
    }

    public void test1(){
        print();
        this.print();
        super.print();
    }

    public void test2(String name){
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);     //调用父类中的方法
    }

}

Person

package com.oop.demo05;

/**
 * Created by Leonardo on 2020/5/3.
 * 人 :父类
 * 在Java中所有的类都默认直接或者间接继承Object类
 */
public class Person /*extends Object*/ {

    public Person() {
        System.out.println("Person无参执行了");
    }

    protected String name = "maziao";

    //私有的无法被继承
    public void print(){
        System.out.println("Person");
    }
}

Application

package com.oop;

import com.oop.demo05.Person;
import com.oop.demo05.Student;

/**
 * Created by Leonardo on 2020/5/2.
 * 封装的意义
 * 1.提高程序的安全性,可以保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.提高了系统的可维护性
 */
public class Application {

    public static void main(String[] args) {

        Student student = new Student();
        //student.test("马子骜");
        //student.test1("马子骜");

    }
}
  • 重写:需要有继承关系,子类重写父类的方法

    • 重写都是方法的重写,和属性无关
  • 静态的方法(static)和非静态的方法区别很大

    • 静态方法:方法的调用只和左边定义的数据类型有关
  • 非静态:重写

    • 方法名必须相同
  • 参数列表必须相同

    • 修饰符:范围可以扩大:public>protected>default>private
    • 抛出的异常:范围:可以被缩小,但不能扩大;ClassNotFoundException -->Exception(大)
  • 重写,子类的方法和父类必须要一样的,方法体可以不同

  • 为什么需要重写:

    • 父类的功能,子类不一定需要,或者不一定满足
    • 快捷键:ALt+Insert;选override

练习文件package com.oop.demo05

Application

package com.oop;

import com.oop.demo05.A;
import com.oop.demo05.B;

/**
 * Created by Leonardo on 2020/5/2.
 * 封装的意义
 * 1.提高程序的安全性,可以保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.提高了系统的可维护性
 */
public class Application {

    public static void main(String[] args) {

        A a = new A();
        a.test();       //A

        //父类的引用指向了子类
        B b = new A();
        b.test();       //B

    }
}

8.4.3、多态

  • 动态编译:类型:增强可扩展性
  • 什么是多态:即同一方法可以根据发送对象的不同而采用多种不同的行为方式
  • 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多(父类,有关系的类)
  • 多态存在的条件
    • 有继承关系
    • 子类重写父类方法
    • 父类引用指向子类对象
  • 注意:多态是方法的多态,属性没有多态性
  • instanceof关键词:(类型转换)引用类型,判断一个对象是什么类型
  • 注意事项:
    • 多态是方法的多态,属性没有多态
    • 父类和子类,必须有相互的联系 类型转换异常!ClassCastException!
    • 存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new Son();
  • 不能重写的方法:
    • static方法:静态方法,属于类,它不属于实例
    • final 常量
    • private方法

练习文件package com.oop.demo06

Application

package com.oop;

import com.oop.demo06.Person;
import com.oop.demo06.Student;

/**
 * Created by Leonardo on 2020/5/2.
 * 封装的意义
 * 1.提高程序的安全性,可以保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.提高了系统的可维护性
 */
public class Application {

    public static void main(String[] args) {

        //一个对象的实际类型是确定的
        //new Student();
        //new Person();

        //可以指向的引用类型就不确定了;父类的引用指向子类

        //student 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person 父类型,可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        //对象能执行那些方法,主要看对象左边的类型,和右边关系不大
        s2.run();       //子类重写了父类的方法,执行子类的方法
        s1.run();
    }
}
  • instanceof关键词:(类型转换)引用类型,判断一个对象是什么类型

练习文件Application

package com.oop;

import com.oop.demo06.Person;
import com.oop.demo06.Student;
import com.oop.demo06.Teacher;
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.util.Objects;

/**
 * Created by Leonardo on 2020/5/2.
 * 封装的意义
 * 1.提高程序的安全性,可以保护数据
 * 2.隐藏代码的实现细节
 * 3.统一接口
 * 4.提高了系统的可维护性
 */
public class Application {

    public static void main(String[] args) {

        //Object > Person > Student
        //Object > Person > Teacher
        //Object > String(在lang包下)
        Object object = new Student();

        ///System.out.println(X instanceof Y);      判断X与Y之间是否有父子关系,能不能编译通过

        System.out.println(object instanceof Student);      //true
        System.out.println(object instanceof Person);       //true
        System.out.println(object instanceof Object);       //true
        System.out.println(object instanceof Teacher);      //false
        System.out.println(object instanceof String);       //false
        System.out.println("==========================================================");
        Person person = new Student();
        System.out.println(person instanceof Student);      //true
        System.out.println(person instanceof Person);       //true
        System.out.println(person instanceof Object);       //true
        System.out.println(person instanceof Teacher);      //false
        //System.out.println(person instanceof String);       //编译报错
        System.out.println("==========================================================");
        Student student = new Student();
        System.out.println(student instanceof Student);     //true
        System.out.println(student instanceof Person);     //true
        System.out.println(student instanceof Object);     //true
        //System.out.println(student instanceof Teacher);     //编译报错
        //System.out.println(student instanceof String);     //编译报错
    }
}
  • 类型转换
    • 父类引用指向子类的对象
    • 把子类转换为父类,向上转型
    • 把父类转换为子类,向下转型,强制转换
    • 方便方法的调用,减少重复的代码!更简洁
  • 抽象类:接口

8.4.4、Static关键字总结

  • final修饰后不能有子类public final class Person {}

练习文件package com.oop.demo07

package com.oop.demo07;

/**
 * Created by Leonardo on 2020/5/4.
 */
public class Student {
    private static int age;     //静态变量  多线程
    private double score;       //非静态变量

    public void run(){

    }

    public static void go(){

    }

    public static void main(String[] args) {
        go();
    }
}

package com.oop.demo07;

/**
 * Created by Leonardo on 2020/5/4.
 */
public final class Person {
    {
        System.out.println("匿名代码块");        //2     赋初始值
    }

    static {
        System.out.println("静态代码块");        //1     只执行一次
    }

    public Person() {
        System.out.println("构造方法");         //3
    }

    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("========================================");
        Person person2 = new Person();
    }

}
package com.oop.demo07;

//静态导入包
import static java.lang.Math.PI;
import static java.lang.Math.random;

/**
 * Created by Leonardo on 2020/5/4.
 */
public class Test {

    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
    }

}

8.5、抽象类

  • abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类

  • 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的

  • 抽象方法,只有方法的声明,没有方法的实习,它是用来让子类实现的

  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类

    • 不能new这个抽象类,只能靠子类去实现它;约束

    • abstract抽象类:类 extends:有局限性,单继承 (接口可以多继承)

  • 抽象类中可以写普通的方法

  • 抽象方法必须在抽象类中

  • 抽象的抽象:约束

练习文件package com.oop.demo08

package com.oop.demo08;

/**
 * Created by Leonardo on 2020/5/4.
 * abstract抽象类:类 extends:有局限性,单继承  (接口可以多继承)
 */
public abstract class Action {

    //约束~有人帮我们实现
    //abstract:抽象方法,只有方法名字,没有方法的实现
    public abstract void doSomething();

    //1.不能new这个抽象类,只能靠子类去实现它;约束
    //2.抽象类中可以写普通的方法
    //3.抽象方法必须在抽象类中
    //抽象的抽象:约束

    //思考题:抽象类存在的意义:抽象出来~  提高开发效率
}
package com.oop.demo08;

/**
 * Created by Leonardo on 2020/5/4.
 * 抽象类的所有方法,继承了它的子类,都必须要实现它的方法~ 除非~
 */
public class A extends Action {
    @Override
    public void doSomething() {

    }
}

8.6、接口

  • 普通类:只有具体实现

  • 抽象类:具体实现和规范(抽象方法)都有

  • 接口:只有规范。自己无法写方法,专业的约束,实现约束和实现的分离:面向接口编程~

    • 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。如果你是天使,则必须能飞;如果你是汽车,则必须能跑;如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
    • 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守
    • OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计模式都只针对具备了抽象能力的语言(如C++、Java、C#等),就是因为设计模式所研发的,实际上就是如何合理的去抽象
    • 声明类的关键字是class,声明接口的关键字是interface
  • 接口的作用:

    • 约束
    • 定义一些方法,让不同的人实现
    • 方法都是public abstract
    • 常量都是public static final
    • 接口不能被实例化,接口中没有构造方法
    • implements可以实现多个接口
    • 必须要重写接口中的方法

练习文件package com.oop.demo09

8.7、内部类即OOP实战

  • 内部类就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
    1. 成员内部类
    2. 静态内部类
    3. 局部内部类
    4. 匿名内部类
  • 一个Java类中可以有多个class类,但是只能有一个public class

练习文件package com.oop.demo10;

Outer

package com.oop.demo10;

/**
 * Created by Leonardo on 2020/5/4.
 */
public class Outer {

    private int id = 10;
    public void out(){
        System.out.println("这是外部类的方法");
    }

    public class Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //获得外部类的私有属性
        public void getID(){
            System.out.println(id);
        }
    }

}

Application

package com.oop;

import com.oop.demo10.Outer;

/**
 * Created by Leonardo on 2020/5/2.
 */
public class Application {

    public static void main(String[] args) {
        //new
        Outer outer = new Outer();
        //通过这个外部类来实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.getID();
    }
}

Outer

package com.oop.demo10;

/**
 * Created by Leonardo on 2020/5/4.
 */
public class Outer {

    //局部内部类
    public void method(){
        class Inner{
            public void in(){

            }
        }
    }

}

Test

package com.oop.demo10;

/**
 * Created by Leonardo on 2020/5/5.
 */
public class Test {
    public static void main(String[] args) {
        //没有名字初始化类,不用将实力保存到变量中
        new Apple().eat();

        UserService userService = new UserService() {

            @Override
            public void hello() {

            }
        };

    }
}

class Apple{
    public void eat(){
        System.out.println("1");
    }
}

interface UserService{
    void hello();
}

第九章 异常机制

9.1、什么是异常

  • 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序在跑着,内存或者硬盘可能满了。等等。
  • 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是Exception,意思是例外。这些,例外情况或者叫异常,怎么让我们写的程序作出合理的处理,而不至于程序崩溃。
  • 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等
  • 异常发生在程序运行期间,它影响力正常的程序执行流程。
  • 简单分类,要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
    • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法遇见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
    • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时一场可以在编译时被忽略。
    • 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如:当栈溢出时,一个错误就发生了,它们在编译时也检查不到的。
    • 异常处理框架

9.2、异常体系结构

  • 异常体系结构
    • Java把一场当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
    • 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sxegt7nD-1588690352168)(JavaSE.assets/异常.jpg)]

  • Error(灾难性的)

    • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
    • Java虚拟机运行错误(virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
    • 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
  • Exception

    • 在Exception分支中有一个重要的子类RunTimeException(运行时异常)
    • ArrayIndexOutOfBoundsException (数组下标越界)
      • NullPointerException (空指针异常)
    • ArithmeticException (算术异常)
      • MissingResourceException (丢失资源)
    • ClassNotFoundException (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
    • 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
  • Error和Exception的区别: Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程; Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

9.3、Java异常处理机制

  • 抛出异常
  • 捕获异常
  • 异常处理的五个关键字:
    • try:尝试着去处理;监控区域
    • catch:catch(想要捕获的异常类型)捕获异常;可以有多个catch但是要从小往大写。
    • finally:处理善后工作
    • throw:抛出
    • throws:抛出

9.4、处理异常

练习文件package com.exception.demo01

9.5、自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常,只需继承Exception类即可。
  • 在程序使用自定义异常类,大体可分为以下几个步骤:
    1. 创建自定义异常类
    2. 在方法中通过throw关键字抛出异常对象
    3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
    4. 在出现异常方法的调用者中捕获并处理异常

练习文件package com.exception.demo01

9.6、总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被一楼的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源

练习文件package com.exception.demo02

em.out.println(“这是外部类的方法”);
}

public class Inner{
    public void in(){
        System.out.println("这是内部类的方法");
    }

    //获得外部类的私有属性
    public void getID(){
        System.out.println(id);
    }
}

}


**Application**

```JAVA
package com.oop;

import com.oop.demo10.Outer;

/**
 * Created by Leonardo on 2020/5/2.
 */
public class Application {

    public static void main(String[] args) {
        //new
        Outer outer = new Outer();
        //通过这个外部类来实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.getID();
    }
}

Outer

package com.oop.demo10;

/**
 * Created by Leonardo on 2020/5/4.
 */
public class Outer {

    //局部内部类
    public void method(){
        class Inner{
            public void in(){

            }
        }
    }

}

Test

package com.oop.demo10;

/**
 * Created by Leonardo on 2020/5/5.
 */
public class Test {
    public static void main(String[] args) {
        //没有名字初始化类,不用将实力保存到变量中
        new Apple().eat();

        UserService userService = new UserService() {

            @Override
            public void hello() {

            }
        };

    }
}

class Apple{
    public void eat(){
        System.out.println("1");
    }
}

interface UserService{
    void hello();
}

第九章 异常机制

9.1、什么是异常

  • 实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求、你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序在跑着,内存或者硬盘可能满了。等等。
  • 软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是Exception,意思是例外。这些,例外情况或者叫异常,怎么让我们写的程序作出合理的处理,而不至于程序崩溃。
  • 异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等
  • 异常发生在程序运行期间,它影响力正常的程序执行流程。
  • 简单分类,要理解Java异常处理是如何工作的,你需要掌握以下三种类型的异常:
    • 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法遇见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。
    • 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时一场可以在编译时被忽略。
    • 错误ERROR:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如:当栈溢出时,一个错误就发生了,它们在编译时也检查不到的。
    • 异常处理框架

9.2、异常体系结构

  • 异常体系结构
    • Java把一场当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类
    • 在Java API中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception

[外链图片转存中…(img-Sxegt7nD-1588690352168)]

  • Error(灾难性的)

    • Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关
    • Java虚拟机运行错误(virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
    • 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
  • Exception

    • 在Exception分支中有一个重要的子类RunTimeException(运行时异常)
    • ArrayIndexOutOfBoundsException (数组下标越界)
      • NullPointerException (空指针异常)
    • ArithmeticException (算术异常)
      • MissingResourceException (丢失资源)
    • ClassNotFoundException (找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
    • 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
  • Error和Exception的区别: Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程; Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。

9.3、Java异常处理机制

  • 抛出异常
  • 捕获异常
  • 异常处理的五个关键字:
    • try:尝试着去处理;监控区域
    • catch:catch(想要捕获的异常类型)捕获异常;可以有多个catch但是要从小往大写。
    • finally:处理善后工作
    • throw:抛出
    • throws:抛出

9.4、处理异常

练习文件package com.exception.demo01

9.5、自定义异常

  • 使用Java内置的异常类可以描述在编程时出现的大部分异常情况。除此之外,用户还可以自定义异常。用户自定义异常,只需继承Exception类即可。
  • 在程序使用自定义异常类,大体可分为以下几个步骤:
    1. 创建自定义异常类
    2. 在方法中通过throw关键字抛出异常对象
    3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch语句捕获并处理;否则在方法的声明处通过throws关键字指明要抛出给方法调用者的异常,继续进行下一步操作
    4. 在出现异常方法的调用者中捕获并处理异常

练习文件package com.exception.demo01

9.6、总结

  • 处理运行时异常时,采用逻辑去合理规避同时辅助 try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被一楼的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源

练习文件package com.exception.demo02

你可能感兴趣的:(Java学习笔记)