计算机存储与Java语法全梳理:进制、变量、数据类型、运算符。

进制及其转换

文件存储单位

在计算机中任何数据都是以二进制形式存在的,二进制早期由电信号开关演变而来

一个开关只有两种状态:1和0,对应到开关中就是开和关。这一个电信号开关称之为1bit(1位)

一般将8个bit分成一组,这一组称之为1byte(字节)

字节是计算机中最小的存储单位

1byte能表示的范围是256个数,无符号的情况下,范围是0-255,有符号的情况下范围是-128~127

1KB = 1024byte

1MB = 1024KB

1GB = 1024MB

思考:为什么计算机中文件大小单位以1024为一个进位

因为1024是2的10次幂,使用2进制表达就是1个1,后面9个0

问题扩展:为什么购买的硬盘在电脑中显示的容量与实际标注的容量不一致?

这是因为计算机中1G=1024*1024*1024 字节,但是硬盘厂商在生产硬盘时,为了方便计算,约定1G=1000*1000KB

常见的进制

2进制,逢二进一,由1、0表示,一般8位一组

比如,5用二进制表示就是:0101

10进制,人类最常见、使用最多的进制,逢十进一,由0~9表示,正常书写,没有什么限制规则

8进制,逢八进一,由0~7表示,一般以0开头,比如053

16进制,逢十六进一,由09和AF,总共16个数字表示,一般以0x开头,比如0x53

八进制和十六进制只是为了更好的表示二进制,缩短二进制长度

二进制转十进制

二进制转十进制,使用每一位(从右到左)上的数字*2的(位数-1)次幂,最后将所有的数字相加

比如01101001的十进制是105

image-20230308204037044

十进制转二进制

“短除法”。将这个十进制数字除以2,获得一个余数,然后再将除得的结果再除以2,再获得余数……,直到结果为0为止。最后将所有的余数从后往前拼接起来,就是这个十进制数字的二进制表示。

比如53转二进制00110101

image-20230308204431579

八进制与十进制转换

八转十:使用每一位(从右到左)上的数字*8的(位数-1)次幂,最后将所有的数字相加。比如125转换成十进制就是85

image-20230308204937980

十转八:”短除法”。将这个十进制数字除以8,获得一个余数,然后再将除得的结果再除以8,再获得余数……,直到结果为0为止。最后将所有的余数从后往前拼接起来,比如587转八进制是1113

image-20230308205125932

十六进制与十进制转换

十六转十:使用每一位(从右到左)上的数字*16的(位数-1)次幂,最后将所有的数字相加。

十转十六:”短除法”。将这个十进制数字除以16,获得一个余数,然后再将除得的结果再除以16,再获得余数……,直到结果为0为止。最后将所有的余数从后往前拼接起来

这里需要注意的是,如果余数是10,就用A表示,如果是11,就用B表示….如果是15,就用F表示

其他进制之间的转换

可以借助10进制进行转换,比如2进制转16进制,可以先将2进制转换成10进制,再将10进制转换成16进制

计算机中整数的存储方式

正数的存储

十进制正数存储到计算机中,就是直接将这个十进制转换成二进制,然后进行存储

比如 15(int)存储到计算机中,00000000 00000000 00000000 00001111

比如 15(byte)存储到计算机中, 00001111

比如 128(short) 存储到计算机中,00000000 11111111

二进制的最高位代表符号位,其中0代表正数,1代表负数

负数的存储

先将负数转换成原码,再将其转换成反码,最后转换成补码,存储的是补码

原码:原码就是这个负数将负号去掉,所得的正数的二进制

反码:将原码按位取反,得到的二进制就是反码

补码:反码+1

比如 -53(int) 在计算机中的存储步骤

计算原码

1
00000000 00000000 00000000 00110101

计算反码

1
11111111 11111111 11111111 11001010

计算补码

1
11111111 11111111 11111111 11001011

常量和变量

关键字和保留字

关键字就是Java预先定义好的一些有特殊意义的单词,这些单词构成了Java的语法。

而保留字也是预先定义的一些特殊意义的单词,但是目前Java语法中还没有使用到这些单词

