计算机存储与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

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

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

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

十六进制与十进制转换
十六转十:使用每一位(从右到左)上的数字*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 | int num1; |
语法2:
1 | 数据类型 变量名1, 变量名2, 变量名3; |
比如
1 | int n1, n2, n3, n4; |
赋值
变量一旦声明必须赋值,否则没有任何意义
方式1:在声明之后进行赋值
1 | 变量名 = 变量值; |
比如
1 | int num1; |
方式2:在声明时就进行赋值
1 | 数据类型 变量名 = 变量值; |
比如
1 | int num = 15; |
方式3:同时声明多个变量,同时进行赋值
1 | int num1 = 10, num2 = 20, num3 = 30; |
- 在方法中声明的变量必须要进行赋值,否则就没有什么意义
- 变量在于一个“变”,声明出来的变量内存空间就在那里,可以反复的往这个内存空间中存储数据
- 变量的命名必须遵守标识符规则,此外变量一般采用小驼峰规则
- 给变量进行赋值,数据类型必须与变量的类型一致
- 同一个代码块中(暂时理解成同一个方法),不能有多个同名的变量
- 可以用一个变量为另一个变量进行赋值
常量
常量指的是一个固定的值,比如1,’c’,true,”HelloWorld”
可以使用 final 关键字来修饰一个变量,此时这个变量就是常量
语法
1 | final 数据类型 常量名 = 常量值; |
代码演示
1 | public class Demo2Constant { |
注意
- 常量只能被赋值一次,赋值完毕后就不可以修改值
- 先声明,后赋值也可以是常量,但依然只能被赋值一次
- 常量一般由大写字母组成,单词间使用
_分隔
为什么要使用常量?
如果常量直接写死成一个数字,在程序中使用,后期想改这个常量的值,就需要修改大量的代码,有可能会修改到非常量的部分。这种“写死的值”,一般称之为魔法值。开发中应当避免使用魔法值。
如果使用final修饰一个常量,我们可以将这个常量统一进行管理,之后其他地方需要使用到这个值,直接用常量名即可,后续如果想修改常量值,直接修改一处的值,其他地方全部都生效
数据类型
Java的数据类型分为 基本类型 和 引用类型
基本数据类型
数值型
byte、short、int、long、float、double
其中,前四个是正数,后2个是浮点数,并且6个数据类型的表示范围从小到大排列


整数型演示
1 | public class Demo3Number { |
浮点数演示
1 | public static void main(String[] args) { |
注意
- 数据类型使用时不能超出范围
- Java中直接写死一个整数常量,默认是int类型
- Java中想要表示long类型的整数,要在数字后面加上 L 或者 l,推荐使用L
- Java中直接写死一个小数常量,默认是double类型
- 如果想表示float类型的小数,可以在数字后面加上 f 或者 F
布尔型
布尔型只有两个值:true和false。true代表真,false代表假
1 | public class Demo4Boolean { |
字符型
字符型在内存中只占用2个字节,字符就是用单引号包裹起来的单个内容,比如 'A','1','你'
1 | public class Demo5Char { |
char类型和int类型在一定范围内是可以互相转换的。

1 | public class Demo6Unicode { |
转义字符
1 | public class Demo7Char { |
引用数据类型
String字符串
使用双引号 "" 包裹起来的内容称之为字符串,双引号中的内容可以有任意多个,也可以为空。
字符串的使用方式与基本数据类型基本一致,但需要注意的是它是引用数据类型。
1 | public class Demo8String { |
Scanner键盘输入
Scanner使用时与前面的基本数据类型不太一样,主要有下面的一些步骤
- 导包
1 | import java.util.Scanner; |
- 创建Scanner对象
1 | Scanner sc = new Scanner(System.in); |
- 调用nextXxx()方法,获取指定的数据类型输入
1 | import java.util.Scanner; |
随堂练习
1、 通过键盘录入获取圆的半径,然后计算出该圆的周长和面积。
思路
- 导包、创建Scanner对象
- 提示输入圆的半径
- 使用Scanner的nextDouble方法接收用户输入的半径
- 计算圆的周长
- 计算圆的面积
- 输出
1 | import java.util.Scanner; |
基本数据的类型转换
在赋值运算或者算术运算时,要求参与计算的数据类型必须全部相同,否则就要进行数据类型转换
基本数据类型转换一般不包括 boolean
自动类型转换
自动类型转换(隐式类型转换)指的是容量小的数据可以直接赋值给容量大的数据类型,这个过程会自动发生数据类型转换
1 | public class Demo11Convert{ |
自动类型转换存在一些特例:把整数常量(int类型)直接赋值给byte、short、char是允许的,只要不超出它们能够表示的范围即可
需要注意的是:
如果两个数值参与算术运算
其中有一个数值是double,另一个数值就会被转换成double。
否则,如果有一个是float,另一个就会被转换成float
否则,如果有一个是long,另一个就会转换成long
否则,两个数都会被转换成int类型

随堂练习
1、 byte b1 = 11; byte b2 = 12;byte sum = b1 + b2; 和int num1 = 100; int num2 = 300; int sum = num1 + num2;哪一个正确呢?
1 | 后面的正确 |
2、 请问说出100000L*100000*100000和100000*100000*100000L的区别?
1 | 有区别 |
3、 int num1 = 90000; int num2 = 90000; int total = num1 * num2; 请问total的结果是多少?
1 | 结果是多少无法确定,因为这个过程中产生了精度的丢失 |
强制类型转换
强制类型转换(显示类型转换),主要用于强制性的将一个范围大的数值转换成另一个范围小的数值,这个过程中可能会存在精度的丢失
1 | 目标类型 变量 = (目标类型)源类型变量或常量; |
代码演示
1 | public class Demo13Convert { |
在进行强制类型转换时,我们要能够尽量保证待转换数据不会超出目标类型的表示范围,否则就会出现精度的丢失

运算符
算术运算符
二元运算符
操作两个数才能完成运算的运算符
| 运算符 | 备注 | |
|---|---|---|
| + | 加法,还可以应用于字符串的拼接 | |
| - | 减法 | |
| * | 乘法 | |
| / | 除法,整数之间的除法结果只会保留整数部分 如果想计算得小数结果,参与运算的数值必须至少有一个是小数 |
|
| % | 取模(求余) |
代码示例
1 | public class Demo14Operator { |
随堂练习
判断一个数是奇数还是偶数;
- 导包、创建Scanner对象
- 提示输入一个整数
- 键盘接收这个整数
- 数字与2取模,结果如果是0,就是偶数。如果是1就是奇数(if)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import 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 + "是奇数");
}
}
}获取三位整数的百位数、十位数和个位数。987
- 导包,创建Scanner对象
- 提示输入一个三位数
- 键盘接收这个三位整数
- 拿百位:将这个数字除以100,获得百位
- 拿后面两位数:将这个数字与100取模,获得的余数就是剩下的2位
- 拿十位:将后两位除以10,获得十位
- 拿个位:将后两位与10取模,获得个位
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import 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 | public class Demo18Operator { |
注意:一元运算符不强制要求必须有变量接收计算后的值,也就是说允许 num++,++num 直接使用的形式,此时二者结果是相同的
【随堂练习】
- 可以对常量进行递增或递减操作吗?例如:5++或++5。
1 | 不可以 |
- int num = 5; num = num++;请问代码执行后num的值为多少?
1 | 结果是5 |
- int a = 3, b = 4; 求a++ / 3 + –b * 2 - a– % 6 + b++ * 3 - ++b的值。
1 | public class Demo20Operator { |
赋值运算符
= ,作用是将右边的值赋值给左边的变量
随堂练习
- 交换两个变量的值(用两种方式实现)。
方式一:使用临时变量
1 | public class Demo21Operator { |
方式二:一加两减
1 | public class Demo21Operator { |

如果只是数字的交换,建议使用第二种方式,如果是非数字交换,建议使用第一种
扩展赋值运算符
| 运算符 | 用法 | 等效表达式 |
|---|---|---|
| += | a += b | a = (数据类型)(a + b) |
| -= | a -= b | |
| *= | ||
| /= | ||
| %= |
代码示例
1 | public class Demo22Operator { |
随堂练习
获取三个学生的成绩,并计算三个学生成绩的平均分。
- 导包、创建Scanner对象
- 提示输入第一名学生成绩
- 创建变量接收这个学生的成绩
- 将这个学生成绩统计到总和中
- 从2开始重复,总共输入3名学生成绩
- 输出总成绩,计算平均分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import 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));
}
}short num = 11; num = num + 1; 和short num = 11; num += 1;哪一个正确呢?
1
2
3
4后者正确。因为扩展赋值运算符包含了一个强转的过程
所以即便是byte、short使用扩展赋值运算符也是允许的
但是前者是short和int的计算,最终计算结果是int类型
将int类型的变量直接赋值给short类型试试不合法的int sum += 30; 请问这行语句语法是否正确???
1
2
3
4
5
6
7不正确
int sum += 30
等价于 int sum = sum + 30;
赋值运算符是将右边的值赋值给左边的变量
即:赋值运算符是从右往左运行的
当计算右边的值时,sum这个变量还没有声明
不能操作一个不存在的变量
关系运算符
关系运算符是用来进行比较运算的运算符,运算结果是boolean类型
| 运算符 | 含义 |
|---|---|
| > | 大于 |
| < | 小于 |
| == | 等于 |
| >= | 大于等于 |
| <= | 小于等于 |
| != | 不等于 |
注意:判断等于是双等号,因为单等号是赋值运算符
1 | import java.util.Scanner; |
关系运算符一般结合选择结构、循环结构进行使用
逻辑运算符
参与逻辑运算的数据类型必须是boolean类型,运算结果也是boolean类型。逻辑运算符一般可以用于连接关系运算符
| 运算符 | 含义 | 描述 |
|---|---|---|
| & | 与运算 | 连接两个boolean类型 如果两个都是true,结果就是true 否则,结果就是false |
| | | 或运算 | 连接两个boolean类型 如果两个都是false,结果就是false 否则,结果就是true |
| ^ | 异或运算 | 连接两个boolean类型 如果两边相同,结果就是false 如果两边不同,结果就是true |
| ! | 非运算 | 操作一个boolean类型| 如果原来是true,结果就是false 如果原来是false,结果就是true |
| && | 逻辑与/短路与 | 逻辑与的运算结果和 & 是一样的 &运算在第一个表达式为false时,就已经可以确定结果了 后面的表达式无论是true还是false,最终结果都是false &&的作用就是当已经能够确定结果时,第二个表达式就不参与运算 |
| || | 逻辑或/短路或 | 运算结果和 | 运算是一样的 如果第一个表达式已经是true时,就可以确定结果了 此时后面的表达式不会影响到最终结果 逻辑或运算下,后面的表达式就不会进行运算 |
代码演示
1 |
|
随堂练习
判断一个数是否在4(包含)~6(不包含)之间;
- 导包、创建Scanner对象
- 提示输入一个数字
- 键盘接收输入的这个数字
- 判断这个数字
>= 4 && < 6
判断一个数是否在4(不包含)~6(包含)之外;
1 | import java.util.Scanner; |
位运算
传统的加减乘除运算要先将数字转换成二进制,再对二进制进行加减乘除,转换过程存在性能的损耗。
位运算是直接对二进制进行的运算,不存在这个转换的过程。
| 运算符 | 含义 | 描述 |
|---|---|---|
| << | 左移运算 | 将一个二进制左移n位,低位空出来的部分补0 左移n位,相当于把这个数字乘以n个2 |
| >> | 右移运算 | 将一个二进制右移n位,高位空出来的部分,正数补0,负数补1 右移n位,相当于把这个数字除以n个2 |
| >>> | 无符号右移 | 与右移运算符类似,但是不管值的正负,最终高位都补0 |
| & | 与运算 | 比较参与运算的两个数字二进制上的每一位 如果相同位上都是1,这一位的结果就是1 否则这一位就是0 |
| | | 或运算 | 比较参与运算的两个数字二进制上的每一位 如果相同位上都是0,这一位的结果就是0 否则这一位就是1 |
| ^ | 异或运算 | 比较参与运算的两个数字二进制位上的每一位 如果相同,结果就是0,不同,结果就是1 |
| ~ | 按位取反运算 | 原本二进制位是1,就改成0,原本是0 |
代码演示
1 | public class Demo27Operator { |
随堂练习
不用临时变量就完成交换两个变量的值。
规律:m ^ n ^ n == m
n ^ m ^ n == m
三次异或进行交换
1 | public class Demo28Operator { |
三目运算符
三目运算符也叫作三元运算符,它有三个组成部分
1 | 条件表达式 ? 表达式1: 表达式2 |
如果条件表达式为true,就执行表达式1,否则执行表达式2
- 获取两个数的最大值或最小值
- 导包,创建Scanner对象
- 提示输入
- 键盘接收输入的数字
- 使用三目运算符,如果a大于b,a就是最大值,否则b就是最大值
1 | import java.util.Scanner; |