文章目录
- 语言类型的强弱并没有好坏之分
- Java中所有的数值类型所占据的字节数量与平台无关
- 数据类型之间的转换
- 数据溢出问题
-
- 整型类型溢出
- 整型转换为字符型的溢出
语言类型的强弱并没有好坏之分
编程鼻祖C语言是有类型的语言,在C语言中的变量必须满足:“在使用前定义,并确定类型”。在C语言之后的编程语言向着两个方向发展:
- C++、Java为代表的强类型语言
更加强调类型,对类型的检查比C语言更严格。 - JavaScript、Python、PHP为代表的弱类型语言
不看重类型,甚至不需要事先定义。
一般来说,面向底层的语言更加强调类型;而越是面向应用的语言会越忽视类型,而去重视事务逻辑的处理。
Java中所有的数值类型所占据的字节数量与平台无关
C/C++中int和long等类型的大小与目标平台相关,因为程序需要针对不同的处理器选择最为高效的整型,例如,在32位处理器上long值为4字节;在64位处理器上则为8字节。这样就有可能造成一个在64位处理器上运行的很好的C程序在32位处理器上运行却发生整数溢出。这就为编写跨平台程序带来了很大的难度。
而在Java中,所有的数值类型所占据的字节数量与平台无关,即数值类型的范围与运行Java代码的机器无关,这也是Java跨平台的一个表现。
另外,Java中的int、long、short、byte类型都是有符号的。底层的二进制形式中,首位如果是 0,就是正的;首位是1就是负的。另外,char则是0-65535的无符号数,从char转换到int类型时,缺少的高16位字节用0扩展。
Java - Type | 默认值 | 大小 | 取值范围 |
---|---|---|---|
byte | 0 | 1字节 | -128 - 127 |
short | 0 | 2字节 | -32768 - 32767 |
int | 0 | 4字节 | -2147483648 to 2147483647(21亿多) |
long | 0L | 8字节 | -232-1 to (232-1-1) |
float | 0.0f | 4字节 | ±1.4E-45 to ±3.4028235E+38(有效位数为6~7位) |
double | 0.0d | 8字节 | ±4.9E-324 to ±1.7976931348623157E+308(有效位数为15位) |
char | ‘\u0000’ | 2字节 | 0-65535 |
boolean | false | 取决于Java虚拟机 | true 或 false |
输出如下:
- 不同类型的变量在内存中的表现形式是不同的,整型变量在内存中表现为
2进制数
,浮点型变量在内存中表现为编码形式
。
数据类型之间的转换
上图中,6个实心箭头的转换表示无信息丢失的转换;3个虚箭头的转换表示可能有精度损失的转换。如果两个不同的数值类型进行二元操作时,先要将两个操作数转换为同一种类型,然后再进行计算,计算规则如下:
- 如果两个操作数中,有一个是double类型,另一个操作数就会转换为double类型。
- 否则,如果其中一个操作数是float类型,另一个操作数就会转换为float类型。
- 否则,如果其中一个操作数是long类型,另一个操作数就会转换为long类型。
- 否则,两个操作数都将被转换为int类型。
特别的:整型向字符型转换时,JVM会把数字当成字符的ASCII编码来处理。
//将整型类型强制转换为字符型时,JVM会把数字当成字符的ASCII编码来处理.
char i = (char)97;
System.out.println(i);//输出:a
数据溢出问题
数据溢出问题就是:当某一种类型的数值已经达到了此类型能够保存的最大值之后,再继续扩大,或者达到了最小值后再继续缩小,就会出现数据溢出问题。
整型类型溢出
下面的代码以int类型为例,测试对int类型进行溢出测试:
package com.gql;
public class Test {
public static void main(String[] args) {
//int类型的最小值为:-2^31
int a = -2147483648;
System.out.println("int类型的最小值为:"+a);
System.out.println("int类型的最小值减1为:"+(a-1));
System.out.println("int类型的最小值减2为:"+(a-2));
System.out.println("int类型的最小值减3为:"+(a-3));
System.out.println("int类型的最小值减4为:"+(a-4));
System.out.println("//总结:超过最小值的数据会向下溢出变成正数.\n");
//int类型的最大值为2^31 - 1
a = 2147483647;
System.out.println("int类型的最大值为:"+a);
System.out.println("int类型的最大值加1为:"+(a+1));
System.out.println("int类型的最大值加2为:"+(a+2));
System.out.println("int类型的最大值加3为:"+(a+3));
System.out.println("int类型的最大值加4为:"+(a+4));
System.out.println("总结:超过最大值的数据会向上溢出变成负数.\n");
}
}
上面的代码符合了整型的数据溢出规则:即超过最大值的整型数值会向上溢出变成负数;超过最小值的整型数值会向下溢出变成正数。
前文提到过,Java中的int、long、short、byte类型都是有符号的。而在C/C++语言中,溢出规则分为两种:
- 有符号的整型溢出:“undefined behavior”,即由编译器实现,通常的编译器都是按照上面测试的整型数据溢出规则。
- 无符号的整型溢出:溢出后的数会以2^(8*sizeof(type))作模运算
整型转换为字符型的溢出
字符型数据在内存中一般情况下下占据一个字节(如今有些Unicode字符需要用两个char来描述),其存放的就是这个字符对应的ASCLL码的整数值,所以字符型数据和整型数据之间可以通用。
ASCCLL码表毕竟范围有限,在转换时也可能会出现字符型的溢出:
下面的代码演示整型向字符型转换时出现的溢出情况。
int j = (char)0;
System.out.println(j);
j = (char)-1;
System.out.println(j);
j = (char)-2;
System.out.println(j);
j = (char)-3;
System.out.println(j);
System.out.println("总结:超过最小值的数据会向下溢出变成正数");
System.out.println("-------");
j = (char)65535;
System.out.println(j);
j = (char)65536;
System.out.println(j);
j = (char)65537;
System.out.println(j);
System.out.println("总结:超过最大值的数据会向下溢出仍变成正数(因为char类型的符号位永远是0,即正数)");
可以发现整型转换为字符型时的溢出规律:
- 当超过最小值的数据时会向下溢出,变成正数,所以直接取了char类型的最大值65535。
- 当超过最大值的数据时会向上溢出,由于字符型不能变成负数,所以直接取了最小值0。
- 可以将上面两条概括理解为,超过最大值后,取最小值;超过最小值后,取最大值。