void assert boolean break byte case
char class const continue default do
else enum extends final finally float
goto if abstract import instanceof int
long native new package private protected
return strictfp short static super switch
this throw throws transient try implements
while catch double for interface synchronized
public volatile

标识符

标识符就是给Java中变量、类、方法、包等命名的符号。

标识符有一定的规则要求

  • 标识符必须以字母、数字、下划线、美元符号组成。
  • 标识符不能以数字开头,而其他部分可以是上面四个部分的任意组合
  • Java标识符区分大小写,长度无限制
  • 标识符不可以是Java关键字和保留字

此外,还有一些规范

  • 类名一般使用大驼峰规则(首字母大写,单词间每个首字母也大写),类名一般只使用字母和数字
  • 变量名、方法名一般使用小驼峰规则(首字母小写,后面单词间每个首字母大写),变量名、方法名一般只使用字母和数字
  • 常量名一般使用下划线规则(所有字母全部大写,单词之间使用_隔开),常量一般只有字母、下划线
  • 包名一般使用全部小写字母,也可以有数字

标识符中的“字母”不是采用的是ASCII字符集,采用的是unicode字符集,这意味着标识符中可以出现中文,但是极不建议

变量

变量,就是一个“可操作的存储空间”,空间的位置是确定的,但是里面存什么东西不确定。

注意:System.out.println() 输出一个变量时,是不需要加引号的,直接放入一个变量名即可

变量的使用

变量必须要声明才能够使用

声明

语法1:

1
数据类型 变量名;

比如

1
2
3
4
5
6
int num1;
byte num2;
short num3;
char c1;
float num4;
double num5;

语法2:

1
数据类型 变量名1, 变量名2, 变量名3;

比如

1
int n1, n2, n3, n4;

赋值

变量一旦声明必须赋值,否则没有任何意义

方式1:在声明之后进行赋值

1
变量名 = 变量值;

比如

1
2
3
4
5
int num1;
num1 = 10;
System.out.println(num1);
num1 = 20;
System.out.println(num1);

方式2:在声明时就进行赋值

1
数据类型 变量名 = 变量值;

比如

1
2
3
4
int num = 15;
System.out.println(num);
num = 30;
System.out.println(num);

方式3:同时声明多个变量,同时进行赋值

1
2
3
4
int num1 = 10, num2 = 20, num3 = 30;
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
  1. 在方法中声明的变量必须要进行赋值,否则就没有什么意义
  2. 变量在于一个“变”,声明出来的变量内存空间就在那里,可以反复的往这个内存空间中存储数据
  3. 变量的命名必须遵守标识符规则,此外变量一般采用小驼峰规则
  4. 给变量进行赋值,数据类型必须与变量的类型一致
  5. 同一个代码块中(暂时理解成同一个方法),不能有多个同名的变量
  6. 可以用一个变量为另一个变量进行赋值

常量

常量指的是一个固定的值,比如1,’c’,true,”HelloWorld”

可以使用 final 关键字来修饰一个变量,此时这个变量就是常量

语法

1
final 数据类型 常量名 = 常量值;

代码演示

1
2
3
4
5
6
public class Demo2Constant {
public static void main(String[] args) {
final int num = 10;
System.out.println(num);
}
}

注意

  1. 常量只能被赋值一次,赋值完毕后就不可以修改值
  2. 先声明,后赋值也可以是常量,但依然只能被赋值一次
  3. 常量一般由大写字母组成,单词间使用 _ 分隔

为什么要使用常量?

如果常量直接写死成一个数字,在程序中使用,后期想改这个常量的值,就需要修改大量的代码,有可能会修改到非常量的部分。这种“写死的值”,一般称之为魔法值。开发中应当避免使用魔法值。

如果使用final修饰一个常量,我们可以将这个常量统一进行管理,之后其他地方需要使用到这个值,直接用常量名即可,后续如果想修改常量值,直接修改一处的值,其他地方全部都生效

数据类型

Java的数据类型分为 基本类型引用类型

基本数据类型

数值型

byte、short、int、long、float、double

其中,前四个是正数,后2个是浮点数,并且6个数据类型的表示范围从小到大排列

image-20230309004412521

image-20230309004508646

