1、数据类型
java是一种强引用类型语言。这就意味着必须为每一个变量声明一种类型。在Java种,共有八种基本类型,其中4种整型、2种浮点型、一种字符类型char、一种用于表示真假的boolean类型
1.1、整型
类型 | 大小 | 取值范围 |
byte | 1字节 | 负数:-128。正数:127 |
short | 2字节 | 负数:-32768。正数:32767 |
int | 4字节 | 负数:-2147483648。正数:2147483647 |
long | 8字节 | 负数:-9223372036854775808。正数:9223372036854775807 |
在通常情况下,int类型最常用,但是如果要表示数值较大的数,例如地球总人口,就需要long类型来表示,而byte、short则用于特定的场所例如底层文件处理或者存储空间很宝贵的大数组
在java种,整型的范围和运行java代码的机器无关,这就很好的解决了软件的移植性问题。于此相反,C++中不同的处理器会选择最高效的整型,这会造成一个32位环境下运行完好的C++程序,到16位中就会造成整型溢出的问题
1.2、浮点数类型
类型 | 大小 | 取值范围 |
float | 4字节 | 负数:1.4E-45 (2的-149次方)。正数:3.4028235E38 (2的128次方-1) |
double | 8字节 | 负数:4.9E-324 (2的-1074次方)。正数:1.7976931348623157E308 (2的1024次方-1) |
double表示的数值精度是float的两倍,所以也成为双精度。float类型的有效数字位6-7位,而double的有效数字为15位。事实上,只有很少的情况下才适合使用float。在java中,float类型代表的数值后边必须要加上F或者f,例如3.14f。如果没有加后缀,表示的就是double浮点数类型
可以用以下三种类型来表示溢出和出错的情况,而对象Double中则有相应的常量表示
- 正无穷大 Double.POSITIVE_INFINITY
- 负无穷大 Double.NEGATIVE_INFINITY
- NaN(不是一个数字)Double.NaN
- 一个正浮点数除以0是正无穷大
- 一个负浮点数除以0是负无穷大
- 0.0/0是NaN
正常情况下所有的“非数值”都不相同,但是可以使用Double.isNaN(X)来判断是否是NaN。
注意:x==Double.NaN恒等于false
1.3、char类型
char类型字面量值要用单个引号括起来,例如‘A’是编码值为65的字符常量。char的大小为16个字节,char使用的时UTF-16的编码策略,能支持65536个unicode字符集。但是现在已知的unicode字符集就有11万多个。所以就导致了超出未定义的部分,就需要两个char来组合表示(也称两个代码单元,辅助字符编码)。这样就导致了字符串中的char的数量与unicode中的字符数量不相等。所以java中不推荐使用char这个数据类型。
1.4、boolean类型
boolean类型有两个值,false和ture。用来进行逻辑判断。整型和布尔值之间不能够互相替换
1.5、数值之间的转型
上图中箭头的方向表示可以显示转换,不需要强制类型转换。而实现表示转换之后精度不会丢失,虚线表示转换之后精度会丢失。
当用一个二元运行算符连接两个值时,例如n+f,需要将两个操作数转换成相同的类型,然后再进行计算
- 如果两个操作数中有一个double,另一个操作数也会转换成double才计算
- 否则,如果其中一个操作数是float类型,另一个操作数也会转换成float才计算
- 否则,如果其中一个操作数是long类型,另一个操作数也会转换成long才计算
- 否则,如果两个操作数都会当作int类型进行计算
2、变量与常量
与所有语言一样,java也使用变量来存储值。常量就是值不变的变量。
2.1、变量声明
Java中每个变量都有一个类型,在声明变量时,要先指定变量的类型,然后再声明变量名,最后以分号结尾,不能使用保留字作为变量名
int vacationDays;
double salary;
可以在一行中声明多个变量,不过不提倡使用这种风格,逐一声明每一个变量可以提高代码的可读性
int a,b,c;
在java中,变量名是大小写敏感的,Student和student是两个不同的变量
2.2、 变量初始化
声明一个变量之后,必须用赋值语句对变量进行显示初始化。不能使用未被初始化的值,java编译器认为这种情况下语句是存在错误的。
赋值可以在声明变量的适合一起执行
示例:
int vacationDays=12;
也可以单独使用一行进行初始化
示例:
int vacationDays;
vacationDays =12;
在java中,变量的声明尽可能的靠近使用的地方,这样能有效提高代码的可读性
而从JAVA10开始,对于局部变量,如果可以从变量的初始值推断出它的类型,就可以不声明类型,只需要使用关键字var而无需指定类型
var vacationDays=12;
var name=“李四”;
2.3、常量
在java中,常量必须使用关键字final进行修饰,final表示这个变量只能被赋值一次,一旦赋值之后就不能被改变了。并且这个变量名最好用全大写描述
示例:
例如final int SIZE=5
而如果希望这个常量能被全局使用,通常使用static 和final一起修饰为静态常量
示例:
例如 public static final int SIZE=5;
2.4、枚举
有时,变量的取值实在一个有限的集合里的,例如比萨只有小、中、大、超大这四种情况,而我们如果在使用的适合在定义变量,那么有可能变量保存的值是错误的例如保存了一个超小。
针对这种情况就可以使用枚举使得代码更为规范和安全
enum Size={SMALL,MEDIUM,LARGE,EXTRA_LARGE};
2.5运算符
java中提供了算术运算符 ’+‘ 、’-‘、’*‘、’/‘表示加减乘除,’%‘用来表示取余,也就是取模。
在使用'/'进行除法运算时,两个操作数都是整数,那么就是整数除法,如果有浮点数,就表示浮点数除法。
注意:整除除以0会产生一个算数异常,而浮点数除以0会得到无穷大,0.0/0将会得到一个NaN
可移植性是java语言的目标之一、无论在哪个虚拟机上运行,运算的结果都是一样的,但是对于浮点数的运算,实现可移植性是非常困难的,double占8个字节,也就是使用了64位来存储一个数值,而有些处理器则使用80位浮点数寄存器,这些寄存器增加了中间过程的精度。
例如 double w=x*y/z;
在上面的计算中,会先计算出x*y,并将结果存储在80位的寄存器中,这时候精度就得到了提高,此时再除以z并将结果截断为64位返回,这就得到了一个更加精确的计算,还能避免溢出问题。但是结果可能与始终用64位的计算不一致,因此java虚拟机的最初规范规定了所有的中间计算都必须进行截断(例如使用的是double,那么从始至终都只能保存64位,不能超过64位),但是这种做法立即遭到了数字社区的反对,因为截断计算不仅会导致溢出,由于截断还需要消耗时间,所以在计算速度上比精确值计算要慢。因此推出了使用strictfp进行关键字标记,如果不进行标记,则保持默认的情况,根据不同的操作系统使用的寄存器进行精度计算,如果标记了strictfp关键字,则严格按照java的计算方式,始终保持单精度或者双精度计算。可以在类上标记、方法上标记、接口上标记等。
3、数学函数
在java中提供了Math类,其中包含了各式各样的数学函数
方法名 | 作用 | 说明 |
Math.sqrt(x) | 求平方根 | x的平方根 |
Math.pow(x,y) | 幂运算 | x的y次幂 |
Math.abs(x) | 求绝对值 | x的绝对值 |
Math.max(x,y) | 返回两数之间的最大值 | - |
Math.min(x,y) | 返回两数之间的最小值 | - |
Math.round(x) | 返回四舍五入后的整数 | - |
Math.random() | 返回0-1的随机数 | - |
在程序中如果大量引入Math的方法,可以通过静态导入的方式,直接使用方法名而不需要通过Math调用
示例:
package com.itheima.springbootactuator;
import static java.lang.Math.*;
public class MathText {
public static void main(String[] args) {
abs(-2);//等同于Math.abs(-2);
}
}
此外,Math还提供了一些验证性计算的方法。
在普通场景下,如果使用一个int类型接收10亿乘以三,会出现溢出现象,但是并不会报错,而是给出一个错误的计算结果,如果我们想不到这种情况,那么就会使用错误的结果进行接下来的计算,导致整个链路以致最终结果的错误。
对于上面的乘法,Math类提供了Math.multiplyExact(a,b)方法,当出现算数溢出的时候,就会抛出一个溢出,防止拿着错误的结果进行计算。
Math还提供其他的方法用于计算加减乘以及反转符号:
方法名 | 作用 | 说明 |
Math.addExact(a,b) | 两数相加 | |
Math.subtractExact(a,b) | a-b | |
Math.multiplyExact(a,b) | a*b | |
Math.incrementExact(a) | a自增 | a+1 |
Math.decrementExact(a) | a自减 | a-1 |
Math.negateExact(a) | 反转符号 | 当a=-1时,返回1,当a=1时,返回-1 |
4、流程控制
4.1、条件语句 if
if作为条件语句判断,其格式为if(condition) statement;
当condition为true的时候,就会执行statement的内容;
示例:
int age =19 ;
if(age>18)
System.out.printf("您当前年龄为%d,您已成年",age);
解释:if作为条件判断,例如上述代码中,此时age=19,而条件为age>18,满足了条件,则进入紧跟着if的代码中,但是这种表答方式并不推荐使用。但是在大部分情况,条件语句都要跟着一些业务,一行代码很难完成,这时候就需要使用代码块,在条件判断过后添加一个代码快,表示当满足条件之后就执行代块中的内容。这也是java中比较推荐的方式,这样可以提高代码的可读性
示例:
int age =19 ;
if (age > 18) {
System.out.printf("您当前年龄为%d,您已成年", age);
System.out.println("成年人要为自己的每一个选择负责,好好学习吧");
}
4.2、条件语句if else
在很多情况下,我们仅仅设置满足条件的是满足不了大多数需求的,这时可以使用else进行补充,相当于把一件事情的两个结果都表述出来了,如果满足if的条件,就执行statementA,如果不满足if的条件就执行statementB,而else后的代码块就意味着不满足条件的时候的处理方案
if(condition) statementA
else statementB
示例:
int age =7 ;
if (age > 18) {
System.out.printf("您当前年龄为%d,您已成年", age);
System.out.println("成年人要为自己的每一个选择负责,好好学习吧");
}else {
System.out.printf("您当前年龄为%d,您还为成年", age);
System.out.println("还是听你老爸老妈的话吧");
}
4.3、条件语句 if else if
也有某些情景,仅仅是if else 两种情况无法满足需求,例如根据成绩评选差、良、优就需要三个分支,if else if 就能解决这种问题
if(conditionA)statementA
else if(conditionB) statementB
else if (conditionC)statementC
else statementD
示例:
int score =60 ;
if (score <60) {
System.out.println("不及格,评分:差");
}else if(60<=score&&score<90){
System.out.println("及格,评分:良");
}else {
System.out.println("真他娘的棒,我咋就没你这水平,评分:优");
}
4.4、多重选择 switch语句
在处理多重选择的情况时(多个分支,一件事情的不同选择产生不同的结果),使用if/else会显得有些笨重。我们可以使用switch语句处理,它会从与选项值相匹配的case标签开始执行,直到遇到break语句,或者执行到swtich语句的结束为止,如果没有相匹配的case标签,可给它配上一个default子句,当不匹配时就执行default子句,作用相当于else。
注意事项:每一个case标签的代码块执行完毕后,必须要加一个break;这样才能正确的结束流程,否则就会执行下一个标签的代码块,直到遇到break
示例:
String x = "A";
switch (x){
case "A":
System.out.println("选中A");
break;
case "B":
System.out.println("选中B");
break;
default:
System.out.println("都没选中");
}
解释:例如上述代码中,定义了一个字符串X = "A" 作为比较值,而switch(X)中,括号内的X则就是要做比较的对象,然后再下面的case标签中进行匹配,这里定义的x是”A“,当执行到第一句case”A“ 的时候,进行匹配,发现匹配上了,就执行冒号后面的代码块,然后通过break推出。如果没有break这个终止标记,那么就会继续执行 System.out.println("选中B");不管case”B“是否满足,直到遇上beak;
当枚举常量作为匹配值的情况:
如果switch使用枚举常量作为匹配值,那么可以不用指明枚举名,会通过推导出结果
示例:
public enum Size {
A,B,C,D
}
Size size = Size.A;
switch (size){
case A:
System.out.println("选中枚举类A");
break;
case B:
System.out.println("选中枚举类B");
break;
}
解释:例如上述代码,先创建一个枚举类Size,然后将枚举类常量作为swtich的匹配项,那么就会推导出枚举类的常量,在case标签中就可以不通过Size.A的方式获取A,而直接输入case A即可
5、大数
如果基本的整数和浮点数的精度不能够满足需求,那么可与使用java.math包下的两个类:BigInteger和BigDecimal。这两个类可与处理任意长度数字序列的值。BigInteger可以实现任意精度的整数运算,BigDecimal可以实现任意精度的浮点数计算