关键字 、保留字与标识符
关键字(keyword)
定义:被 Java 语言赋予了特殊含义,用做专门用途的字符串(或单词)
HelloWorld 中,出现的关键字有 class
、public
、 static
、 void
等,这些单词已经被 Java 定义好了
特点:全部关键字都是小写字母。
关键字比较多,不需要死记硬背,学到哪里记到哪里即可。
官方地址:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
说明:
- 关键字一共 50 个,其中
const
和goto
是保留字(reserved word)。 true
、false
、null
不在其中,它们看起来像关键字,其实是字面量,表示特殊的布尔值和空值。
标识符(identifier)
Java 中变量、方法、类等要素命名时使用的字符序列,称为标识符。
技巧:凡是自己可以起名字的地方都叫标识符。
标识符的命名规则(必须遵守的硬性规定):
- 由 26 个英文字母大小写、0-9、
_
或$
组成 - 数字不可以开头
- 不可以使用关键字和保留字,但能包含关键字和保留字
- Java 中严格区分大小写,长度无限制
- 标识符不能包含空格
标识符的命名规范(建议遵守的软性要求,否则工作时容易被鄙视):
- 包名:多单词组成时所有字母都小写:
xxxyyyzzz
- 例如:
java.lang
、com.atguigu.bean
- 例如:
- 类名、接口名:多单词组成时,所有单词的首字母大写:
XxxYyyZzz
- 例如:
HelloWorld
、String
、System
- 例如:
- 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:
xxxYyyZzz
- 例如:
age
、bookName
、main
、binarySearch
、getName
- 例如:
- 常量名:所有字母都大写。多单词时每个单词用下划线连接:
XXX_YYY_ZZZ
- 例如:
MAX_VALUE
、PI
、DEFAULT_CAPACITY
- 例如:
在起名字时,为了提高阅读性,要尽量有意义,“见名知意”。
变量和数据类型
变量
变量的概念:
- 内存中的一个存储区域,该区域的数据可以在同一类型范围内不断变化
- 变量的构成包含三个要素:数据类型、变量名、存储的值
- Java 中变量声明的格式:
数据类型 变量名 = 变量值;
变量的作用:用于在内存中保存数据
使用变量注意:
- Java 中每个变量必须先声明,后使用
- 使用变量名来访问这块区域的数据
- 变量的作用域:其定义所在的一对
{}
内 - 变量只有在其作用域内才有效。出了作用域,变量不可以再被调用
- 同一个作用域内,不能定义重名的变量
变量的数据类型
Java 中变量的数据类型分为两大类:
- 基本数据类型:包括整数类型、浮点数类型、字符类型、布尔类型
- 引用数据类型:包括数组、类、接口、枚举、注解、记录
变量的使用
步骤 1:声明变量
格式:数据类型 变量名;
举例:
// 声明一个整数类型的年龄
int age;
// 声明一个小数类型的体重
double weight;
// 声明一个单字符类型的性别
char gender;
// 声明一个布尔类型的婚姻状态
boolean marry;
// 声明一个字符串类型的姓名
String name;
// 声明多个同类型的变量
int a, b, c; // 表示 a, b, c 三个变量都是 int 类型
步骤 2:变量的赋值
给变量赋值,就是把“值”存到该变量代表的内存空间中。同时,给变量赋的值类型必须与变量声明的类型一致或兼容。
变量赋值的语法格式:变量名 = 值;
举例 1:可以使用合适类型的常量值给已经声明的变量赋值
age = 18;
weight = 109;
gender = '女';
举例 2:可以使用其他变量或者表达式给变量赋值
int m = 1;
int n = m;
int x = 1;
int y = 2;
int z = 2 * x + y;
举例 3:变量可以反复赋值
// 先声明,后初始化
char gender;
gender = '女';
// 给变量重新赋值,修改 gender 变量的值
gender = '男';
System.out.println("gender = " + gender); // gender = 男
举例 4:也可以将变量的声明和赋值一并执行
boolean isBeauty = true;
String name = "迪丽热巴";
基本数据类型
整数类型:byte
、short
、int
、long
Java 各整数类型有固定的表数范围和字段长度,不受具体操作系统的影响,以保证 Java 程序的可移植性。
- 定义
long
类型的变量,赋值时需要以”l
”或”L
”作为后缀。 - Java 程序中变量通常声明为
int
型,除非不足以表示较大的数,才使用long
。 - Java 的整型常量默认为
int
型 `。
补充 :计算机存储单位
- 字节(Byte):是计算机用于计量存储容量的基本单位,一个字节等于 8 bit。
- 位(bit):是数据存储的最小单位。二进制数系统中,每个 0 或 1 就是一个位,叫做 bit(比特),其中 8 bit 就称为一个字节(Byte)。
- 转换关系:
- 8 bit = 1 Byte
- 1024 Byte = 1 KB
- 1024 KB = 1 MB
- 1024 MB = 1 GB
- 1024 GB = 1 TB
- 1024 TB = 1 PB
浮点类型:float
、double
与整数类型类似,Java 浮点类型也有固定的表数范围和字段长度,不受具体操作系统的影响。
- 浮点型常量有两种表示形式:
- 十进制数形式。如:
5.12
、512.0f
、.512
(必须有小数点) - 科学计数法形式。如:
5.12e2
、512E2
、100E-2
- 十进制数形式。如:
float
:单精度,尾数可以精确到 7 位有效数字。很多情况下,精度很难满足需求。double
:双精度,精度是float
的两倍。通常采用此类型。- 定义
float
类型的变量,赋值时需要以”f
”或”F
”作为后缀。 - Java 的浮点型常量默认为
double
型。
关于浮点型精度的说明:
- 并不是所有的小数都能可以精确的用二进制浮点数表示。二进制浮点数不能精确的表示
0.1
、0.01
、0.001
这样 10 的负次幂。 - 浮点类型
float
、double
的数据不适合在不容许舍入误差的金融计算领域。如果需要精确数字计算或保留指定位数的精度,需要使用BigDecimal
类。 - 测试用例:
// 测试1:(解释见章末企业真题:为什么 0.1 + 0.2 不等于 0.3)
System.out.println(0.1 + 0.2); // 0.30000000000000004
// 测试2:
float ff1 = 123123123f;
float ff2 = ff1 + 1;
System.out.println(ff1); // 1.2312312E8
System.out.println(ff2); // 1.2312312E8
System.out.println(ff1 == ff2); // true
字符类型:char
char
型数据用来表示通常意义上“字符”(占 2 字节)
Java 中的所有字符都使用 Unicode 编码,故一个字符可以存储一个字母、一个汉字、或其他书面语的一个字符。
字符型变量的三种表现形式:
- 形式 1:使用单引号(
'
)括起来的单个字符。- 例如:
char c1 = 'a';
、char c2 = '中';
、char c3 = '9';
- 例如:
- 形式 2:直接使用 Unicode 值来表示字符型常量:
\uXXXX
。其中,XXXX 代表一个十六进制整数。- 例如:
\u0023
表示'#'
。
- 例如:
- 形式 3:Java 中还允许使用转义字符
\
来将其后的字符转变为特殊字符型常量。- 例如:
char c3 = '\n';
,'\n'
表示换行符
- 例如:
转义字符 | 说明 | Unicode 表示方式 |
---|---|---|
\n | 换行符 | \u000a |
\t | 制表符 | \u0009 |
\" | 双引号 | \u0022 |
\' | 单引号 | \u0027 |
\\ | 反斜线 | \u005c |
\b | 退格符 | \u0008 |
\r | 回车符 | \u000d |
char
类型是可以进行运算的。因为它都对应有 Unicode 码,可以看做是一个数值。
布尔类型:boolean
boolean
类型用来判断逻辑条件,一般用于流程控制语句中:
if
条件控制语句;while
循环控制语句;for
循环控制语句;do-while
循环控制语句;
boolean
类型数据只有两个值:true
、false
不可以使用 0 或非 0 的整数替代 false
和 true
,这点和 C 语言不同。
拓展:Java 虚拟机中没有任何供 boolean
值专用的字节码指令,Java 语言表达所操作的 boolean
值,在编译之后都使用 java 虚拟机中的 int
数据类型来代替:true
用 1 表示,false
用 0 表示。——《Java 虚拟机规范 8 版》
boolean isFlag = true;
if (isFlag) {
// true 分支
} else {
// false 分支
}
经验之谈:
Less is More!建议不要这样写:
if (isFlag == true)
,只有新手才如此。关键也很容易写错成if (isFlag = true)
,这样就变成赋值isFlag
为true
,而不是判断!老鸟的写法是if (isFlag)
或者if (!isFlag)
。
基本数据类型变量间运算规则
在 Java 程序中,不同的基本数据类型变量的值经常需要进行相互转换(7 种,一般 boolean
类型不需要转换)
转换的方式有两种:自动类型提升和强制类型转换。
自动类型提升
规则:将取值范围小(或容量小)的类型自动提升为取值范围大(或容量大)的类型 。
基本数据类型的转换规则如图所示:
- 当把存储范围小的值(常量值、变量的值、表达式计算的结果值)赋值给了存储范围大的变量时
int i = 'A'; // char 自动升级为 int,其实就是把字符的编码值赋值给 i 变量了
double d = 10; // int 自动升级为 double
long num = 1234567; // 右边的整数常量值如果在 int 范围,编译和运行都可以通过,这里涉及到数据类型转换
// byte bigB = 130; // 错误,右边的整数常量值超过 byte 范围
long bigNum = 12345678912L; // 右边的整数常量值如果超过 int 范围,必须加 L,显式表示 long 类型。否则编译不通过
- 当存储范围小的数据类型与存储范围大的数据类型变量一起混合运算时,会按照其中最大的类型运算
int i = 1;
byte b = 1;
double d = 1.0;
double sum = i + b + d; // 混合运算,升级为 double
- 当
byte
、short
、char
数据类型的变量进行算术运算时,按照int
类型处理
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2; // 编译报错,b1 + b2 自动升级为 int
char c1 = '0';
char c2 = 'A';
int i = c1 + c2; // 至少需要使用 int 类型来接收
System.out.println(c1 + c2); // 113
强制类型转换
将 3.14
赋值到 int
类型变量会发生什么?产生编译失败,肯定无法赋值
int i = 3.14; // 编译报错
想要赋值成功,只有通过强制类型转换,将 double
类型强制转换成 int
类型才能赋值。
规则:将取值范围大(或容量大)的类型强制转换成取值范围小(或容量小)的类型。
自动类型提升是 Java 自动执行的,而强制类型转换是自动类型提升的逆运算,需要我们自己手动执行。
转换格式:
数据类型1 变量名 = (数据类型1) 被强转数据值; // ()中的数据类型必须<=变量值的数据类型
- 当把存储范围大的值(常量值、变量的值、表达式计算的结果值)强制转换为存储范围小的变量时,可能会损失精度或溢出
int i = (int) 3.14; // 损失精度
double d = 1.2;
int num = (int) d; // 损失精度
int i = 200;
byte b = (byte) i; // 溢出
- 当某个值想要提升数据类型时,也可以使用强制类型转换。这种情况的强制类型转换是没有风险的,通常省略
int i = 1;
int j = 2;
double bigger = (double) (i / j);
- 声明
long
类型变量时,可以出现省略后缀的情况。float
则不同
long l1 = 123L;
long l2 = 123; // 如何理解呢?可以看做是 int 类型的 123 自动类型提升为 long 类型
// long l3 = 123123123123; // 报错,因为 123123123123 超出了 int 的范围
long l4 = 123123123123L;
// float f1 = 12.3; // 报错,因为 12.3 是 double,不能自动转换为 float 类型
float f2 = 12.3F;
float f3 = (float) 12.3;
练习:判断是否能通过编译
// 1
short s = 5;
s = s - 2; // no
// 2
byte b = 3;
b = b + 4; // no
b = (byte) (b + 4); // yes
// 3
char c = 'a';
int i = 5;
float d = .314F;
double result = c + i + d; // yes
// 4
byte b = 5;
short s = 3;
short t = s + b; // no: s + b 是 int 类型
问答:为什么标识符的声明规则里要求不能数字开头?
// 如果允许数字开头,则如下的声明编译就可以通过
int 123L = 12;
// 进而,如下的声明中 l 的值到底是 123?还是变量 123L 对应的取值 12 呢?出现歧义了
long l = 123L;
基本数据类型与 String
的运算
字符串类型:String
String
不是基本数据类型,属于引用数据类型
使用一对 ""
来表示一个字符串,内部可以包含任意个字符(0 个、1 个或多个)
声明方式与基本数据类型类似。例如:String str = "尚硅谷"
运算规则
任意八种基本数据类型的数据与 String
类型只能进行连接 “+
” 运算,且结果一定也是 String
类型
System.out.println("" + 1 + 2); // 12
int num = 10;
boolean b1 = true;
String s1 = "abc";
String s2 = s1 + num + b1;
System.out.println(s2); // abc10true
// String s3 = num + b1 + s1; // 编译不通过,因为 int 类型不能与 boolean 运算
String s4 = num + (b1 + s1); // 编译通过
String
类型不能通过强制类型 ()
转换,转为其他的类型
String str = "123";
int num = (int) str; // 错误的
int num = Integer.parseInt(str); // 正确的,后面才能讲到,借助包装类的方法才能转
计算机底层如何存储数据
计算机世界中只有二进制,计算机中存储和运算的所有数据都要转为二进制。包括数字、字符、图片、声音、视频等。
进制的分类
class BinaryTest {
public static void main(String[] args) {
int num1 = 123; // 十进制
int num2 = 0b101; // 二进制
int num3 = 0127; // 八进制
int num4 = 0x12aF; // 十六进制
System.out.println(num1);
System.out.println(num2);
System.out.println(num3);
System.out.println(num4);
}
}
二进制的由来
二进制,是计算技术中广泛采用的一种数制,由德国数理哲学大师莱布尼茨于 1679 年发明。
二进制数据是用 0 和 1 两个数码来表示的数。它的基数为 2,进位规则是“逢二进一”。
二进制广泛应用于我们生活的方方面面。比如,广泛使用的摩尔斯电码(Morse Code),它由两种基本信号组成:短促的点信号“·
”,读“滴”;保持一定时间的长信号“—
”,读“嗒”。然后,组成了 26 个字母,从而拼写出相应的单词。
二进制如何表示整数?
计算机数据的存储使用二进制补码形式存储,并且最高位是符号位。
-
非负数:最高位是 0
-
负数:最高位是 1
-
非负数的补码与反码、原码一样,称为“三码合一”
-
负数的补码与反码、原码不一样:
- 负数的原码:把十进制转为二进制,然后最高位设置为 1
- 负数的反码:在原码的基础上,最高位不变,其余位取反(0 变 1、1 变 0)
- 负数的补码:反码 +1
25:
原码:0001 1001
反码:0001 1001
补码:0001 1001
-25:
原码:1001 1001
反码:1110 0110
补码:1110 0111
一个字节可以存储的整数范围是多少?
1 个字节:8 位
0000 0001 ~ 0111 111 ==> 1~127
1000 0001 ~ 1111 1111 ==> -127 ~ -1
0000 0000 ==> 0
1000 0000 ==> -128(特殊规定)= -127 - 1
八进制与十六进制
- 八进制:3 个二进制位表示一个八进制位
- 十六进制:4 个二进制位表示一个十六进制位
运算符
运算符是一些特殊的符号,用以表示数据的运算、赋值和比较等。
运算符的分类:
- 按照功能分为:算术运算符、赋值运算符、关系运算符、逻辑运算符、位运算符、条件运算符、Lambda 运算符
分类 | 运算符 |
---|---|
算术运算符(7 个) | + 、- 、* 、/ 、% 、++ 、-- |
赋值运算符(12 个) | = 、+= 、-= 、*= 、/= 、%= 、>>= 、<<= 、>>>= 、&= 、丨= 、^= |
关系运算符(6 个) | > 、>= 、< 、<= 、== 、!= |
逻辑运算符(6 个) | & 、丨 、^ 、! 、&& 、丨丨 |
位运算符(7 个) | & 、丨 、^ 、~ 、<< 、>> 、>>> |
条件运算符(1 个) | 条件表达式 ? 结果1 : 结果2 |
Lambda 运算符(1 个) | -> |
- 按照操作数个数分为:一元运算符(单目运算符)、二元运算符(双目运算符)、三元运算符 (三目运算符)
分类 | 运算符 |
---|---|
一元运算符(单目运算符) | 正号(+ )、负号(- )、++ 、-- 、! 、~ |
二元运算符(双目运算符) | 除了一元和三元运算符剩下的都是二元运算符 |
三元运算符 (三目运算符) | 条件表达式 ? 结果1 : 结果2 |
算术运算符
“+
”号的两种用法:
- 对于
+
两边都是数值的话,+
就是加法的意思 - 对于
+
两边至少有一边是字符串的话,+
就是拼接的意思
自加自减运算:
理解:++
运算,表示自增 1。同理,--
运算,表示自减 1。
- 单独使用
- 变量在单独运算的时候,变量前
++
和变量后++
是没有区别的。 - 变量前
++
:例如++a
- 变量后
++
:例如a++
- 变量在单独运算的时候,变量前
- 复合使用
- 和其他变量放在一起使用或者和输出语句放在一起使用,前
++
和后++
就产生了不同。 - 变量前
++
:变量先自增 1,然后再运算。 - 变量后
++
:变量先运算,然后再自增 1。
- 和其他变量放在一起使用或者和输出语句放在一起使用,前
赋值运算符
当 =
两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理
支持连续赋值
int i1 = 10;
long l1 = i1; // 自动类型转换
byte bb1 = (byte) i1; // 强制类型转换
// 连续赋值的写法
int a2, b2;
a2 = b2 = 10;
int a3 = 10, b3 = 20;
// 举例说明 +=、-=、*=、/=、%=
int m1 = 10;
m1 += 5; // 类似于 m1 = m1 + 5 的操作,但不等同于
// 写法1:推荐
short s1 = 10;
s1 += 2; // 编译通过,因为在得到 int 类型的结果后,JVM 自动完成一步强制类型转换,将 int 类型强转成 short
// 写法2:
short s2 = 10;
// s2 = s2 + 2; // 编译报错,因为将 int 类型的结果赋值给 short 类型的变量时,可能损失精度
s2 = (short) (s2 + 2);
关系运算符
比较运算符的结果都是 boolean
型,也就是要么是 true
,要么是 false
。
>
、<
、>=
、<=
:只适用于基本数据类型(除boolean
类型之外)==
、!=
:适用于基本数据类型和引用数据类型
比较运算符 ==
不能误写成 =
逻辑运算符
逻辑运算符,操作的都是 boolean
类型的变量或常量,而且运算得结果也是 boolean
类型的值。
运算符说明:
&
和&&
:表示”且”关系,当符号左右两边布尔值都是true
时,结果才能为true
;否则为false
|
和||
:表示”或”关系,当符号两边布尔值有一边为true
时,结果为true
;当两边都为false
时,结果为false
!
:表示”非”关系,当变量布尔值为true
时,结果为false
;当变量布尔值为false
时,结果为true
^
:“异或”,当符号左右两边布尔值不同时,结果为true
。当两边布尔值相同时,结果为false
- 理解:异或,追求的是“异”!
- 逻辑运算符用于连接布尔型表达式,在 Java 中不可以写成
3 < x < 6
,应该写成x > 3 && x < 6
&&
和||
:短路性
位运算符
位运算符的运算过程都是基于二进制的补码运算
条件运算符
条件表达式是 boolean
类型的结果,根据 boolean
的值选择表达式 1 或表达式 2
如果运算后的结果赋给新的变量,要求表达式 1 和表达式 2 为同种或兼容的类型
public static void main(String[] args) {
int i = (1==2 ? 100 : 200);
System.out.println(i); // 200
boolean marry = false;
System.out.println(marry ? "已婚" : "未婚");
double d1 = (m1 > m2) ? 1 : 2.0;
System.out.println(d1);
int num = 12;
System.out.println(num > 0 ? true : "num 非正数");
}
运算符优先级
运算符有不同的优先级,所谓优先级就是在表达式运算中的运算符顺序。
优先级 | 运算符说明 | Java 运算符 |
---|---|---|
1 | 括号 | () 、[] 、{} |
2 | 正负号 | + 、- |
3 | 单元运算符 | ++ 、-- 、~ 、! |
4 | 乘法、除法、求余 | * 、/ 、% |
5 | 加法、减法 | + 、- |
6 | 移位运算符 | << 、>> 、>>> |
7 | 关系运算符 | < 、<= 、>= 、> 、instanceof |
8 | 等价运算符 | == 、!= |
9 | 按位与 | & |
10 | 按位异或 | ^ |
11 | 按位或 | 丨 |
12 | 条件与 | && |
13 | 条件或 | 丨丨 |
14 | 三元运算符 | ? : |
15 | 赋值运算符 | = 、+= 、-= 、*= 、/= 、%= |
16 | 位赋值运算符 | &= 、丨= 、<<= 、>>= 、>>>= |
开发建议:
- 不要过多的依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用
()
来控制表达式的执行顺序 - 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。例如:
(num1 + num2) * 2 > num3 && num2 > num3 ? num3 : num1 + num2;
关于字符集
字符集
编码与解码:计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。
- 字符编码(Character Encoding): 就是一套自然语言的字符与二进制数之间的对应规则。
- 字符集:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。
ASCII 码
ASCII 码(American Standard Code for Information Interchange,美国信息交换标准代码):上个世纪 60 年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码。
ASCII 码用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
基本的 ASCII 字符集,使用 7 位(bits)表示一个字符(最前面的 1 位统一规定为 0),共 128 个字符。比如:空格“SPACE”是 32(二进制 00100000),大写的字母 A 是 65(二进制 01000001)。
缺点:不能表示所有字符。
ISO-8859-1 字符集
拉丁码表,别名 Latin-1,用于显示欧洲使用的语言,包括荷兰语、德语、意大利语、葡萄牙语等
ISO-8859-1 使用单字节编码,兼容 ASCII 编码。
GBXXX 字符集
GB 就是国标的意思,是为了编解码中文而设计的一套字符集。
- GB2312:简体中文码表。一个小于 127 的字符的意义与原来相同,即向下兼容 ASCII 码。但两个大于 127 的字符连在一起时,就表示一个汉字,这样大约可以组合了包含 7000 多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,这就是常说的”全角”字符,而原来在 127 号以下的那些符号就叫”半角”字符了。
- GBK:最常用的中文码表。是在 GB2312 标准基础上的扩展规范,使用了双字节编码方案,共收录了 21003 个汉字,完全兼容 GB2312 标准,同时支持繁体汉字以及日韩汉字等。
- GB18030:最新的中文码表。收录汉字 70244 个,采用多字节编码,每个字可以由 1 个、2 个或 4 个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
Unicode 码
Unicode 编码为表达任意语言的任意字符而设计,也称为统一码、标准万国码。Unicode 将世界上所有的文字用 2 个字节统一进行编码,为每个字符设定唯一的二进制编码,以满足跨语言、跨平台进行文本处理的要求。
Unicode 的缺点:
- 英文字母只用一个字节表示就够了,如果用更多的字节存储是极大的浪费。
- 如何才能区别 Unicode 和 ASCII?计算机怎么知道两个字节表示一个符号,而不是分别表示两个符号呢?
- 如果和 GBK 等双字节编码方式一样,用最高位是 1 或 0 表示两个字节和一个字节,就少了很多值无法用于表示字符,不够表示所有字符。
Unicode 在很长一段时间内无法推广,直到互联网的出现,为解决 Unicode 如何在网络上传输的问题,于是面向传输的众多 UTF(UCS Transfer Format)标准出现。具体来说,有三种编码方案,UTF-8、UTF-16 和 UTF-32。
UTF-8
Unicode 是字符集,UTF-8、UTF-16、UTF-32 是三种将数字转换到程序数据的编码方案。顾名思义,UTF-8 就是每次 8 个位传输数据,而 UTF-16 就是每次 16 个位。其中,UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式。
互联网工程工作小组(IETF)要求所有互联网协议都必须支持 UTF-8 编码。所以,我们开发 Web 应用,也要使用 UTF-8 编码。UTF-8 是一种变长的编码方式。它可以使用 1-4 个字节表示一个符号它使用一至四个字节为每个字符编码,编码规则:
- 128 个 US-ASCII 字符,只需一个字节编码。
- 拉丁文等字符,需要二个字节编码。
- 大部分常用字(含中文),使用三个字节编码。
- 其他极少使用的 Unicode 辅助字符,使用四字节编码。
Unicode 符号范围 | UTF-8 编码方式
(十六进制) | (二进制)
————————————————————|—–—–—–—–—–—–—–—–—–—–—–—–—–—–
0000 0000-0000 007F | 0xxxxxxx(兼容原来的 ASCII)
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
注意:在中文操作系统上,ANSI(美国国家标准学会、AMERICAN NATIONAL STANDARDS INSTITUTE)编码即为 GBK;在英文操作系统上,ANSI 编码即为 ISO-8859-1。