阿里云【名师课堂】Java零基础入门10 ~ 13:Java数据类型划分
10、整型
int、short、long
在Java程序里面任何一个整数的常量默认类型都是int型。
- 范例:定义一个整型变量
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
// 10是一个整数常量(不会改变的数据是常量)
// nums是一个整型变量
int num = 10 ; // 声明一个int型变量
// num是int型的变量 * 2是int型的常量 = 结果还是int型
System.out.println(num * 2) ;
}
}
数据溢出问题
但是在进行整型数据操作的过程中会存在一个数据溢出问题,指的是当已经达到了整型的最大或最小值,如果继续进行数学运算而可能产生的错误数据。
- 范例:观察数据溢出操作
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int maxValue = Integer.MAX_VALUE ; // 取得最大值
int minValue = Integer.MIN_VALUE ; // 取得最小值
System.out.println(maxValue) ; // 2147483647
System.out.println(minValue) ; // -2147483648
// maxValue属于int型变量 + 1是int型常量 = int型
System.out.println(maxValue + 1) ; //数据溢出(最小值):-2147483648
System.out.println(minValue - 1) ; //数据溢出(最大值):2147483647
//实际上就是二进制的加法中的符号位的操作
System.out.println(minValue - 2) ; //数据溢出(次最大值):2147483646
}
}
发现当已经超过了数据类型的局限之后,数据的计算就会出现偏差,所以要在操作前预估数据大小。那么问题是:既然已经知道了int会存在溢出的问题,怎么解决?➡使用更大范围的数据类型(long
)。
- 范例:使用
long
来解决int
的数据溢出问题
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int maxValue = Integer.MAX_VALUE ; // 取得最大值
long result = maxValue + 1 ;
System.out.println(result) ;
// 输出还是-2147483678
}
}
从上面程序我们可以看出来,数据溢出问题并没有得到解决。这是因为:所有程序的执行顺序都是由等号的右边到左边,即程序先计算了int型maxValue + 1
,然后把结果赋给了long型变量result
,这时输出当然还是 -2147483648 。
数据类型转换
所以最简单的做法是将其中一个变量首先做类型转换,数据类型转换有2种实现方式:
- 低级到高级的自动类型转换
- 容量小(低级)自动转换为容量大(高级)
- 由低到高:
byte、short、char—int—long—float—double
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int maxValue = Integer.MAX_VALUE ; // 取得最大值
int minValue = Integer.MIN_VALUE ; // 取得最小值
// 方法一 :直接将int变量的内容赋值给long变量
long result = maxValue ; // 将int型变量赋值给long型
System.out.println(result + 1) ; // result是long类型 + 1是int型 = long型(低到高自动转换)
/* 方法二:直接将某个int型变量变为long型变量
long result = (long)maxValue + 1 ; // maxValue变为了long类型 + 1是int型 = long型result
System.out.println(result) ;
*/
// 输出2147483648,成功
}
}
- 高级到低级的强制类型转换
- 强制转换的后果:丢失精度、内容
- 方法:赋值时设置需要的目标类型,格式:
type n = (type)m ;
- 注意:规范的Java格式中强制转换括号之后数据之前没有空格。(出自阿里巴巴《Java开发手册》)
范例:强制类型转换
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
// long num = 2147483648 ; // error,因为任何整数默认类型都是int型,但是2147483648已经超出了int型范围
long num = 2147483648L ; // 将超出int范围的数赋值给long型需要在末尾加上“L”或“l”,表示是一个long型常量
int result = (int) num; // 强制转换格式:type n = (type) m ;
System.out.println(result) ;
// 结果-2147483648,溢出
}
}
- java是如何处理强制类型转换的溢出处理呢?
- 在计算机中,所有的数据都是存储的补码形式(但是正数的补码是其本身)。那么原数据首先被当成int型存储,四个字节32位,转换为需要的类型时根据位数进行截取,高字节部分去除,保留低字节部分,得到转换为低级类型的补码,我们将其转换为源码,得到最后的结果。
- 正数的源码、反码、补码相同。
- 负数的反码:符号位取1,其余位取反;负数的补码:符号位取1,其余位取反,整个数再加1。
范例:2147483648L转化为int型:
- 2147483648L的补码是:······ 1000 0000 0000 0000 0000 0000 0000 0000,截取32位是负数,整个数取反:0111 1111 1111 1111 1111 1111 1111 1111,转化为10进制是2147483647,加上负号后减一:-2147483648。
- -2147483649的补码是:······ 0001 0111 1111 1111 1111 1111 1111 1111 1111,截取32位是正数,直接得到2147483647.
数据类型默认值问题
所有数据类型都有其默认值,但是这个默认值在方法的声明中(主方法)无效。
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int result ; // 定义一个result变量,没有赋值,可以输出默认值吗?
System.out.println(result) ;
// TestDemo.java:4: 错误: 可能尚未初始化变量result
}
}
两种解决方案:
- 在使用前进行赋值
范例:在使用前为变量赋值
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int result ;
result = 10 ; // 在result输出之前为变量设置内容
System.out.println(result) ;
// 输出10
}
}
- 在声明变量时赋值(推荐)
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int result = 10 ; // 在声明变量时赋值
System.out.println(result) ;
// 输出10
}
}
而对于各种数据类型默认值的使用需要结合到类的情况下才可以观察到。
byte型
范围:-128~127
- 范例:声明byte变量
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
// 10是int型,int范围要大于byte,理论上需要进行强制转换
// 可是实际上没有转换,因为其数据量符合byte要求
byte result = 10 ; // 10是int型,在byte范围内
System.out.println(result) ;
// 输出10
}
}
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
/* 当超出byte范围是还是要进行强制转换
byte result = 128 ;
System.out.println(result) ;
TestDemo.java:4: 错误: 不兼容的类型: 从int转换到byte可能会有损失
*/
byte result = (byte) 128 ;
System.out.println(result) ;
// -128
}
}
11、浮点型
- 小数的默认类型是double,double范围最大。
- float变量也可以表示小数,但是因为float范围小于double,声明变量时需要尾部加上“F”或“f”,或者采用强制转换的格式。
范例:定义double、float
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
// 定义double型变量
double dnum = 4.7 ;
// dnum是double型变量 * 2是int型常量(自动转换为double型) = double型
System.out.println((double) 2) ;
System.out.println(dnum * 2) ;
// 定义float型变量
float fnum = 1.1F ;
float ffnum = (float) 1.1 ; // 或者这样
System.out.println(fnum * ffnum) ;
System.out.println(1.1 * 1.1) ; // java传统bug
}
}
小数与整型计算问题
进行数学运算时一定注意数据类型问题,尤其是整数的除法可能会有小数。
- 范例:观察下面程序
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
int numA = 10 ;
int numB = 4 ;
// int型 / int型 = int型
System.out.println(numA / numB) ; // 结果丢失精度
// 如果要准确的进行计算,必须要保证至少有一个变量是double或float型
System.out.println(numA / (double) numB) ;
System.out.println((float) numA / numB) ;
}
}
12、字符型
虽然在开发中会使用到字符型的概念,但是真正使用字符型并不多。
字符型使用char
来定义,并且使用单引号''
来声明字符变量的内容。
同时字符型可以与int型互相转换,这是处理字符型的麻烦之处。所有的字符在程序中都是通过编码(Unicode码)描述的,所以char型变量变为int型的时候其所包含的就是编码。
- 范例:观察编码的出现
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
char c = 'A' ; // 定义一个字符变量
System.out.println(c) ;
int num = c ; // 转化为int型
System.out.println(num) ;
}
}
常用范围:
- 大写字母'A' ~ 'Z':65('A') ~ 90('Z')
- 小写字母'a' ~ 'z':97('a') ~ 122('z')
- 字符数字'0' ~ '9':48('0') ~ 57('9')
范例:大小写字母之间的转换(通过一个字母大小写之间相差32)
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
char c = 'A' ; // 定义一个字符变量
System.out.println(c) ;
// 字符变量 + int常量 = int类型
int num = c + 32 ; // 转化为int型
System.out.println(num) ;
// 将int的内容转换为字符类型:强制转换
char cc = (char) num ;
System.out.println(cc) ;
}
}
字符数字与数字不是同一个概念。
Java采用Unicode码,它包含部分ASCII码内容但是所包含的编码又多于ASCII码。Unicode用两个字节编码一个字符,即16位二进制,这个编码可以保存任何的文字信息,包括中文。
- 范例:保存中文
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
char c = '山' ;
int num = c ;
System.out.println(c) ;
System.out.println(num) ;
}
}
13、布尔型
布尔是一位数学家,建立了逻辑运算。
布尔型只表示逻辑运算的结果:true、false。
- 范例:观察布尔型的操作
public class TestDemo{ // 定义一个程序类
public static void main(String args[]){
boolean flag = 10 > 2 ; // true
System.out.println(flag) ;
if (flag) {
System.out.println("Hello World!") ;
}
}
}
在其他语言中,由于没有布尔型变量,往往使用数字表示逻辑运算结果,如:0表示false、非0表示true,但是Java没有这个概念。