整数型演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Demo3Number {
public static void main(String[] args) {
byte num1 = 100;
byte num2 = 127;
System.out.println(num1);
System.out.println(num2);
short num3 = 10000;
System.out.println(num3);
int num4 = 1000000;
System.out.println(num4);
long num5 = 10000000000L;
System.out.println(num5);
}
}

浮点数演示

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
float num1 = 10.0F;
System.out.println(num1);
double num2 = 3.14;
System.out.println(num2);
// 强制类型转换
float num3 = (float)(10.0 / 3);
System.out.println(num3);
double num4 = 10.0 / 3;
System.out.println(num4);
}

注意

  1. 数据类型使用时不能超出范围
  2. Java中直接写死一个整数常量,默认是int类型
  3. Java中想要表示long类型的整数,要在数字后面加上 L 或者 l,推荐使用L
  4. Java中直接写死一个小数常量,默认是double类型
  5. 如果想表示float类型的小数,可以在数字后面加上 f 或者 F

布尔型

布尔型只有两个值:true和false。true代表真,false代表假

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Demo4Boolean {
public static void main(String[] args) {
boolean flag1 = true;
System.out.println(flag1);
boolean flag2 = false;
System.out.println(flag2);
if(flag2) {
System.out.println("条件为真");
}else {
System.out.println("条件为假");
}
}
}

字符型

字符型在内存中只占用2个字节,字符就是用单引号包裹起来的单个内容,比如 'A','1','你'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Demo5Char {
public static void main(String[] args) {
char c1 = 'a';
char c2 = '1';
char c3 = ' ';
char c4 = '你';
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
// char c5 = 'abc'; // 不是字符,因为单引号中只能出现单个内容
// char c6 = ''; 不是字符,单引号中必须要有内容
// char c7 = "a"; 不是字符,双引号包裹的叫做“字符串”
}
}

char类型和int类型在一定范围内是可以互相转换的。

1.字符在计算机中的存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Demo6Unicode {
public static void main(String[] args) {
char c1 = 'A';
System.out.println(c1);
int num1 = c1;
System.out.println(num1); // 65
int num2 = 'Z';
System.out.println(num2); // 90
int num3 = 'a';
int num4 = 'z';
System.out.println(num3); // 97
System.out.println(num4); // 122
int num5 = '0';
System.out.println(num5);
int num6 = '9';
System.out.println(num6);
char c2 = 97;
System.out.println(c2);
}
}

转义字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Demo7Char {
public static void main(String[] args) {
char c1 = '\n';
System.out.println(c1);
char c2 = '\b';
System.out.println(c2);
char c3 = '\t';
System.out.print(c3);
System.out.println("HelloWorld");
char c4 = '\'';
System.out.println(c4);
char c5 = '\"';
System.out.println(c5);
char c6 = '\\';
System.out.println(c6);
}
}

引用数据类型

String字符串

使用双引号 "" 包裹起来的内容称之为字符串,双引号中的内容可以有任意多个,也可以为空。

字符串的使用方式与基本数据类型基本一致,但需要注意的是它是引用数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Demo8String {
public static void main(String[] args) {
// 字符串简单使用
String str = "HelloWorld";
System.out.println(str);
// 使用 + 号可以拼接字符串
String s2 = "leo" + str;
System.out.println(s2);
// 使用+号时,如果下一个+的是字符串,那么整体会被拼接成字符串。
// 如果字符串使用+号拼接一个基本数据类型,那么这个数据也会被视为字符串进行拼接
System.out.println(1 + "HelloWorld");
System.out.println("1" + 1);
System.out.println("1" + 1 + 1);
System.out.println(1 + 1 + "1");
System.out.println("Hello" + "World" + "!");
}
}

Scanner键盘输入

Scanner使用时与前面的基本数据类型不太一样,主要有下面的一些步骤

  1. 导包
1
import java.util.Scanner;
  1. 创建Scanner对象
1
Scanner sc = new Scanner(System.in);
  1. 调用nextXxx()方法,获取指定的数据类型输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Scanner;
