一、数据类型
Java 中的数据类型包括基本数据类型和引用数据类型,本篇主要介绍 Java 中的基本数据类型。
Java 是一种强类型语言,意味着必须为每一个变量声明一种类型。在 Java 中共有八种基本数据类型。
1.1 整型(int)
在 Java 中, int 类型占用四个字节, int 的大小与操作系统无关。4 个字节表示的数据范围是 -2^31 -> 2^31-1 ,即-2147483648 ~ 2147483647。
public static void main(String[] args) {
int a = 1;//定义一个整型变量a
int b = 0;
System.out.println(a);
}
使用代码查看 int 类型的最大值和最小值:
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE); // int 的最大值
System.out.println(Integer.MIN_VALUE); // int 的最小值
//Integer是int的包装类
}
将2147483648赋值给 int 类型的变量时,编译器会提醒超出最大范围。
如果超出了这个范围我们需要用什么类型表示呢? Java 中提供了 long 类型。
1.2 长整型(long)
长整型在定义的时候必须在数值后面加上 L ,用来和整型数值进行区分。 long 类型占用8个字节,可表示的范围为 -2^63 -> 2^63-1。
public static void main(String[] args){
//定义一个long类型的变量a
long a = 10L; //定义的时候加L,意思是10是长整型
System.out.println(a);
//打印long的最大值和最小值,其中Long是long的包装类
System.out.println("长整型最大值:" + Long.MAX_VALUE);//用+拼接
System.out.println("长整型最小值:" + Long.MIN_VALUE);
}
1.3 字节型变量(byte)
- 字节类型表示的也是整数。只占一个字节, 表示范围较小 ( -128 -> +127 )。
- 字节类型和字符类型互不相干。
//字节类型:byte,占用1个字节 数值范围:128~127
public static void main(String[] args){
byte b = 12;//定义byte型变量
byte c = 21;
System.out.println(b + " " + c);
//System.out.println(c);
System.out.println(Byte.MAX_VALUE);
System.out.println(Byte.MIN_VALUE);
}
类型提升:1是整数(int),d是字节型,整型表示的范围比字节型要大,把1赋值给d,发生了类型提升。
byte d = Byte.MAX_VALUE + 1;//发生了类型提升
编译器会报如下错误:
如果我们直接打印Byte.MAX_VALUE + 1的值,我们得到的结果是128,因为 println 默认是以整形进行打印的。
整型提升:对于小于4字节的类型的数据进行算术运算,会先提升为整型再进行算术运算。 byte d = b + c; 进行运算,会先把b和c提升为整型再进行相加,结果还是一个整型。
public static void main(String[] args) {
byte b = 10;
byte c = 20;
byte d = (byte)(b + c);//强制类型转换时类型必须带括号
int d2 = b + c;
System.out.println(d);
}
整型提升:对于小于4字节的类型的数据进行算术运算,会先提升为整型再进行算术运算。
byte d = b + c;进行运算,会先把b和c提升为整型再进行相加,结果还是一个整型。
1.4 短整型(short)
short 占用了2个字节,其范围为-32768~32767。
public static void main(String[] args){
short sh = 12;
System.out.println(Short.MAX_VALUE);
System.out.println(Short.MIN_VALUE);
}
1.5 双精度浮点型(double)
Java 中的 double 虽然也是 8 个字节,但是浮点数的内存布局和整数差别很大,不能单纯的用 2 ^ n 的形式表示数据范围。
public static void main(String[] args){
double d = 12.5;//默认12.5是双精度类型
System.out.println(d);
System.out.println(Double.MAX_VALUE);
System.out.println(Double.MIN_VALUE);
}
Java 的 double 类型的内存布局遵守 IEEE 754 标准(和C语言一样),尝试使用有限的内存空间表示可能无限的小数, 势必会存在一定的精度误差。
public static void main(String[] args){
int a = 1;
int b = 2;
System.out.println(a / b);
// 执行结果-----0
double a = 1.0;
double b = 2.0;
System.out.println(a / b);
// 执行结果-----0.5
double num = 1.1;
System.out.println(num * num);
// 执行结果-----1.2100000000000002
1.6 单精度浮点(float)
float 类型在 Java 中占四个字节,同样遵守 IEEE 754 标准。由于表示的数据精度范围较小, 一般在工程上用到浮点数都优先考虑 double,不太推荐使用 float。
在定义 float 类型时,要在小数后面加f,不加默认是double类型。
public static void main(String[] args){
float f = 12.3f;//4个字节,不加f默认是double类型
System.out.println(f);
}
在 Java 中,不允许把一个 double 类型的值直接赋值给 float ,会出现编译错误,体现出 Java 的安全性。C语言是一个弱类型语言, Java 是一个强类型语言,以下代码在C语言中成立。
1.7 字符类型变量(char)
- Java 中使用 单引号 + 单个字母 的形式表示字符字面值。
- 计算机中的字符本质上是一个整数。在 C 语言中使用 ASCII 表示字符, 而 Java 中使用 Unicode 表示字符。因此一个字符占用两个字节,表示的字符种类更多,包括中文。取值范围0~65535。
//char类型对应的包装类是Character
public static void main(String[] args){
char ch = 'a';
System.out.println(ch);
// 执行结果-----a
char ch2 = '陈';
System.out.println(ch2);
// 执行结果-----陈
char ch3 = 98;
System.out.println(ch3);
// 执行结果-----b,打印的是98所代表的ASCII字符
}
1.8 布尔类型(boolean)
- 在 Java 中布尔类型没有明确的大小,有些 JVM 的实现是占 1 个字节, 有些是占 1 个比特位。
- 布尔类型只有两个取值:true和false。
- 在 Java 中没有所谓的0是假,非0是真,真只有true,假只有false。
public static void main(String[] args){
boolean flg = false;
System.out.println(flg);
}
总结:
1.Java 当中的8种基本数据类型是以下几种:byte、char、short、int、long、float、double、boolean;
2.它们对应的包装类:Byte、Character、Short、Integer、Long、Float 、Double、Boolean;
3.对应的字节数:1、2、2、4、8、4、8、没有规定(0/1)。
二、运算符
2.1 算术运算符
基本四则运算符 + - * / %
规则比较简单,值得注意的是除法:
a) int / int 结果还是 int, 需要使用 double 来计算。
public static void main(String[] args){
int a = 1;
int b = 2;
System.out.println(a / b);
// 执行结果-----0
double a = 1.0;
double b = 2.0;
System.out.println(a / b);
// 执行结果-----0.5
}
b) 0 不能作为除数。
c) % 表示取余,不仅仅可以对 int 求模,也能对 double 来求模。
System.out.println(11.5 % 2.0);
// 运行结果-----1.5
增量赋值运算符 += -= *= /= %=
public static void main(String[] args){
int a = 10;
a += 1; // 等价于 a = a + 1
System.out.println(a);
}
自增/自减运算符 ++ –
1.如果不取自增运算的表达式的返回值,则前置自增和后置自增没有区别。
2.如果取表达式的返回值,则前置自增的返回值是自增之后的值,后置自增的返回值是自增之前的值。
2.2 关系运算符
关系运算符主要有六个:== != < > <= >=
public static void main(String[] args){
int a = 10;
int b = 20;
System.out.println(a == b);
System.out.println(a != b);
System.out.println(a < b);
System.out.println(a > b);
System.out.println(a <= b);
System.out.println(a >= b);
}
注意: 关系运算符的表达式返回值都是 boolean 类型。
2.3 逻辑运算符
逻辑运算符主要有三个:&& || !
注意: 逻辑运算符的操作数(操作数往往是关系运算符的结果)和返回值都是 boolean
逻辑与 &&
规则:两个操作数都为 true,结果为 true,否则结果为 false。
public static void main(String[] args){
int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b && b < c);
}
逻辑或 ||
规则:两个操作数都为 false, 结果为 false,否则结果为 true。
public static void main(String[] args){
int a = 10;
int b = 20;
int c = 30;
System.out.println(a < b || b < c);
}
逻辑非 !
规则:操作数为 true,结果为 false;操作数为 false,结果为 true(这是个单目运算符,只有一个操作数)。
public static void main(String[] args){
int a = 10;
int b = 20;
System.out.println(!a < b);
}
短路求值:&& 和 || 遵守短路求值的规则
System.out.println(10 > 20 && 10 / 0 == 0); // 打印 false
System.out.println(10 < 20 || 10 / 0 == 0); // 打印 true
我们都知道,计算 10 / 0 会导致程序抛出异常。但是上面的代码却能正常运行,说明 10 / 0 并没有真正被求值。
- 对于 && ,如果左侧表达式值为 false,则表达式的整体的值一定是 false,无需计算右侧表达式。
- 对于 || ,如果左侧表达式值为 true,则表达式的整体的值一定是 true,无需计算右侧表达式。
& 和 | (不推荐使用)
& 和 | 如果操作数为 boolean 的时候,也表示逻辑运算。但是和 && 以及 || 相比,它们不支持短路求值。
System.out.println(10 > 20 & 10 / 0 == 0); // 程序抛出异常
System.out.println(10 < 20 | 10 / 0 == 0); // 程序抛出异常
2.4 位运算符
Java 中对数据的操作的最小单位不是字节,而是二进制位。
位运算符主要有四个:& | ~ ^
位操作表示按二进制位运算。计算机中都是使用二进制来表示数据的(01构成的序列),按位运算就是在按照二进制位的每一位依次进行计算。
按位与 &:如果两个二进制位都是 1,则结果为 1,否则结果为 0。
int a = 10;
int b = 20;
System.out.println(a & b);
按位或 |:如果两个二进制位都是 0, 则结果为 0,否则结果为 1。
运算方式和按位于类似。
当 & 和 | 的操作数为整数(int, short, long, byte) 的时候,表示按位运算,当操作数为 boolean 的时候,表示逻辑运算。
按位取反 ~:如果该位为 0 则转为 1,如果该位为 1 则转为 0。
int a = 0xf;
System.out.printf("%x\n", ~a)
按位异或 ^:如果两个数字的二进制位相同,则结果为 0,相异则结果为 1。
2.5 移位运算
移位运算符有三个:<< >> >>>,都是按照二进制位来运算。
左移 <<:最左侧位不要了,最右侧补 0。
int a = 0x10;
System.out.printf("%x\n", a << 1);
// 运行结果(按十六进制打印的)-----20
右移 >>:最右侧位不要了,最左侧补符号位(正数补0,负数补1)。
int a = 0x10;
System.out.printf("%x\n", a >> 1);
// 运行结果-----8
int b = 0xffff0000;
System.out.printf("%x\n", b >> 1);
// 运行结果-----ffff8000
无符号右移 >>>:最右侧位不要了,最左侧补 0。
int a = 0xffffffff;
System.out.printf("%x\n", a >>> 1);
// 运行结果-----7fffffff
- 左移 1 位,相当于原数字 * 2。左移 N 位,相当于原数字 * 2 的N次方。
- 右移 1 位,相当于原数字 / 2。右移 N 位,相当于原数字 / 2 的N次方。
- 由于计算机计算移位效率高于计算乘除,当某个代码正好乘除 2 的N次方的时候可以用移位运算代替。
- 移动负数位或者移位位数过大都没有意义。
2.6 条件运算符
条件运算符只有一个:表达式1 ? 表达式2 : 表达式3
当 表达式1 的值为 true 时,整个表达式的值为 表达式2 的值;当 表达式1 的值为 false 时,整个表达式的值为 表达式3 的值,也是 Java 中唯一的一个 三目运算符,是条件判断语句的简化写法。
// 求两个整数的最大值
int a = 10;
int b = 20;
int max = a > b ? a : b;
2.7 运算符的优先级
运算符之间是有优先级的,具体的规则不必记忆。在可能存在歧义的代码中加上括号即可。
总结:
1.% 操作再 Java 中也能针对 double 来计算。
2.需要区分清楚 前置自增 和 后置自增之间的区别。
3.由于 Java 是强类型语言,因此对于类型检查较严格,因此像 && 之类的运算操作数必须是 boolean。
4.要区分清楚 & 和 | 什么时候是表示按位运算,什么时候表示逻辑运算。