运算符
1.隐式转换和强制转换
类型转换的分类
1.隐式转换:
取值范围小的数值 转换为 取值范围大的数值
2.强制转换:
取值范围大的数值 转换为 取值范围小的数值
隐式转换的两种提升规则
取值范围小的,和取值范围大的进行运算,小的会先提升为大的,再进行运算
byte short char 三种类型的数据在运算的时候,都会直接先提升为 int,然后再进行运算
byte => int
int => long => float => double
short => int
// 判断结果的数据类型: // byte b1 = 10; // byte b2 = 20; // result = b1 + b2; // 数据类型 int // // int i = 10; // long n = 100L; // double d = 20.0; // result = i + n + d; // 数据类型 double // // byte b = 10; // short s = 20; // long n = 100L; // result = b + s + n; // 数据类型 long
强制转换
如果把一个取值范围大的数值,赋值给取值范围小的变量。是不允许直接赋值的。如果一定要这么做就需要加入强制转换。
格式:目标数据类型 变量名 =(目标数据类型) 被强转的数据;
// 范例: double a = 12.3; int b = (int) a; byte b1 = 100; byte b2 = 100; byte result = (byte)(b1 + b2); System.out.println(result);// -56 结果就发生错误了 因为要转换的数据过大
2.字符串和字符的加操作
字符串的 “+” 操作
当 “+” 操作中出现字符串时,这个 “+” 是字符串连接符,而不是算术运算符了。会将前后的数据进行拼接,并产生一个新的字符串。
“123” + 123 结果为 “123123”
连续进行 “+” 操作时,从左到右逐个执行。
1 + 99 + “年黑马” 结果为 “100 年黑马”
// 当 字符+字符 或 字符+数字 时,会把字符通过 ASCII 码表查询到对应的数字再进行计算。 System.out.println(1 + 'a'); //98 System.out.println('a' + 'c'); //196 System.out.println('a' + "abc"); //aabc
3.自增自减运算符
// 单独使用: ++ 和 -- 无论是放在变量的前边还是后边,单独写一行结果是一样的。 // 参与计算: // 先用后加 int a = 10; int b = a++; // 先加后用 int a = 10; int b = ++a;
4.赋值运算符和关系运算符
赋值运算符
符号 作用 说明
= 赋值 int a = 10,将 10 赋值给变量 a
+= 加后赋值 a += b,将 a + b 的值给 a
-= 减后赋值 a -= b,将 a - b 的值给 a
*= 乘后赋值 a *= b,将 a × b 的值给 a
/= 除后赋值 a /= b,将 a ÷ b 的商给 a
%= 取余后赋值 a %= b,将 a ÷ b 的余数给 a
关系运算符
符号 说明
== a==b,判断 a 和 b 的值是否相等,成立为 true,不成立为 false
!= a!=b,判断 a 和 b 的值是否不相等,成立为 true,不成立为 false
> a>b,判断 a 是否大于 b,成立为 true,不成立为 false
>= a>=b,判断 a 是否大于等于 b,成立为 true,不成立为 false
< a<b,判断 a 是否小于 b,成立为 true,不成立为 false
<= a<=b,判断 a 是否小于等于 b,成立为 true,不成立为 false
5.四种逻辑运算符和两个短路逻辑运算符
符号 作用 说明
& 逻辑与(且) 并且,两边都为真,结果才是真
| 逻辑或 或者,两边都为假,结果才是假
^ 逻辑异或 相同为 false,不同为 true
! 逻辑非 取反
&& 短路与 结果和 & 相同,但是有短路效果
|| 短路或 结果和 | 相同,但是有短路效果
6.三元运算符和运算符的优先级
(三元运算符 / 三元表达式) 格式
格式:关系表达式? 表达式1: 表达式2;
// 范例:求两个数的较大值 int max = a > b ? a : b; System.out.println(a > b ? a : b);
计算规则
首先计算关系表达式的值
如果值为 true,表达式 1 的值就是运算结果
如果值为 false,表达式 2 的值就是运算结果
小括号()的优先级最高
判断和循环
1.顺序结构
// 顺序结构语句是 Java 程序默认的执行流程,按照代码的先后顺序,从上到下依次执行 System.out.println("努力做主人喜欢的事"); System.out.println("大小姐驾到!统统闪开!"); System.out.println("凛冬已至,故乡的梅花开了吗"); System.out.println("心怀不惧,方能翱翔于天际");
2.分支结构if
if格式
if(关系表达式){
语句体;
}
if 的注意点:
大括号的开头可以另起一行书写,但是建议写在第一行的末尾
在语句体中,如果只有一句代码,大括号可以省略不写
如果对一个布尔类型的变量进行判断,不要用 == 号
if (关系表达式) {
语句体1;
} else {
语句体2;
}
执行流程:
I. 首先计算关系表达式的值
II. 如果关系表达式的值为 true 就执行语句体 1
III. 如果关系表达式的值为 false 就执行语句体 2
IV. 继续执行后面的其他语句
if (关系表达式1) {
语句体1;
} else if (关系表达式2) {
语句体2;
}
...
else {
语句体 n + 1;
}
执行流程:
I. 首先计算关系表达式 1 的值
II. 如果为 true 就执行语句体 1;如果为 false 就计算关系表达式 2 的值
III. 如果为 true 就执行语句体 2;如果为 false 就计算关系表达式 3 的值
IV. ……
V. 如果所有关系表达式结果都为 false,就执行语句体 n+1
3.分支结构switch
switch(表达式) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
执行流程:
I. 首先计算表达式的值。
II. 依次和 case 后面的值进行比较,如果有对应的值,就会执行相应的语句,在执行的过程中,遇到 break 就会结束。
III. 如果所有的 case 后面的值和表达式的值都不匹配,就会执行 default 里面的语句体,然后结束整个 switch 语句。
default 的位置和省略
位置:default 不一定是写在最下面的,我们可以写在任意位置。只不过习惯会写在最下面
省略:default 可以省略,语法不会有问题,但是不建议省略。
case 穿透
就是语句体中没有写 break 导致的。
执行流程:
首先还是会拿着小括号中表达式的值跟下面每一个 case 进行匹配。
如果匹配上了,就会执行对应的语句体,如果此时发现了 break,那么结束整个 switch 语句。
如果没有发现 break,那么程序会继续执行下一个 case 的语句体,一直遇到 break 或者右大括号为止
使用场景:
如果多个 case 的语句体重复了,那么我们考虑利用 case 穿透去简化代码。
// 用箭头简写 int number = 1; switch (number){ case 1 -> { System.out.println("一"); break; } case 2 -> { System.out.println("二"); break; } case 3 -> { System.out.println("三"); break; } default -> { System.out.println("没有这种选项"); break; } }
// 省略大括号 switch (number){ case 1 -> System.out.println("一"); case 2 -> System.out.println("二"); case 3 -> System.out.println("三"); default -> System.out.println("没有这种选项"); }
4.循环语句for
格式:
for (初始化语句 ;条件判断语句 ;条件控制语句) {
循环体语句;
}
执行流程:
① 执行初始化语句
② 执行条件判断语句,看其结果是 true 还是 false
如果是 false,循环结束
如果是 true,执行循环体语句
③ 执行条件控制语句
④ 回到②继续执行条件判断语句
5.循环语句while
初始化语句;
while(条件判断语句){
循环体语句;
条件控制语句;
}
for 和 while 的区别:
for 循环中,控制循环的变量,因为归属 for 循环的语法结构中,在 for 循环结束后,就不能再次被访问到了
while 循环中,控制循环的变量,对于 while 循环来说不归属其语法结构中,在 while 循环结束后,该变量还可以继续使用
循环高级综合练习
1.无限循环和跳转控制语句
//for格式的无限循环 for(;;){ System.out.println("学习"); }
//while格式的无限循环 while(true){ System.out.println("学习"); }
注意事项
无限循环的下面不能再写其他代码了,因为循环永远停不下来,那么下面的代码永远执行不到
//1.continue跳过某一次循环 for (int i = 1; i <= 5; i++) { if(i == 3){ //结束本次循环,继续下次循环 continue; } System.out.println("小老虎在吃第" + i + "个包子"); } //2.结束整个循环 for (int i = 1; i <= 5; i++) { if(i == 3){ //结束整个循环 break; } System.out.println("小老虎在吃第" + i + "个包子");
数组
1.数组的概述和静态初始化
数组:是一种容器,可以用来存储同种数据类型的多个值
数组容器在存储数据的时候,需要结合隐式转换考虑
格式一:数据类型 [] 数组名
范例:int [] array
格式二:数据类型 数组名 []
范例:int array[]
数组的初始化
初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程。
数组初始化的两种方式
1.静态初始化
2.动态初始化
数组的静态初始化
初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程
完整格式:数据类型 [] 数组名 = new 数据类型 []{元素1,元素2,元素3...};
范例:int [] array = new int []{11, 22, 33};
范例:double [] array2 = new double []{11.1, 22.2, 33.3};
简化格式:数据类型 [] 数组名 = {元素1,元素2,元素3...};
范例:int [] array = {11, 22, 33};
范例:double [] array2 = {11.1, 22.2, 33.3};
//需求1:定义数组存储5个学生的年龄 int[] arr1 = new int[]{11,12,13,14,15}; int[] arr2 = {11,12,13,14,15}; //需求2:定义数组存储3个学生的姓名 String[] arr3 = new String[]{"zhangsan","lisi","wangwu"}; String[] arr4 = {"zhangsan","lisi","wangwu"}; //需求3:定义数组存储4个学生的身高 1.93 double[] arr5 = new double[]{1.93,1.75,1.73,1.81}; double[] arr6 = {1.93,1.75,1.73,1.81};
2.数组的地址值和元素访问
double[] arr6 = {1.93,1.75,1.73,1.81};
System.out.println(arr6);//[D@23fc625e 地址值
扩展:
解释一下地址值的格式含义 [D@23fc625e
[ :表示当前是一个数组
D:表示当前数组里面的元素都是double类型的
@:表示一个间隔符号。(固定格式)
23fc625e:才是数组真正的地址值,(十六进制)
平时我们习惯性的会把这个整体叫做数组的地址值
数组元素访问
格式:数组名[索引];
索引:也叫做下标,角标。
索引的特点:从 0 开始,逐个 + 1 增长,连续不间断
利用索引对数组中的元素进行访问
1.获取数组里面的元素
格式: 数组名[索引]
int[] arr = {1,2,3,4,5}; //获取数组中的第一个元素 //其实就是0索引上对应的元素 int number = arr[0]; System.out.println(number);//1 //获取数组中1索引上对应的数据,并直接打印出来 System.out.println(arr[1]);//2 //2.把数据存储到数组当中 //格式: 数组名[索引] = 具体数据/变量; arr[0] = 100; System.out.println(arr[0]);//100
3.数组的遍历
int[] arr = {1,2,3,4,5};
在Java当中,关于数组的一个长度属性,length
调用方式:数组名.length
System.out.println(arr.length);
for (int i = 0; i < arr.length; i++) {
//i: 0 1 2 3 4
System.out.println(arr[i]);
}
扩展:
自动的快速生成数组的遍历方式
idea提供的
数组名.fori
4.数组的动态初始化和常见问题
数组动态初始化
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
格式:数据类型[] 数组名 = new 数据类型[数组长度];
范例:int[] arr = new int[3];
//在创建的时候,由我们自己指定数组的长度,由虚拟机给出默认的初始化值 String[] arr = new String[50]; //添加学生 arr[0] = "zhangsan"; arr[1] = "lisi"; //获取 System.out.println(arr[0]);//zhangsan System.out.println(arr[1]);//lisi System.out.println(arr[2]);//打印出来的是默认初始化值null
数组默认初始化值的规律
整数类型:默认初始化值0
小数类型:默认初始化值0.0
字符类型:默认初始化值'\u0000' 空格
布尔类型:默认初始化值 false
引用数据类型:默认初始化值 null
int[] arr2 = new int[3]; System.out.println(arr2[0]);//0 System.out.println(arr2[1]);//0 System.out.println(arr2[2]);//0
数组动态初始化和静态初始化的区别
动态初始化:手动指定数组长度,由系统给出默认初始化值。
只明确元素个数,不明确具体数值,推荐使用动态初始化
静态初始化:手动指定数组元素,系统会根据元素个数,计算出数组的长度。
需求中已经明确了要操作的具体数据,直接静态初始化即可。
数组常见问题
当访问了数组中不存在的索引,就会引发索引越界异常。
5.数组的内存圈
Java 内存分配
栈:方法运行时使用的内存,比如 main 方法运行,进入方法栈中执行
堆:存储对象或者数组,new 来创建的,都存储在堆内存
方法区:存储可以运行的 class 文件
本地方法栈:JVM 在使用操作系统功能的时候使用,和我们开发无关
寄存器:给 CPU 使用,和我们开发无关
方法
1.什么是方法
什么是方法?
方法是程序中最小的执行单元
实际开发中,什么时候用到方法?
重复的代码、具有独立功能的代码可以抽取到方法中
实际开发中,方法有什么好处?
可以提高代码的复用性
可以提高代码的可维护性
2.最简单的方法定义和调用
方法定义
格式
public static void 方法名 (){
方法体(就是打包起来的代码);
}
范例
public static void playGame (){
七个打印语句;
}
方法调用
格式
方法名();
范例
playGame();
注意:方法必须先定义后调用,否则程序将报错
//定义一个方法 public static void playGame(){ System.out.println("选人物"); System.out.println("准备开局"); System.out.println("对线"); System.out.println("崩盘"); System.out.println("骂队友"); System.out.println("送人头"); System.out.println("GG"); }
//调用方法 playGame();
3.带参数的方法定义和调用
带参数的方法定义
单个参数
格式:public static void 方法名(参数){......}
范例:public static void method(int number){......}
多个参数
格式:public static void 方法名(参数1, 参数2, ......){......}
范例:public static void getSum(int number1, int number2){......}
带参数的方法调用
单个参数
单个参数:方法名(参数);
范例 1:method(10);
范例 2:method(变量);
多个参数
多个参数:方法名(参数1, 参数2, ……);
范例 1:getSum(10,20);
范例 2:getSum(变量1, 变量2);
public static void main(String[] args) { getSum(10,20); } public static void getSum(int num1, int num2){ int result = num1 + num2; System.out.println(result); }
形参和实参
形参:全称形式参数,是指方法定义中的参数
实参:全称实际参数,方法调用中的参数
注意:方法调用时,形参和实参必须一一对应,否则程序将报错。
4.带返回值方法的定义和调用
方法的返回值其实就是方法运行的最终结果
如果在调用处要根据方法的结果,去编写另外一段代码逻辑
为了在调用处拿到方法产生的结果,就需要定义带有返回值的方法
带返回值方法定义
格式
public static 返回值类型 方法名(参数) {
方法体;
return 返回值;
}
范例
public static int getSum(int a, int b) {
int c = a + b;
return c;
}
带返回值方法的调用
直接调用:方法名 (实参);
赋值调用:整数类型 变量名 = 方法名 (实参);
输出调用:System.out.println (方法名 (实参));
return 关键字
方法没有返回值:可以省略不写。如果书写,表示结束方法
方法有返回值:必须要写。表示结束方法和返回结果
5.方法的重载
方法的重载
在同一个类中,定义了多个同名的方法,这些同名的方法具有同种的功能。
每个方法具有不同的参数类型或参数个数,这些同名的方法,就构成了重载关系
简单记:同一个类中,方法名相同,参数不同的方法。与返回值无关。
参数不同:个数不同、类型不同、顺序不同