public class Demo9Scanner {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 接收键盘输入的一个整数,将这个整数赋值给num
int num = sc.nextInt();
double num2 = sc.nextDouble();
System.out.println("输入的整数是:" + num);
System.out.println("输入的小数是:" + num2);
// 字符串的输入有两种方式
// next()方法输入一个字符串,会把回车、空格视为结束符
String s1 = sc.next();
System.out.println("s1:" + s1);
// 接收上一个输入的回车,防止下面的nextLine无法正确执行
sc.nextLine();
// nextLine会以回车作为结束符。这里有一个bug:如果有连续的输入操作
// 上一个输入的回车会被nextLine接收,此时nextLine接收到了回车,认为输入完毕
// 就会导致nextLine像是没有执行一样
String s2 = sc.nextLine();
System.out.println("s2:" + s2);
// 没有nextChar方法

}
}

随堂练习

1、 通过键盘录入获取圆的半径,然后计算出该圆的周长和面积。

思路

  • 导包、创建Scanner对象
  • 提示输入圆的半径
  • 使用Scanner的nextDouble方法接收用户输入的半径
  • 计算圆的周长
  • 计算圆的面积
  • 输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.util.Scanner;
public class Demo10Circle {
public static void main(String[] args) {
// - 导包、创建Scanner对象
Scanner sc = new Scanner(System.in);
// - 提示输入圆的半径
System.out.println("请输入圆的半径:");
// - 使用Scanner的nextDouble方法接收用户输入的半径
double r = sc.nextDouble();
final double PI = 3.1415926535;
// - 计算圆的周长
double paremeter = 2 * r * PI;
// - 计算圆的面积
double area = r * r * PI;
// - 输出
System.out.println("半径为" + r + "的园周长是:" + paremeter);
System.out.println("半径为"+r+"的圆面积是:"+area);
}
}

基本数据的类型转换

在赋值运算或者算术运算时,要求参与计算的数据类型必须全部相同,否则就要进行数据类型转换

基本数据类型转换一般不包括 boolean

自动类型转换

自动类型转换(隐式类型转换)指的是容量小的数据可以直接赋值给容量大的数据类型,这个过程会自动发生数据类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Demo11Convert{
public static void main(String[] args) {
short num3 = 100;
final int num = num3;
long num2 = num;
System.out.println(num);
System.out.println(num2);
float f1 = 3.14F;
double f2 = f1;
System.out.println(f1);
System.out.println(f2);
double f3 = num2;
System.out.println(f3);
// 自动类型转换存在一些特例:**把整数常量(int类型)**直接赋值给byte、short、char是允许的,只要不超出它们能够表示的范围即可
byte num4 = 127;
char c1 = 97;
System.out.println(c1);
// 使用final修饰的,并且是在声明时直接赋值一个常量的最终变量
final int num6 = 100;
byte num5 = num6;
System.out.println(num5);
}
}

自动类型转换存在一些特例:把整数常量(int类型)直接赋值给byte、short、char是允许的,只要不超出它们能够表示的范围即可

需要注意的是:
如果两个数值参与算术运算

其中有一个数值是double,另一个数值就会被转换成double。

否则,如果有一个是float,另一个就会被转换成float

否则,如果有一个是long,另一个就会转换成long

否则,两个数都会被转换成int类型

2.自动类型转换原理

随堂练习

1、 byte b1 = 11; byte b2 = 12;byte sum = b1 + b2; 和int num1 = 100; int num2 = 300; int sum = num1 + num2;哪一个正确呢?

1
2
3
4
5
6
7
8
9
后面的正确
byte b1 = 11; byte b2 = 12;
这两行没有任何问题,问题出在下一行
byte sum = b1 + b2;
参与运算的b1和b2不是double、float、long,最终都会被转换成int类型
b1+b2的结果是int类型,且是变量,不能直接赋值给sum
而 int num1 = 100; int num2 = 300; int sum = num1 + num2;
则完成正确

2、 请问说出100000L*100000*100000和100000*100000*100000L的区别?

1
2
3
4
5
6
7
8
有区别
100000L*100000*100000
是先进行Long和int的运算,会把后面的数值转换成long类型,最终计算结果就是long类型。
再把计算结果和第三个数值进行计算,第三个数值也会被转换成long类型,最终计算结果就是准确的long类型。

100000*100000*100000L
先进行int 和int的计算,最终结果是int类型,这个过程发生了精度的丢失。之后再将int类型与long类型进行计算
int类型会转换成long类型,最终计算得结果,但是这个结果存在精度的不准确。

