02.基本语法
1.关键字与标识符
1.关键字
2.标识符的使用
定义:凡是自己可以起名字的地方都叫标识符
涉及到的结构:包名、类名、接口名、变量名、方法名、常量名
2.变量的使用(重点)
1.变量的分类
按数据类型分类
详细说明:
1.整型:byte(1字节=8bit) \ short(2字节) \ int(4字节) \ long(8字节)
① byte范围:-128 ~ 127
② 声明long型变量,必须以"l"或"L"结尾
③ 通常,定义整型变量时,使用int型
④ 整型的常量,默认类型是:int型
500MB 1MB = 1024KB 1KB= 1024B B= byte ? bit?
bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。
2.浮点型:float(4字节) \ double(8字节)
① 浮点型,表示带小数点的数值
② float表示数值的范围比long还大
③ 定义float类型变量时,变量要以"f"或"F"结尾
④ 通常,定义浮点型变量时,使用double型。
⑤ 浮点型的常量,默认类型为:double
浮点型数据计算精度丢失问题
float和double数据类型的地城数据存储结构不一样:
计算机系统采纳了所谓的浮点数表达方式。这种表达方式利用科学计数法来表达实数,即用一个尾数(Mantissa也叫有效数字 ),一个基数(Base),一个指数(Exponent)以及一个表示正负的符号来表达实数。浮点数利用指数达到了浮动小数点的效果,从而可以灵活地表达更大范围的实数。
float:1bit(符号位),8bits(指数位),23bits(尾数位)
double:1bit(符号位),11bits(指数位),52bits(尾数位)Java中double类型的格式基本遵循IEEE 754标准。尽管数学意义上的小数是连续的,但double仅仅能表示其中的一些离散点,把这些离散点组成的集合记为S,S的大小还是有限的。如果要保存的小数P刚好在集合S内,那么double类型就能精确的表示P;否则double类型只能从集合S中找一个与P最近的离散点P'代替P。
对于float和double数据类型精度丢失问题,在‘Effective Java’一书中也提到:float和double只能用来做科学计算或者工程计算(why?),在商业计算中我们要用java.math.BigDecimal。如果我们需要精确计算,非要用String来构建BigDecimal不可!
剖析float型的内存存储和精度丢失问题:https://www.iteye.com/blog/hxraid-504293
3.字符型:char (1字符=2字节)
① 定义char型变量,通常使用一对'',内部只能写一个字符
② 表示方式:1.声明一个字符 2.转义字符 3.直接使用 Unicode 值来表示字符型常量
4.布尔型:boolean
① 只能取两个值之一:true 、 false
② 常常在条件判断、循环结构中使用
按声明的位置分类(了解)
2.定义变量的格式:
数据类型 变量名 = 变量值;
或
数据类型 变量名;
变量名 = 变量值;
3.变量使用的注意点
① 变量必须先声明,后使用
② 变量都定义在其作用域内。在作用域内,它是有效的。换句话说,出了作用域,就失效了
③ 同一个作用域内,不可以声明两个同名的变量
4.基本数据类型变量间运算规则
1.涉及到的基本数据类型:除了boolean之外的其他7种
2.自动类型转换(只涉及7种基本数据类型)
结论:当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。
byte 、char 、short --> int --> long --> float --> double
特别的:byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型
说明:此时的容量大小指的是,表示数值的范围的大和小。比如:float容量要大于long的容量
3.强制类型转换(只涉及7种基本数据类型):自动类型提升运算的逆运算
1.需要使用强转符:()
2.注意点:
-
强制类型转换,可能导致精度损失。(在大转小时)
-
java中强转只能针对单个bean对象,数组间不可直接强转 eg:Object[] objs ==> String[] strs
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
4.String与8种基本数据类型间的运算
- String属于引用数据类型,翻译为:字符串
- 声明String类型变量时,使用一对""
- String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+
- 运算的结果仍然是String类型
3.进制的转换
![image-20211226170750644](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072759259-1853223553.png)
进制转换的介绍
第一组:
- 二进制转十进制
- 八进制转十进制
- 十六进制转十进制
第二组: - 十进制转二进制
- 十进制转八进制
- 十进制转十六进制
第三组 - 二进制转八进制
- 二进制转十六进制
第四组 - 八进制转二进制
- 十六进制转二进制
第一组
二进制转换成十进制
![image-20211226170300552](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072759534-17724571.png)
八进制转换成十进制
![image-20211226170346346](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072759806-407215463.png)
第二组
十六进制转换成十进制
规则:从最低位(右边)开始,将每个位上的数提取出来,乘以 16 的(位数-1)次方,然后求和。
案例:请将 0x23A 转成十进制的数
0x23A = 10 * 16^0 + 3 * 16 ^ 1 + 2 * 16^2 = 10 + 48 + 512 = 570
十进制转换成二进制
规则:将该数不断除以 2,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制。
案例:请将 34 转成二进制
= 0B00100010
十进制转换成八进制
规则:将该数不断除以 8,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的八进制。
案例:请将 131 转成八进制 => 0203
十进制转换成十六进制
规则:将该数不断除以 16,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的十六进制。
案例:请将 237 转成十六进制 => 0xED
第三组
二进制转换成八进制
规则:从低位开始,将二进制数每三位一组,转成对应的八进制数即可。
案例:请将 ob11010101 转成八进制
ob11(3)010(2)101(5) => 0325
二进制转换成十六进制
规则:从低位开始,将二进制数每四位一组,转成对应的十六进制数即可。
案例:请将 ob11010101 转成十六进制
ob1101(D)0101(5) = 0xD5
第四组
八进制转换成二进制
规则:将八进制数每 1 位,转成对应的一个 3 位的二进制数即可。
案例:请将 0237 转成二进制
02(010)3(011)7(111) = 0b10011111
十六进制转换成二进制
规则:将十六进制数每 1 位,转成对应的 4 位的一个二进制数即可。
案例:请将 0x23B 转成二进制
0x2(0010)3(0011)B(1011) = 0b001000111011
3.运算符
运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。
算术运算符
赋值运算符
比较运算符(关系运算符 )
逻辑运算符
位运算符
元运算符
1.算术运算符
注意点
1.如果对负数取模,可以把模数负号忽略不记,eg:5%-2=1;但被模数是负数则不可忽略。此外,取模运算的结果不一定总是整数,eg:-5%2=-1
2.对于除号“/”,它的整数除和小数除是区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
例如:int x=3510;x=x/1000*1000; x的 结果是? //1000
3.“+”除字符串相加功能外,还能把非字符串转换成字符串.例如: System.out.println(“5+5=”+5+5); //打印结果是? 5+5=55 ?
2.赋值运算符
符号:=
当“=”两侧数据类型不一致时,可以使用自动类型转换或使用强制类型转换原则进行处理。
支持连续赋值
扩展赋值运算符: +=, -=, *=, /=, %= (使用这些运算符,在与容量大的类型的数据计算时,原数据类型不会自动提升为容量大的数据类型)
3.比较运算符
比较运算符的结果都是boolean型,也就是要么是true,要么是false。
比较运算符“==”不能误写成“=”
instanceof只能用于引用数据类型
4.逻辑运算符
注意点:
逻辑运算符用于连接布尔型表达式,在Java中不可以写成3<x<6,应该写成x>3 & x<6 。
“&”和“&&”的区别:
单&时,左边无论真假,右边都进行运算;
双&时,如果左边为真,右边参与运算,如果左边为假,那么右边不参与运算。
“|”和“||”的区别同理,||表示:当左边为真,右边不参与运算。
异或( ^ )理解:异或,追求的是“异”
5.位运算
基本规则
java 中有 7 个位运算(&、|、^、~、>>、<<和 >>>)
![image-20211226170935967](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072800089-1239484409.png)
运算过程
算术左移<<
![image-20211226171813442](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072800350-1471147020.png)
算术右移>> 无符号右移(逻辑右移)>>>
![image-20211226171639801](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072800609-1126667459.png)
按位与& 按位或| 按位异或^
按位取反~
![image-20211226172153592](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072801015-134458931.png)
原码、补码、反码
基本规则
二进制的最高位是符号位: 0表示正数,1表示负数
正数的原码,反码,补码都一样(三码合一)
负数的反码=它的原码符号位不变,其它位取反
负数的补码=它的反码+1,负数的反码 = 负数的补码 - 1
0的反码,补码都是O
java没有无符号数,换言之,java中的数都是有符号的
在计算机运算的时候,都是以补码的方式来运算和存储的.
当我们看运算结果的时候,要看他的原码
- Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位;
当是long类型时,二进制默认占64位,第64位是符号位 - 二进制的整数有如下三种形式:
原码:直接将一个数值换成二进制数。最高位是符号位
负数的反码:是对原码按位取反,只是最高位(符号位)确定为1。
负数的补码:其反码加1。 - 计算机以二进制补码的形式保存所有的整数。
正数的原码、反码、补码都相同
负数的补码是其反码+1
为什么使用原码、反码、补码
计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法.
我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 ,
所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了。
1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补 = [0000 0000]原
byte取值区间:-127~128
-127 = 1000 0001(byte类型 最小的负数)
-1 = 1111 1111 (byte类型 最大的负数)
1 = 0000 0001
0 = 0000 0000
6.三元运算符
语法是“条件表达式?表达式1:表达式2”
使用这个算法可以使调用数据时逐级筛选。
表达式:“( ) ? : ” ()中进行二元运算 ?再运算,就形成三元运算符
一般if--else可以改写为三元表达式
4.流程控制
顺序结构:程序从上到下执行
分支结构:
if-else if - else
switch-case
switch(表达式)中表达式的值必须是下述几种类型之一:byte,short, char,int,枚举 (jdk 5.0),String (jdk 7.0);
case子句中的值必须是常量,不能是变量名或不确定的表达式值;
同一个switch语句,所有case子句中的常量值互不相同;
break语句用来在执行完一个case分支后使程序跳出switch语句块;如 果没break,程序会顺序执行到switch结尾
default子句是可任选的。同时,位置也是灵活的。当没匹配的case时, 执行default
循环结构:
for
while
do-while 先执行一次在判断while的条件来决定是否循环
带标记的for循环
@Test
public void test() { // i0-j0-j1-i1-j0-j1-i2-
Outerloop:
for (int i = 0; i < 10; i++) {
System.out.print("i" + i + "-");
Innerloop:
for (int j = 0; j < 2; j++) {
if (i == 2) {
break Outerloop; // 只能打断外层的循环(当外层的 i = 2 时)即打断了整个循环
}
System.out.print("j" + j + "-");
}
}
}
@Test
public void test1() { // i0-j0-j1-i1-j0-j1 -i2- i3-j0-j1-i4-j0-j1-i5-j0-j1-i6-j0-j1-i7-j0-j1-i8-j0-j1-i9-j0-j1-
for (int i = 0; i < 10; i++) {
System.out.print("i" + i + "-");
Innerloop:
for (int j = 0; j < 2; j++) {
if (i == 2) {
break; // 只能打断内层的一次循环(当外层的 i = 2 时)
}
System.out.print("j" + j + "-");
}
}
}
5.常见字符集、编码
文件编码的方式(比如:GBK),决定了解析时使用的字符集(也只能是GBK)。
ASCII
和Unicode
是字符集,Unicode
是基于ASCII
扩展出来的编码;而GBK
和UTF8
是编码规则。
ANSI
编码,通常指的是平台的默认编码,例如英文操作系统中是ISO-8859-1
,中文系统是GBK
Unicode字符集
只是定义了字符的集合和唯一编号,Unicode编码
,则是对UTF-8
、UCS-2
/UTF-16
等具体编码方案的统称而已,并不是具体的编码方案。
1.常见的编码表
ASCII:美国标准信息交换码 用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表 用一个字节的8位表示。
GB2312:中国的中文编码表 最多两个字节编码所有字符
GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
Unicode:国际标准码,融合了目前人类使用的所字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。2.对后面学习的启示
客户端/浏览器端 <----> 后台(java,GO,Python,Node.js,php) <----> 数据库
要求前前后后使用的字符集都要统一:UTF-8.
-
字符集
Charset
:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。
常见字符集有ASCII字符集、GB字符集、Unicode字符集等。
字符集:一个「字符」分配一个唯一的 ID(学名为码位 / 码点 / Code Point)
int a = (int)'你'; // 这里是获取到字符 你 所对应的 Unicode编码 System.out.println(a);
编码规则:将「码位」转换为字节序列的规则s(编码/解码 可以理解为 加密/解密 的过程)。
String x = "你"; System.out.println(Arrays.toString(x.getBytes()));
![image-20220116220129540](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072801266-953207756.png)
可见,当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。
-
ASCII字符集:
- ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
- 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
-
ISO-8859-1字符集:
- 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
- ISO-8859-1使用单字节编码,兼容ASCII编码。
-
GBxxx字符集:
- GB就是国标的意思,是为了显示中文而设计的一套字符集。
- GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
- GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。
- GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
-
Unicode字符集:
-
Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。
-
它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。
-
UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:
-
128个US-ASCII字符,只需一个字节编码。
-
拉丁文等字符,需要二个字节编码。
-
大部分常用字(含中文),使用三个字节编码。
-
其他极少使用的Unicode辅助字符,使用四字节编码。
Unicode范围(十六进制) UTF8编码方式(二进制) 0000~007F(即:0000 0000-0000 007F) 00000000 0080~07FF(即:0000 0080-0000 07FF) 11000000 10000000 0800~FFFF(即:0000 0800-0000 FFFF) 111000000 10000000 10000000 10000~10FFFF (即:0001 0000-0010 FFFF) 11110000 10000000 10000000 10000000
-
-
![image-20220116222349559](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072801538-83972026.png)
举例:
![image-20220116222412472](https://img2022.cnblogs.com/blog/2733620/202206/2733620-20220602072801769-1880893509.png)
6.运算符的优先级
Java中的表达式就是使用运算符连接起来的符合Java规则的式子。
运算符的优先级决定了表达式中运算执行的先后顺序。
通常优先级由高到低的顺序依次是:
- 增量和减量运算
- 算术运算
- 比较运算
- 逻辑运算
- 赋值运算
如果两个运算有相同的优先级,那么左边的表达式要比右边的表达式先被处理。
运算符的优先级
在编写程序如果不记得运算符的优先级可以使用括号运算符来限定运算次序,以免产生错误的运算顺序。
system.out.println("2 + 4 >> 1 = " + (2 + 4 >> 1))
// '+'优先级大于'>>',所以先2加4等于6,再移位运算等于3
7.转义字符/占位符
public class PrintDemo {
public static void main(String[] args) {
// \表示转移字符串,对紧跟着的字符进行转移
// \n 换行
// \r 回车(不同的编程语言和不同的平台操作系统)
// \t 制表符
// \\ 表示 \
// \' 表示 一个单引号
// \" 表示 一个双引号
System.out.println("Hello\\tWorld"); // Hello\tWorld
System.out.println("Tom said \"I am tom\"");
System.out.println("tom said I\'m tom");
// printf 用来实现格式化输出
// %d 表示整数的占位符
// %nd 表示如果数字不够 n 位,前面使用空格补齐
// %-nd 表示如果数字不够 n 位,后面使用空格补齐
// %0nd 表示如果数字不够n位,前面使用0补齐
// %s 表示字符串的占位符
// %f 表示浮点数的占位
// %.nf 表示四舍五入保留到小数点后 n 位
// %% 表示一个 %
int num = 8;
String name = "渣渣辉";
System.out.println("大家好,我是第" + num + "号选手,我的名字是" + name);
System.out.printf("大家好,我是第%-3d号选手,我的名字是%s",num,name);
System.out.printf("我今天挣了%.2f元钱",3.147);
System.out.printf("我的名字是%%d");
}
}