【JAVA进化论】LV1-2:java中的变量类型

一、基础变量类型

1.1:整型

即整数类型,如1,2,0,-1,-2这种。

整型变量在java中的声明方式如下:

代码块1
1
2
int a; //声明名称为a的整型变量(默认值为0)
int b = 5; //声明名称为b的整型变量(初始化值为5)

整型变量在内存中占据32个bit位(4字节),每个bit位可存储0和1,通常第一位为符号位(±),所以有效数字部分就占了31位,如图(图中表示十进制数字+6):

图1

按照这个特性,整型的取值范围为:(-2^31) ~ (2^31)-1

即:-2147483648 ~ 2147483647

除了浮点型,其余只要有符号位的类型,都符合这个范围规则。

为什么负数的数值位比正数多1,计算机是如何做减法运算的?请参考:JAVA有关位运算的全套梳理

1.2:长整型

长整型变量在java中的声明方式如下:

代码块2
1
2
long a; //声明名称为a的长整型变量(默认值为0)
long b = 5; //声明名称为b的长整型变量(初始化值为5)

这种类型所表示的数值范围相比整型的位数,多了一倍,占据64个bit位(8字节)

因此其取值范围为:(-2^64) ~ (2^64)-1

即:-9223372036854775808 ~ 9223372036854775807

1.3:短整型

短整型变量在java中的声明方式如下:

代码块3
1
2
short a; //声明名称为a的长整型变量(默认值为0)
short b = 5; //声明名称为b的长整型变量(初始化值为5)

这种类型所表示的数值范围相比整型的位数,少了一倍,只占据16个bit位(2字节)

取值范围为:(-2^15) ~ (2^15)-1

即:-32768 ~ 32767

巩固:

这里说明下,short、int、long本质上都表示整数,因此像下面这种写法都是ok的:

代码块4
1
2
3
short a = 1;
int a = 1;
long a = 1;

那为什么要如此区分呢?这就存在一个取值范围的问题,因为这三种类型的二进制位数不一样,所以他们所能容下的数值范围也不同,具体参考下图:

图2

所以今后在写程序时,需要严格推断数值的极端可能性,然后设计出合理接收数据的类型。

举个反例:比如某个系统的id,id增长特别迅速,开始设计用int类型接收id,后来id值超过了int表示数据的最大范围,就会出现很严重的问题。

1.4:单精度浮点型

浮点型变量在java中的声明方式如下:

代码块5
1
2
float a; //声明名称为a的单精度浮点型变量(默认值为0.0)
float b = 5.0f; //声明名称为b的单精度浮点型变量(初始化值为5.0)

单精度浮点型变量在内存中占据32个bit位(4字节),相比整型,它存在指数位,分布如下:

图3

取值范围为:-2^128 ~ 2^127

即:-3.40E+38 ~ +3.40E+38

注:java中如果单独写一个类似0.1这样的小数,默认是双精度,如果用float接收,会报错,一般需要在小数后面加个f修饰符(隐式类型转换)。

1.5:双精度浮点型

双精度变量在java中的声明方式如下:

代码块6
1
2
float a; //声明名称为a的浮点型变量(默认值为0.0)
float b = 5.0; //声明名称为b的浮点型变量(初始化值为5.0)

双精度浮点型变量在内存中占据64个bit位(8字节),相比单精度浮点型数据,它用来存放指数和尾数的位数明显更多,分布如下:

图4

1.6:字符型

字符变量在java中的声明方式如下:

代码块7
1
2
char a; //声明名称为a的字符型变量(默认值为0,对应的字符为空字符,BLANK)
char b = '我'; //声明名称为b的字符型变量(初始化值为汉字'我',对应的Unicode码为25105)

字符型变量在内存中占据16个bit位(2字节),java语言的字符基于Unicode,无论是数字、字母,还是汉字,均占2个字节。

按照16位的保存方式,char的数字取值区间为:0 ~ 65535

1.7:字节

字节变量在java中的声明方式如下:

代码块7
1
2
byte a; //声明名称为a的字节变量(默认值为0)
byte b = 5; //声明名称为b的字符型变量(初始化值为5)

字节变量在内存中占据8个bit位

取值区间为:(-2^7) ~ (2^7)-1

即:-128~127