3、 int num1 = 90000; int num2 = 90000; int total = num1 * num2; 请问total的结果是多少?

1
2
结果是多少无法确定,因为这个过程中产生了精度的丢失
但是可以确定的一点是,肯定不是81亿

强制类型转换

强制类型转换(显示类型转换),主要用于强制性的将一个范围大的数值转换成另一个范围小的数值,这个过程中可能会存在精度的丢失

1
目标类型 变量 = (目标类型)源类型变量或常量;

代码演示

1
2
3
4
5
6
7
public class Demo13Convert {
public static void main(String[] args) {
int num = 128;
byte num2 = (byte)num;
System.out.println(num2);
}
}

在进行强制类型转换时,我们要能够尽量保证待转换数据不会超出目标类型的表示范围,否则就会出现精度的丢失

3.强制类型转换原理

运算符

算术运算符

二元运算符

操作两个数才能完成运算的运算符

运算符 备注
+ 加法,还可以应用于字符串的拼接
- 减法
* 乘法
/ 除法,整数之间的除法结果只会保留整数部分
如果想计算得小数结果,参与运算的数值必须至少有一个是小数
% 取模(求余)

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
public class Demo14Operator {
public static void main(String[] args) {
System.out.println(3+2); // 5
System.out.println(3-2); // 1
System.out.println(3*2); // 6
System.out.println(5/2); // 2
System.out.println(5.0/2); // 2.5
System.out.println(5%2); // 1
System.out.println(1+1+"1"+1+1+"1"+1); // 211111
System.out.println(1+1+"1"+(1+1)+"1"+1); // 21211
}
}

随堂练习

  1. 判断一个数是奇数还是偶数;

    1. 导包、创建Scanner对象
    2. 提示输入一个整数
    3. 键盘接收这个整数
    4. 数字与2取模,结果如果是0,就是偶数。如果是1就是奇数(if)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import java.util.Scanner;
    public class Demo16Operator {
    public static void main(String[] args) {
    // 1. 导包、创建Scanner对象
    Scanner sc = new Scanner(System.in);
    // 2. 提示输入一个整数
    System.out.println("请输入一个整数:");
    // 3. 键盘接收这个整数
    int num = sc.nextInt();
    // 4. 数字与2取模,结果如果是0,就是偶数。如果是1就是奇数(if)
    int result = num % 2;
    // 双等于是判断等于。单等于是进行赋值
    if(result == 0) {
    System.out.println(num + "是偶数");
    }else {
    System.out.println(num + "是奇数");
    }
    }
    }
  2. 获取三位整数的百位数、十位数和个位数。987

    1. 导包,创建Scanner对象
    2. 提示输入一个三位数
    3. 键盘接收这个三位整数
    4. 拿百位:将这个数字除以100,获得百位
    5. 拿后面两位数:将这个数字与100取模,获得的余数就是剩下的2位
    6. 拿十位:将后两位除以10,获得十位
    7. 拿个位:将后两位与10取模,获得个位
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    import java.util.Scanner;
    public class Demo17Operator {
    public static void main(String[] args) {
    // 1. 导包,创建Scanner对象
    Scanner sc = new Scanner(System.in);
    // 2. 提示输入一个三位数
    System.out.println("请输入一个三位整数:");
    // 3. 键盘接收这个三位整数
    int num = sc.nextInt();
    // 4. 拿百位:将这个数字除以100,获得百位
    int n1 = num / 100;
    // 5. 拿后面两位数:将这个数字与100取模,获得的余数就是剩下的2位
    int last = num % 100;
    // 6. 拿十位:将后两位除以10,获得十位
    int n2 = last / 10;
    // 7. 拿个位:将后两位与10取模,获得个位
    int n3 = last % 10;
    System.out.println("百位数:" + n1);
    System.out.println("十位数:" + n2);
    System.out.println("个位数:" + n3);
    }
    }

一元运算符

只操作一个数的运算符

