常量与变量
1.1 常量:在Java程序中固定不变的数据。
常量类型
解释
举例
整数常量
所有的整数
0,1, 567, -9
小数常量
所有的小数
0.0, -0.1, 2.55
字符常量
单引号引起来,只能写一个字符,必须有内容
'a' , ' ', '好'
字符串常量
双引号引起来,可以写多个字符,也可以不写
"A" ,"Hello" ,"你好" ,""
布尔常量
只有两个值(流程控制中讲解)
true , false
空常量
只有一个值(引用数据类型中讲解)
null
注意:
字符串可以为空"",但是字符不能为空''。如System.out.println('');会报错。
空常量不能直接用来打印输出,如System.out.println(null);会报错。
1.2 变量:在程序中可以变化的量称为变量。
Java中要求一个变量每次只能保存一个数据,必须要明确保存的数据类型。
基本数据类型
2.1 Java的数据类型分为两大类:
基本数据类型:包括 整数、浮点数、字符、布尔。
引用数据类型:包括 类、数组、接口。
2.2 四类八种基本数据类型:
数据类型
关键字
内存占用
取值范围
字节型
byte
1个字节
-128~127
短整型
short
2个字节
-32768~32767
整型
int(默认)
4个字节
-2的31次方~2的31次方-1
长整型
long
8个字节
-2的63次方~2的63次方-1
单精度浮点数
float
4个字节
1.4013E-45~3.4028E+38
双精度浮点数
double(默认)
8个字节
4.9E-324~1.7977E+308
字符型
char
2个字节
0-65535
布尔类型
boolean
1个字节
true,false
Java中的默认类型:整数类型是 int、浮点类型是 double。
整数型byte short int long。
2.3 变量定义
变量定义的格式包括三个要素:数据类型、变量名、数据值。
数据类型 变量名 = 数据值;
long类型:建议数据后加L表示。
float类型:建议数据后加F表示。
变量名称:在同一个大括号范围内,变量的名字不可以相同。
变量赋值:定义的变量,不赋值不能使用。
2.4 引用数据类型(今后学习)
字符串、数组、类、接口、Lambda
注意事项:
字符串不是基本类型,而是引用类型。
浮点型可能只是一个近似值,并非精确的值。
数据范围与字节数不一定相关,例如float数据范围比long更加广泛,但是float是4字节,long是8字节。
浮点数当中默认类型是double。如果一定要使用float类型,需要加上一个后缀F。
如果是整数,默认为int类型,如果一定要使用long类型,需要加上一个后缀L。推荐使用大写字母后缀。
如果使用byte或者short类型的变量,那么右侧的数据值不能超过左侧类型的范围。
没有进行赋值的变量,不能直接使用;一定要赋值之后,才能使用。
数据类型转换
Java程序中要求参与的计算的数据,必须要保证数据类型的一致性,如果数据类型不一致将发生类型的转换。
3.1 自动转换(隐式)
规则:将取值范围小的类型自动提升为取值范围大的类型 。 浮点型数据比整数数据的范围大
一个int类型变量和一个byte类型变量进行加法运算,运算结果,变量的类型将是int类型。
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、short、char运算时直接提升为int。
byte、short、char‐‐>int‐‐>long‐‐>float‐‐>double
3.2 强制转换(显示)
将取值范围大的类型强制转换成取值范围小的类型。比较而言,自动转换是Java自动执行的,而强制转换需要我们自己手动执行。
转换格式:
数据类型 变量名 =(数据类型)被转数据值;
// double类型数据强制转成int类型,直接去掉小数点。
int i = (int)1.5;
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);//编译成功
}
转换原理图解
3.3 类型转换注意事项
强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出。
// double --> int,强制类型转换
int num3 = (int) 3.99;
System.out.println(num3); // 3,这并不是四舍五入,所有的小数位都会被舍弃掉
byte/short/char这三种类型都可以发生数学运算,例如加法“+”。
char zifu1 = 'A'; // 这是一个字符型变量,里面是大写字母A
System.out.println(zifu1 + 1); // 66,也就是大写字母A被当做65进行处理
// 计算机的底层会用一个数字(二进制)来代表字符A,就是65
// 一旦char类型进行了数学运算,那么字符就会按照一定的规则翻译成为一个数字
byte/short/char这三种类型在运算的时候,都会被首先提升成为int类型,然后再计算。
byte num4 = 40; // 注意!右侧的数值大小不能超过左侧的类型范围
byte num5 = 50;
//错误:“不兼容的类型,从int到byte可能会有损失”
byte result1 = num4 + num5; // byte + byte --> int + int --> int
//正确:应该使用int数据类型接收,byte类型计算时已经提升为int类型
int result1 = num4 + num5;
System.out.println(result1); // 理论应该输出90
short num6 = 60;
// byte + short --> int + int --> int
// int强制转换为short:注意必须保证逻辑上真实大小本来就没有超过short范围,否则会发生数据溢出
short result2 = (short) (num4 + num6);
boolean类型不能发生数据类型转换。布尔类型不能被当作1或者0。
3.4 ASCII编码
数字和字符的对照关系表(编码表):
ASCII码表:American Standard Code for Information Interchange,美国信息交换标准代码。
Unicode码表:万国码。也是数字和符号的对照关系,开头0-127部分和ASCII完全一样,但是从128开始包含有更多字符。
字符
数值
0
48
9
57
A
65
Z
90
a
97
z
122
运算符
4.1 算数运算符
运算符:进行特定操作的符号。例如:+
表达式:用运算符连起来的式子叫做表达式。例如:20 + 5。又例如:a + b
+ | - | * | / | % | ++ | --
注意:
对于一个整数的表达式来说,除法用的是整除,整数除以整数,结果仍然是整数。只看商,不看余数。只有对于整数的除法来说,取模运算符才有余数的意义。
一旦运算当中有不同类型的数据,那么结果将会是数据类型范围大的那种。即计算时类型会统一到范围大的类型在计算。
加号的用法:
对于数值来说,那就是加法。
对于字符char类型来说,在计算之前,char会被提升成为int,然后再计算。
char类型字符,和int类型数字,之间的对照关系表:ASCII、Unicode
对于字符串String(首字母大写,并不是关键字)来说,加号代表字符串连接操作。
任何数据类型和字符串进行连接的时候,结果都会变成字符串。
String str2 = "Java";
// String + int --> String
System.out.println(str2 + 20); // Java20
// 优先级问题
// String + int + int
// String + int
// String
System.out.println(str2 + 20 + 30); // Java2030
System.out.println(str2 + (20 + 30)); // Java50
自增自减 ++/--
在单独使用的时候,前++和后++没有任何区别。也就是:++num;和num++;是完全一样的。
在混合的时候,有【重大区别】
A. 如果是【前++】,那么变量【立刻马上+1】,然后拿着结果进行使用。【先加后用】
B. 如果是【后++】,那么首先使用变量本来的数值,【然后再让变量+1】。【先用后加】
int x = 10;
int y = 20;
// 11 + 20 = 31
int result3 = ++x + y--;
System.out.println(result3); // 31
System.out.println(x); // 11
System.out.println(y); // 19
注意:只有变量才能使用自增、自减运算符。常量不可发生改变,所以不能用。
30++; // 错误写法!常量不可以使用++或者--
4.2 赋值运算符
赋值运算符包括
=
等于号
+=
加等于
-=
减等于
*=
乘等于
/=
除等于
%=
取模等
只有变量才能使用赋值运算符,常量不能进行赋值。
复合赋值运算符其中隐含了一个强制类型转换。
byte num = 30;
// num = num + 5;
// num = byte + int
// num = int + int
// num = int
// num = (byte) int
num += 5;
System.out.println(num); // 35
4.3 比较运算符
比较运算符包括:
==
比较符号两边数据是否相等,相等结果是true。
<
比较符号左边的数据是否小于右边的数据,如果小于结果是true。
>
比较符号左边的数据是否大于右边的数据,如果大于结果是true。
<=
比较符号左边的数据是否小于或者等于右边的数据,如果小于结果是true。
>=
比较符号左边的数据是否大于或者等于右边的数据,如果小于结果是true。
!=
不等于符号 ,如果符号两边的数据不相等,结果是true。
比较运算符的结果一定是一个boolean值,成立就是true,不成立就是false
如果进行多次判断,不能连着写。
数学当中的写法,例如:1 < x < 3 程序当中【不允许】这种写法。因为1
4.4 逻辑运算符
逻辑运算符包括
与(并且)
&&
全都是true,才是true;否则就是false
或(或者)
||
至少一个是true,就是true;全都是false,才是false
非(取反)
!
本来是true,变成false;本来是false,变成true
**与“&&”,或“
”,具有短路效果:如果根据左边已经可以判断得到最终结果,那么右边的代码将不再执行,从而节省一定的性能。**
注意事项:
逻辑运算符只能用于boolean值。
与、或需要左右各自有一个boolean值,但是取反只要有唯一的一个boolean值即可。
与、或两种运算符,如果有多个条件,可以连续写。
两个条件:条件A && 条件B
多个条件:条件A && 条件B && 条件C
TIPS:
对于1 < x < 3的情况,应该拆成两个部分,然后使用与运算符连接起来:
int x = 2;
1 < x && x < 3
int a = 10;
// false && ...
System.out.println(3 > 4 && ++a < 100); // false
System.out.println(a); // 10 短路!
System.out.println("============");
int b = 20;
// true || ...
System.out.println(3 < 4 || ++b < 100); // true
System.out.println(b); // 20 短路!
4.5 三元运算符
一元运算符:只需要一个数据就可以进行操作的运算符。例如:取反!、自增++、自减--
二元运算符:需要两个数据才可以进行操作的运算符。例如:加法+、赋值=
三元运算符:需要三个数据才可以进行操作的运算符。
数据类型 变量名称 = 条件判断 ? 表达式A : 表达式B;
流程:
首先判断条件是否成立:
如果成立为true,那么将表达式A的值赋值给左侧的变量;
如果不成立为false,那么将表达式B的值赋值给左侧的变量;
二者选其一。
注意事项:
必须同时保证表达式A和表达式B都符合左侧数据类型的要求。
int result = 3 > 4 ? 2.5 : 10; // 错误写法!
三元运算符的结果必须被使用。
a > b ? a : b; // 错误写法!
方法入门
方法:就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能。当我们需要这个功能的时候,就可以去调用。这样即实现了代码的复用性,也解决了代码冗余的现象
定义一个方法的格式:
public static void 方法名称() {
方法体
}
方法名称的命名规则和变量一样,使用小驼峰。
方法体:也就是大括号当中可以包含任意条语句。
注意事项:
方法定义的先后顺序无所谓。
方法的定义不能产生嵌套包含关系。
方法定义好了之后,不会执行的。如果要想执行,一定要进行方法的【调用】。
如何调用方法,格式:
方法名称();
编译器的两点优化 !!
对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(char)。
如果没有超过左侧的范围,编译器补上强转。
如果右侧超过了左侧范围,那么直接编译器报错。
public class Demo12Notice {
public static void main(String[] args) {
// 右侧确实是一个int数字,但是没有超过左侧的范围,就是正确的。
// int --> byte,不是自动类型转换
byte num1 = /*(byte)*/ 30; // 右侧没有超过左侧的范围
System.out.println(num1); // 30
// byte num2 = 128; // 报错,右侧超过了左侧的范围
// int --> char,没有超过范围
// 编译器将会自动补上一个隐含的(char)
char zifu = /*(char)*/ 65;
System.out.println(zifu); // A
}
}
编译器的常量优化
/*
在给变量进行赋值的时候,如果右侧的表达式当中全都是常量,没有任何变量,
那么编译器javac将会直接将若干个常量表达式计算得到结果。
short result = 5 + 8; // 等号右边全都是常量,没有任何变量参与运算
编译之后,得到的.class字节码文件当中相当于【直接就是】:
short result = 13;
右侧的常量结果数值,没有超过左侧范围,所以正确。
这称为“编译器的常量优化”。
但是注意:一旦表达式当中有变量参与,那么就不能进行这种优化了。
*/
public class Demo13Notice {
public static void main(String[] args) {
short num1 = 10; // 正确写法,右侧没有超过左侧的范围,
short a = 5;
short b = 8;
// short + short --> int + int --> int
// short result = a + b; // 错误写法!左侧需要是int类型
// 右侧不用变量,而是采用常量,而且只有两个常量,没有别人
short result = 5 + 8;
System.out.println(result);
short result2 = 5 + a + 8; // 18
}
}
流程控制语句
1. 顺序结构
2. 判断语句 if
// 1) 单if语句
if(关系表达式){
语句体;
}
// 2) 标准的if-else语句
if(关系表达式) {
语句体1;
}else {
语句体2;
}
// 3)嵌套if-else if else
if (判断条件1) {
执行语句1;
} else if (判断条件2) {
执行语句2;
}
...
}else if (判断条件n) {
执行语句n;
} else {
执行语句n+1;
}
3. 选择语句 switch
switch(表达式) {
case 常量值1:
语句体1;
break;
case 常量值2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
switch语句使用的注意事项:
多个case后面的数值不可以重复。
switch后面小括号当中只能是下列数据类型:
基本数据类型:byte/short/char/int (其他的基本类型不可以使用)
引用数据类型:String字符串、enum枚举
switch语句格式可以很灵活:前后顺序可以颠倒,而且break语句还可以省略。
“匹配哪一个case就从哪一个位置向下执行,直到遇到了break或者整体结束为止。” 具有穿透性
4. 循环语句
循环结构的基本组成部分,一般可以分成四部分:
初始化语句:在循环开始最初执行,而且只做唯一一次。
条件判断:如果成立,则循环继续;如果不成立,则循环退出。
循环体:重复要做的事情内容,若干行语句。
步进语句:每次循环之后都要进行的扫尾工作,每次循环结束之后都要执行一次。
// for 循环
for(初始化表达式①; 布尔表达式②; 步进表达式④){
循环体③
}
// while 循环
初始化表达式①
while(布尔表达式②){
循环体③
步进表达式④
}
// do-while 循环
初始化表达式①
do{
循环体③
步进表达式④
}while(布尔表达式②);
三种循环的区别:
如果条件判断从来没有满足过,那么for循环和while循环将会执行0次,但是do-while循环会执行至少一次。
for循环的变量在小括号当中定义,只有循环内部才可以使用。while循环和do-while循环初始化语句本来就在外面,所以出来循环之后还可以继续使用。
5. 循环控制语句
break
可以用在switch语句当中,一旦执行,整个switch语句立刻结束。
还可以用在循环语句当中,一旦执行,整个循环语句立刻结束。打断循环。
关于循环的选择,有一个小建议:凡是次数确定的场景多用for循环;否则多用while循环。
continue
一旦执行,立刻跳过当前次循环剩余内容,马上开始下一次循环。
6. 死循环
即循环中的条件永远为true,死循环的是永不结束的循环。例如:while(true){}
7. 嵌套循环
所谓嵌套循环,是指一个循环的循环体是另一个循环。比如for循环里面还有一个for循环,就是嵌套循环。总共的循环次数=外循环次数*内循环次数
for(初始化表达式①; 循环条件②; 步进表达式⑦) {
for(初始化表达式③; 循环条件④; 步进表达式⑥) {
执行语句⑤;
}
}