一个字节就是一个数字,字节存储的数字聚合在一起就变成了字节流(byte[])字节流可以被不同的编码方式解码成具体某一个字符或者某一段语句,现有的文本信息,在计算机中以字节的方式进行存储,存储前通过某种编码方式编码,获取到时通过同样的编码方式解码即可获取到具体的文本信息。

1.8:布尔值

布尔类型的变量在java中的声明方式如下:

代码块8
1
2
boolean a; //声明名称为a的布尔变量(无初始化值时,默认值为false)
boolean b = true; //声明名称为b的布尔变量(初始化值为true)

这种类型的变量只有true或false两种值,用来表示真或假。

布尔变量在内存中占据8个bit位(1个字节,存在争议,JVM规范中提到应占4个字节)。

二、字符串类型&引用变量

上面所有的类型,均为java的基本类型,除了基本类型变量,其他的所有变量均为引用变量,这里介绍一种引用变量:String

String相比char只能表示一个字符来说,它可以用来表达一段话,它的声明方式如下:

代码块10
1
2
3
String a; //声明名称为a的String类型变量(由于其非基本类型,因此a属于引用变量,引用类型变量在不赋值的情况下默认值为null)
String b = "这是一段话"; //声明名称为b的String类型变量(初始值为:这是一段话),常用的声明字符串的方式
String c = new String("这是一段话"); //声明名称为c的String类型变量(初始值为:这是一段话)这种写法不建议

字符串的拼接也很简单:

代码块11
1
2
3
String a = "哔哩哔哩 ";
String b = "乾杯~";
String c = a + b; //c最终的结果为:哔哩哔哩 乾杯~

三、基本类型转换

我们按照基本类型所能表示的数值范围来区分它们的大小,现可以做出如下排序:

图5

所谓类型转换,就是java语法里为了程序严谨性所做的一层保护,举个例子,一个比较大的类型long,声明了一个变量,我们记为α,现在用一个比较小的类型int来接收α,这在java的语法里是不允许的,因为你不知道α的大小是不是已经超出int型所能表达的范围值了,但是相反的,如果现在声明一个int型的变量,我们记为β,这时使用long型接收β在java的语法里是允许的,因为int型的数顶天了也不可能超过long型所能表达的范围,所谓基本类型的转换就是这么回事,下面来看看具体的场景。

注:布尔类型是不参与类型转换的

4.1:强制转换

通过上面简短的介绍,已经知道了java为什么要做一些类型转换的操作,那么哪些情况下需要做强制类型转换呢?

按照类型大小排列,long型可以接收int型数据,而int型要想接收long型数据,就需要做强转,语法如下:

代码块12
1
2
3
4
5
long γ = 1; //声明long型的变量γ
int λ = (int) γ; //声明int型的变量λ,由于int型表示范围比long型小,因此有超范围的风险,因此java要求必须做一层强转

int α = 1; //声明int型的变量α
long β = α; //声明long型的变量β,使其值等于α,由于long型表示范围比int型大,因此α不需要做类型强转

比较特殊的就是short和char型变量,它们俩由于位数相同,虽然表达的取值范围不同,但是其类型大小在java眼里是相同的,所以它们俩需要互转,不存在谁比谁大的情况:

代码块12
1
2
3
4
5
6
//short和char不管由谁接收谁,均需要强转
short γ = 1;
char λ = (char) γ;

char α = 1;
short β = (short) α;

这个规则放到方法传参时同样是适用的:

代码块13
1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
short param1 = 1;
method(param1); //method接收的参数是int型,声明的参数值却是short型,short比int表达范围小,因此调用method时,不需要强转
long param2 = 1;
method((int) param2); //method接收的参数是int型,声明的参数值却是long型,调用method时,需要强转
}
//这是一个接收int型参数的方法
public static void method(int param) {
//方法逻辑省略...
}

4.2:自动转换

自动转换就是指取值范围小的数据类型可以自动转换成取值范围大的数据类型。

需要结合4.1理解,4.1介绍了强制类型转换,例子中不需要强转的统统都是自动转换的,如代码块10中的α和β的类型转换:

代码块14
1
2
int α = 1; //声明int型的变量α,值为1
long β = α; //声明long型的变量β,使其值等于α的值,由于long型表示范围比int型大,因此α的值不需要做类型强转,但其实是α的值类型已经自动转成long了

四、小结

通过本节,我们知道了java里的基本数据类型,字符串类型,以及引用变量的简单介绍。

下一节将会介绍java中的运算符,让本节里的数据通过运算”活起来“。