用法 含义
int a = num++ 先将num的值赋值给a,再将num+1
int a = ++num 先将num+1,再将num的值赋值给a
int a = num– 先将num的值赋值给a,再将num-1
int a = –num 先将num-1,再将num的值赋值给a

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Demo18Operator {
public static void main(String[] args) {
int num = 5;
System.out.println("num=" + num);
int a = num++;
System.out.println("a="+a+", num="+num); // a=5, num=6
int b = ++num;
System.out.println("b="+b+", num="+num); // b=7, num=7
int c = num--;
System.out.println("c="+c+", num="+num); // c=7, num=6
int d = --num;
System.out.println("d="+d+", num="+num); // d=5, num=5
}
}

注意:一元运算符不强制要求必须有变量接收计算后的值,也就是说允许 num++++num 直接使用的形式,此时二者结果是相同的

【随堂练习】

  1. 可以对常量进行递增或递减操作吗?例如:5++或++5。
1
2
3
不可以
比如int a = 5++,先将5赋值给a,再将5+1
因为5是常量,不存在+1操作,所以不允许
  1. int num = 5; num = num++;请问代码执行后num的值为多少?
1
2
3
4
5
6
结果是5
++运算符的运算规则如下。
实际上,++运算符分成了好几步进行操作,这个过程中还使用到了临时的变量
第一步,创建临时的变量接收num的值:int tmp = num;
第二步:将num的值+1:num = num + 1;
第三步:将临时保管的值赋值给左边的变量
  1. int a = 3, b = 4; 求a++ / 3 + –b * 2 - a– % 6 + b++ * 3 - ++b的值。
1
2
3
4
5
6
7
8
public class Demo20Operator {
public static void main(String[] args) {
// int a = 3, b = 4; 求a++ / 3 + --b * 2 - a-- % 6 + b++ * 3 - ++b的值。
int a = 3, b = 4;
int num = a++ / 3 + --b * 2 - a-- % 6 + b++ * 3 - ++b;
System.out.println(num);
}
}

赋值运算符

= ,作用是将右边的值赋值给左边的变量

随堂练习

  1. 交换两个变量的值(用两种方式实现)。

方式一:使用临时变量

1
2
3
4
5
6
7
8
9
10
11
12
public class Demo21Operator {
public static void main(String[] args) {
// 交换两个变量的值:方式1
int a = 10;
int b = 20;
System.out.println("交换前:a="+a+",b="+b);
int tmp = b;
b = a;
a = tmp;
System.out.println("交换后:a="+a+",b="+b);
}
}

方式二:一加两减

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Demo21Operator {

public static void main(String[] args) {
// 交换两个变量的值:方式2
int a = 10;
int b = 20;
System.out.println("交换前:a="+a+",b="+b);
a = a + b;
b = a - b;
a = a - b;
System.out.println("交换后:a="+a+",b="+b);
}

}

4.一加两减交换值

如果只是数字的交换,建议使用第二种方式,如果是非数字交换,建议使用第一种

扩展赋值运算符

运算符 用法 等效表达式
+= a += b a = (数据类型)(a + b)
-= a -= b
*=
/=
%=

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Demo22Operator {

public static void main(String[] args) {
byte num1 = 10;
byte num2 = 20;
// num1 += num2;
num1 = (byte)(num1 + num2);
System.out.println(num1);
}

public static void main1(String[] args) {
int num = 10;
int num2 = 20;
num += num2;
System.out.println(num);
int num3 = 3;
num2 %= num3;
System.out.println(num2);
}
}

