Java基础语法(续)
1.数据类型转换
Java程序中要求参与的计算的数据, 必须要保证数据类型的一致性, 如果数据类型不一致将发生类型的转换。
1. 自动类型转换(隐式)
将取值范围小的类型自动提升为取值范围大的类型 。
public class Demo {
public static void main(String[] args) {
int i = 1;
byte b = 2;
// byte x = b + i; // 报错
//int类型和byte类型运算, 结果是int类型
int j = b + i;
System.out.println(j);
}
}
byte 类型内存占有1 个字节, 在和 int 类型运算时会提升为 int 类型 , 自动补充3个字节, 因此计算后的结果还是 int 类型。
转换规则:
范围小的类型向范围大的类型提升, byte、 short、 char 运算时直接提升为 int 。
byte、 short、 char‐‐>int‐‐>long‐‐>float‐‐>double
说明:
- 整数默认是int类型, byte、 short和char类型数据参与运算均会自动转换为int类型。
byte b1 = 10;
byte b2 = 20;
byte b3 = b1 + b2;
// 第三行代码会报错, b1和b2会自动转换为int类型, 计算结果为int, int赋值给byte需要强制类型转换。
// 修改为:
int num = b1 + b2;
// 或者:
byte b3 = (byte) (b1 + b2) ;
- boolean类型不能与其他基本数据类型相互转换。
2. 强制转换(显式)
将值范围大的类型强制转换成取值范围小的类型 。
比较而言, 自动转换是Java自动执行的, 而强制转换需要我们自己手动执行。
转换格式:
数据类型 变量名 = (数据类型) 被转数据值;
示例:
public class Demo1 {
public static void main(String[] args) {
//short类型变量, 内存中2个字节
short s = 1;
/*
出现编译失败
s和1做运算的时候, 1是int类型, s会被提升为int类型
s+1后的结果是int类型, 将结果在赋值会short类型时发生错误
short内存2个字节, int类型4个字节
必须将int强制转成short才能完成赋值
*/
//s = s + 1; //编译失败
s = (short) (s + 1); //编译成功
}
}
注意:
- 浮点转成整数, 直接取消小数点, 可能造成数据损失精度。
- int 强制转成 short 砍掉2个字节, 可能造成数据丢失
3. ASCII编码表
编码表 : 就是将人类的文字和一个十进制数进行对应起来组成一张表格。
规定:
字符 | 数值 |
---|---|
0 | 48 |
9 | 57 |
A | 65 |
Z | 90 |
a | 97 |
z | 122 |
将所有的英文字母, 数字, 符号都和十进制进行了对应, 因此产生了世界上第一张编码表ASCII(American Standard Code for Information Interchange 美国标准信息交换码) 。
public class Demo2 {
public static void main(String[] args) {
//字符类型变量
char c = 'a';
int i = 1;
//字符类型和int类型计算
System.out.println(c + i); //输出结果是98
}
}
在char类型和int类型计算的过程中, char类型的字符先查询编码表, 得到97, 再和1 求和, 结果为98。 char类型提升为了int类型。
char类型内存2个字节, int类型内存4个字节。
4. 类型转换案例
byte a = 3;
byte b = 4;
byte c = a + b; //错误。 因为两个byte变量相加, 会先提升为int类型
byte d = 3 + 4; //正确。 常量优化机制
常量优化机制:
在编译时,整数常量的计算会直接算出结果,并且会自动判断该结果是否在byte取值范围内
在:编译通过
不在:编译失败
2.运算符
1. 算术运算符
算术运算符包括
+ | 加法运算, 字符串连接运算 |
---|---|
- | 减法运算 |
* | 乘法运算 |
/ | 除法运算 |
% | 取模运算, 两个数字相除取余数 |
++、– | 自增自减运算 |
注意:
- /和%的区别:两个数据做除法, /取结果的商, %取结果的余数。
- 整数操作只能得到整数,要想得到小数,必须有浮点数参与运算。
++ 运算, 变量自己增长1 。 反之, – 运算, 变量自己减少1 , 用法与 ++ 一致
-
独立运算:
- 变量在独立运算时, 前++ 和 后++ 没有区别 。
- 变量 前++ : 例如 ++i 。
- 变量 后++ : 例如 i++ 。
-
混合运算:
-
和其他变量放在一起, 前++ 和 后++ 就产生了不同。
-
变量 前++ : 变量a自己加1 , 将加1 后的结果赋值给b, 也就是说a先计算。 a和b的结果都是2。
public class Demo4 { public static void main(String[] args) { int a = 1; int b = ++a; System.out.println(a); //计算结果是2 System.out.println(b); //计算结果是2 } }
- 变量 后++ : 变量a先把自己的值1 ,赋值给变量b,此时变量b的值就是1 ,变量a自己再加1 。a的结果是2,b的结果是1 。
int a = 1; int b = a++; System. out. println(a) ; //计算结果是2 System. out. println(b) ; //计算结果是1
-
+符号在字符串中的操作:
+ 符号在遇到字符串的时候, 表示连接、 拼接的含义。
“a”+"b"的结果是“ab”, 连接含义。
public class Demo5 {
public static void main(String[] args) {
System.out.println(1 + 99 + "wen"); // 输出: 100wen
System.out.println(1 + 2 + "wen" + 3 + 4); // 输出: 3wen34
// 可以使用小括号改变运算的优先级
System.out.println(1 + 2 + "wen" + (3 + 4)); // 输出: 3wen7
}
}
2. 赋值运算符
赋值运算符的作用是将一个表达式的值赋给左边,左边必须是可修改的,不能是常量。
符号 | 作用 | 说明 |
---|---|---|
= | 赋值 | 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 |
注意:扩展的赋值运算符隐含了强制类型转换
3. 关系运算符
关系运算符有6种关系,分别为小于、小于等于、大于、等于、大于等于、不等于。
符号 | 说明 |
---|---|
== | 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 |
注意事项:
关系运算符的结果都是boolean类型,要么是true,要么是false。
“=="是判断是否相等的关系, "="是赋值,不要混淆两者。
4. 逻辑运算符
逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。
符号 | 作用 | 说明 |
---|---|---|
& | 逻辑与 | a&b, a和b都是true,结果为true,否则为false |
| | 逻辑或 | a|b, a和b都是false,结果为false,否则为true |
^ | 逻辑异或 | a^b, a和b结果不同为true,相同为false |
! | 逻辑非 | !a,结果和a的结果正好相反 |
&& | 短路与 | 作用和&相同,但是有短路效果 |
|| | 短路或 | 作用和|相同,但是有短路效果 |
在逻辑与运算中,只要有一个表达式的值为false,那么结果就可以判定为false了,没有必要将所有表达式的值都计算出来,短路与操作就有这样的效果,可以提高效率。同理在逻辑或运算中,一旦发现值为true,右边的表达式将不再参与运算。
- 逻辑与&,无论左边真假,右边都要执行。
- 短路与&&,如果左边为真,右边执行;如果左边为假,右边不执行。
- 逻辑或| ,无论左边真假,右边都要执行。
- 短路或|| ,如果左边为假,右边执行;如果左边为真,右边不执行。
public class Demo6 {
public static void main(String[] args) {
int x = 3;
int y = 4;
System.out.println((x++ > 4) & (y++ > 5)); // 两个表达都会运算
System.out.println(x); // 4
System.out.println(y); // 5
System.out.println((x++ > 4) && (y++ > 5)); // 左边已经可以确定结果为false, 右边不参与运算
System.out.println(x); // 4
System.out.println(y); // 4
}
}
5. 三元运算符
三元运算符语法格式:
关系表达式 ? 表达式1 : 表达式2;
解释:问号前面的位置是判断的条件,判断结果为boolean型,为true时调用表达式1 ,为false时调用表达式2。其逻辑为:如果条件表达式成立或者满足则执行表达式1 ,否则执行第二个。
举例:
int a = 10;
int b = 20;
int c = a > b ? a : b; // 判断 a>b 是否为真, 如果为真取a的值, 如果为假, 取b的值
3. 方法
方法: 就是将一个功能抽取出来, 把代码单独定义在一个大括号内, 形成一个单独的功能。
当我们需要这个功能的时候, 就可以去调用。 这样即实现了代码的复用性, 也解决了代码冗余的现象。
方法的定义格式:
修饰符 返回值类型 方法名 (参数列表) {
代码. . .
return ;
}
方法在定义完毕后, 方法不会自己运行, 必须被调用才能执行, 我们可以在主方法main中来调用我们自己定义好的方法。 在主方法中, 直接写要调用的方法名字就可以调用了。
import java.util.Scanner;
public class Tool {
public static void main(String[] args) {
int a, b;
Scanner scanner = new Scanner(System.in);
a = scanner.nextInt();
b = scanner.nextInt();
System.out.println(a+ "和" + b + "中" + getMax(a,b) + "更大");
scanner.close();
}
public static int getMax(int a,int b) {
return a > b ? a : b;
}
}
注意事项:
- 方法必须定义在一类中方法外
- 方法不能定义在另一个方法的里面
4.流程控制语句
1.顺序结构
顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
2.分支语句
- if语句格式
格式:
if (关系表达式) {
语句体1;
}
else {
语句体2;//可嵌套if语句
}
执行流程:
①首先计算关系表达式的值
②如果关系表达式的值为true就执行语句体1
③如果关系表达式的值为false就执行语句体2
④继续执行后面的语句内容
示例:
public static void main(String[] args) {
// 程序判断一个数, 是奇数还是偶数
int num = 9;
if (num % 2 == 0) {
System.out.println("偶数");
} else {
System.out.println("奇数");
}
}
- switch语句
格式:
switch (表达式) {
case 1:
语句体1;
break;
case 2:
语句体2;
break;
. . .
default:
语句体n+1;
break;
}
首先计算出表达式的值
其次,和case依次比较,一旦有对应的值,就会执行相应的语句,在执行的过程中,遇到break就会结束。
最后,如果所有的case都和表达式的值不匹配,就会执行default语句体部分,然后程序结束掉。
注意:如果switch语句中,case省略了break语句, 就会开始case穿透
示例:
需求:键盘录入星期数,输出工作日、休息日 (1-5)工作日, (6-7)休息日
public class Test {
/*
case穿透是如何产生的?
如果switch语句中, case省略了break语句, 就会开始case穿透
现象:
当开始case穿透, 后续的case就不会具有匹配效果, 内部的语句都会执行
直到看见break, 或者将整体switch语句执行完毕, 才会结束。
*/
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入星期数: ");
int week = sc.nextInt();
switch (week) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("工作日 ");
break;
case 6:
case 7:
System.out.println("休息日 ");
break;
default:
System.out.println("您的输入有误");
break;
}
}
}
3.循环
1. for循环
循环语句可以在满足循环条件的情况下,反复执行某一段代码,这段被重复执行的代码被称为循环体语句,当反复 执行这个循环体时,需要在合适的时候把循环判断条件修改为false,从而结束循环,否则循环将一直执行下去,形成死循环。
for循环格式:
for (初始化语句; 条件判断语句; 条件控制语句) {
循环体语句;
}
水仙花数示例:
水仙花数,指的是一个三位数,个位、十位、百位的数字立方和等于原数
public static void main(String[] args) {
//输出所有的水仙花数必然要使用到循环, 遍历所有的三位数, 三位数从100开始, 到999结束
for(int i=100; i<1000; i++) {
//在计算之前获取三位数中每个位上的值
int ge = i%10;
int shi = i/10%10;
int bai = i/10/10%10;
//判定条件是将三位数中的每个数值取出来, 计算立方和后与原始数字比较是否相等
if(ge*ge*ge + shi*shi*shi + bai*bai*bai == i) {
//输出满足条件的数字就是水仙花数
System. out. println(i) ;
}
}
}
2. while循环
while循环完整格式:
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}
示例:
public static void main(String[] args) {
//需求: 在控制台输出5次"HelloWorld"
//for循环实现
for (int i = 1; i <= 5; i++) {
System.out.println("HelloWorld");
}
System.out.println("--------");
//while循环实现
int j = 1;
while (j <= 5) {
System.out.println("HelloWorld");
j++;
}
}
3. do-while循环
完整格式:
初始化语句;
do {
循环体语句;
条件控制语句;
}while(条件判断语句) ;
4. 三种循环的区别
-
三种循环的区别
- for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
- do…while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
-
for循环和while的区别
-
条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
-
条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
-
5. 死循环
死循环(无限循环)的三种格式
- for(;;){}
- while(true){}
- do {} while(true);
5. JShell脚本工具
什么时候会用到 JShell 工具呢, 当我们编写的代码非常少的时候, 而又不愿意编写类, main方法,也不愿意去编译和运行, 这个时候可以使用JShell工具。
注意:
JShell工具, 只适合片段代码的测试, 开发更多内容, 建议编写在方法中。