随堂练习

  1. 获取三个学生的成绩,并计算三个学生成绩的平均分。

    1. 导包、创建Scanner对象
    2. 提示输入第一名学生成绩
    3. 创建变量接收这个学生的成绩
    4. 将这个学生成绩统计到总和中
    5. 从2开始重复,总共输入3名学生成绩
    6. 输出总成绩,计算平均分
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import java.util.Scanner;
    public class Demo23Operator {
    public static void main(String[] args) {
    // 1. 导包、创建Scanner对象
    Scanner sc = new Scanner(System.in);
    // 2. 提示输入第一名学生成绩
    System.out.print("请输入第一名学生的成绩:");
    // 3. 创建变量接收这个学生的成绩
    double score1 = sc.nextDouble();
    // 4. 将这个学生成绩统计到总和中
    double sum = 0;
    sum += score1;
    // 5. 从2开始重复,总共输入3名学生成绩
    System.out.print("请输入第二名学生的成绩:");
    double score2 = sc.nextDouble();
    sum+=score2;
    System.out.print("请输入第三名学生的成绩:");
    double score3 = sc.nextDouble();
    sum += score3;
    // 6. 输出总成绩,计算平均分
    System.out.println("三名学生的总成绩为:" + sum);
    System.out.println("平均分为:" + (sum / 3));
    }
    }
  2. short num = 11; num = num + 1; 和short num = 11; num += 1;哪一个正确呢?

    1
    2
    3
    4
    后者正确。因为扩展赋值运算符包含了一个强转的过程
    所以即便是byte、short使用扩展赋值运算符也是允许的
    但是前者是short和int的计算,最终计算结果是int类型
    将int类型的变量直接赋值给short类型试试不合法的
  3. int sum += 30; 请问这行语句语法是否正确???

    1
    2
    3
    4
    5
    6
    7
    不正确
    int sum += 30
    等价于 int sum = sum + 30;
    赋值运算符是将右边的值赋值给左边的变量
    即:赋值运算符是从右往左运行的
    当计算右边的值时,sum这个变量还没有声明
    不能操作一个不存在的变量

关系运算符

关系运算符是用来进行比较运算的运算符,运算结果是boolean类型

运算符 含义
> 大于
< 小于
== 等于
>= 大于等于
<= 小于等于
!= 不等于

注意:判断等于是双等号,因为单等号是赋值运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.Scanner;
public class Demo24Operator {
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
System.out.println("请输入两个数字");
int num1 = sc.nextInt();
int num2 = sc.nextInt();
System.out.println(num1 > num2);
System.out.println(num1 < num2);
System.out.println(num1 == num2);
System.out.println(num1 >= num2);
System.out.println(num1 <= num2);
System.out.println(num1 != num2);
}
}

关系运算符一般结合选择结构、循环结构进行使用

逻辑运算符

参与逻辑运算的数据类型必须是boolean类型,运算结果也是boolean类型。逻辑运算符一般可以用于连接关系运算符

运算符 含义 描述
& 与运算 连接两个boolean类型
如果两个都是true,结果就是true
否则,结果就是false
| 或运算 连接两个boolean类型
如果两个都是false,结果就是false
否则,结果就是true
^ 异或运算 连接两个boolean类型
如果两边相同,结果就是false
如果两边不同,结果就是true
! 非运算 操作一个boolean类型|
如果原来是true,结果就是false
如果原来是false,结果就是true
&& 逻辑与/短路与 逻辑与的运算结果和 & 是一样的
&运算在第一个表达式为false时,就已经可以确定结果了
后面的表达式无论是true还是false,最终结果都是false
&&的作用就是当已经能够确定结果时,第二个表达式就不参与运算
|| 逻辑或/短路或 运算结果和 | 运算是一样的
如果第一个表达式已经是true时,就可以确定结果了
此时后面的表达式不会影响到最终结果
逻辑或运算下,后面的表达式就不会进行运算

代码演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

public class Demo25Operator {
public static void main(String[] args) {
// 与运算
System.out.println(true & true); // true
System.out.println(true & false); // false
System.out.println(false & true); // false
System.out.println(false & false); // false
System.out.println("=========");
// 或运算
System.out.println(true | true); // true
System.out.println(true | false); // true
System.out.println(false | true); // true
System.out.println(false | false); // false
System.out.println("=========");
// 异或运算
System.out.println(true ^ true); // false
System.out.println(true ^ false); // true
System.out.println(false ^ true); // true
System.out.println(false ^ false); // false
System.out.println("=========");
// 非运算
System.out.println(!true); // false
System.out.println(!false); // true
System.out.println("=========");
// 逻辑与
System.out.println(true && true); // true
System.out.println(true && false); // false
System.out.println(false && true); // false
System.out.println(false && false); // false
System.out.println("=========");
// 验证逻辑与
int num = 0;
boolean flag = (num = 3) > 4 && (num = 2) > 1;
System.out.println(flag);
System.out.println(num);
System.out.println("=========");
// 逻辑或
System.out.println(true || true); // true
System.out.println(true || false); // true
System.out.println(false || true); // true
System.out.println(false || false); // false

}
}

随堂练习

  1. 判断一个数是否在4(包含)~6(不包含)之间;

    1. 导包、创建Scanner对象
    2. 提示输入一个数字
    3. 键盘接收输入的这个数字
    4. 判断这个数字 >= 4 && < 6
  2. 判断一个数是否在4(不包含)~6(包含)之外;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.Scanner;
public class Demo26Operator {
public static void main(String[] agrs) {
// 1、判断一个数是否在4(包含)~6(不包含)之间;
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个数字:");
double num = sc.nextDouble();
// 4 <= num < 6 是不合法的语法
if(num >= 4 && num < 6) {
System.out.println(num + "在4(包含)~6(不包含)之间");
}else {
System.out.println(num + "不在4(包含)~6(不包含)之间");
}
// 2、判断一个数是否在4(不包含)~6(包含)之外;
// if(num < 4 || num >= 6) {
// 也可以先将题目要求的范围之外的表达出来,然后使用 ! 运算就是想要的结果
if(!(num >= 4 && num < 6)) {
System.out.println(num + "在4(不包含)~6(包含)之外");
}else {
System.out.println(num + "不在4(不包含)~6(包含)之外");
}
}
}

位运算

传统的加减乘除运算要先将数字转换成二进制,再对二进制进行加减乘除,转换过程存在性能的损耗。

位运算是直接对二进制进行的运算,不存在这个转换的过程。

运算符 含义 描述
<< 左移运算 将一个二进制左移n位,低位空出来的部分补0
左移n位,相当于把这个数字乘以n个2
>> 右移运算 将一个二进制右移n位,高位空出来的部分,正数补0,负数补1
右移n位,相当于把这个数字除以n个2
>>> 无符号右移 与右移运算符类似,但是不管值的正负,最终高位都补0
& 与运算 比较参与运算的两个数字二进制上的每一位
如果相同位上都是1,这一位的结果就是1
否则这一位就是0
| 或运算 比较参与运算的两个数字二进制上的每一位
如果相同位上都是0,这一位的结果就是0
否则这一位就是1
^ 异或运算 比较参与运算的两个数字二进制位上的每一位
如果相同,结果就是0,不同,结果就是1
~ 按位取反运算 原本二进制位是1,就改成0,原本是0

代码演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Demo27Operator {
public static void main(String[] args) {
// 左移
System.out.println(3 << 2);
System.out.println(4 << 1);
System.out.println(2 << 4);
System.out.println(3 << 2);
System.out.println(3 << 3);
System.out.println(3 << 4);
System.out.println(3 << 5);
System.out.println("========");
// 右移
System.out.println(50 >> 2);
System.out.println(512 >> 4);
System.out.println(-50 >> 2);
System.out.println("========");
System.out.println(50 >>> 2);
System.out.println(512 >>> 4);
System.out.println(-50 >>> 2);
System.out.println("========");
// 与运算
System.out.println(13 & 28);
System.out.println("========");
// 或运算
System.out.println(13 | 28);
System.out.println("========");
// 异或运算
System.out.println(13 ^ 28);
System.out.println("========");
// 按位取反运算
System.out.println(~13);

}
}

随堂练习

不用临时变量就完成交换两个变量的值。

规律:m ^ n ^ n == m

n ^ m ^ n == m

三次异或进行交换

1
2
3
4
5
6
7
8
9
10
11
public class Demo28Operator {
public static void main(String[] args) {
int a = 10;
int b = 20;
System.out.println("交换前:a="+a+",b="+b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("交换后:a="+a+",b="+b);
}
}

三目运算符

三目运算符也叫作三元运算符,它有三个组成部分

1
条件表达式 ? 表达式1: 表达式2

如果条件表达式为true,就执行表达式1,否则执行表达式2

  1. 获取两个数的最大值或最小值
    1. 导包,创建Scanner对象
    2. 提示输入
    3. 键盘接收输入的数字
    4. 使用三目运算符,如果a大于b,a就是最大值,否则b就是最大值
1
2
3
4
5
6
7
8
9
10
11
import java.util.Scanner;
public class Demo29Operator {
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
System.out.println("请输入两个整数:");
int num1 = sc.nextInt();
int num2 = sc.nextInt();
int max = num1 > num2 ? num1 : num2;
System.out.println("最大值是:" + max);
}
}