基本数据类型转换
- Java程序中要求参与的计算的数据,必须要保证数据类型的一致性,如果数据类型不一致将发生类型的转换。java中数据类型转换分为自动类型转换和强制类型转换。
自动类型转换
一个 int 类型变量和一个 byte 类型变量进行加法运算, 结果会是什么数据类型?
public class Demo {
public static void main(String[] args) {
int a = 41;
byte b = 66;
// byte result = a + b; 错误,不能使用byte类型的数据接收结果
int result = a + b;
}
}
运算结果,变量的类型将是 int 类型,这就是出现了数据类型的自动类型转换现象。byte 类型内存占有1个字节,在和 int 类型运算时会提升为 int 类型 ,自动补充3个字节,因此计算后的结果还是 int 类。同样道理,当一个 int 类型变量和一个 double 变量运算时, int 类型将会自动提升为 double 类型进行运算。数据之间的运算包括赋值,计算.....
概念:将 取值范围小的类型 自动提升为 取值范围大的类型 就是自动类型转换
特点:代码不需要进行特殊处理,自动完成。
数据类型按容量大小排序为:
- 有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
- byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
- boolean类型不能与其它数据类型运算。
举例:
public class Demo01DataType {
public static void main(String[] args) {
byte b = 2;
short s = 129;
/*
byte b2 = b + s; 编译不通过
byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
int类型的数据不能直接赋值给byte类型的变量去接收
*/
int i = b + s;
System.out.println(i);//131
//int + short -->int 可以直接赋值给long类型的变量接收
long l = b + i;
System.out.println(l);//133
//int + short -->int 可以直接赋值给float类型的变量接收
float f = b + i;
System.out.println(f);//133.0
// short 赋值给double 符合自动类型转换的条件
double d = s;
System.out.println(d);//129.0
char c = 'a';
// char + int --> int
int result = c + i;
System.out.println(result);//228
/*
左边是float类型,右边是long类型,左右不一样
long类型赋值给float类型存储,范围是float更大一些,符合从小到大的规则
也发生了自动类型转换
*/
float f1 = 30L;
System.out.println(f1); // 30.0
}
}
强制类型转换
将 1.5 赋值到 int 类型变量会发生什么?产生编译失败,肯定无法赋值
int i = 1.5; // 错误
double 类型内存8个字节, int 类型内存4个字节。 1.5 是 double 类型,取值范围大于 int 。可以理解为 double 是8升的水壶, int 是4升的水壶,不能把大水壶中的水直接放进小水壶去。想要赋值成功,只有通过强制类型转换,将 double 类型强制转换成 int 类型才能赋值。自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使 用时要加上强制转换符:(),但可能造成精度降低或溢出,格外要注意。
- 概念:将 取值范围大的类型 强制转换成 取值范围小的类型 。
- 格式:数据类型 变量名=(数据类型)被转数据值;
- 特点:代码需要进行特殊的格式处理,不能自动完成。
将 1.5 赋值到 int 类型要想成功就必须使用强制类型转换,代码修改为:
// double类型数据强制转成int类型,直接去掉小数点。
int i = (int)1.5;
同样道理,当一个 short 类型与 1 相加,我们知道会类型提升,但是还想给结果赋值给short类型变量,就需要强制转换。
注意事项:
- 强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出。
-
boolean 类型不可以转换为其它的数据类型。
举例:
/*
1. 特点:代码需要进行特殊的格式处理,不能自动完成。
2. 格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据;
*/
public class Demo02DataType {
public static void main(String[] args) {
/* 左边是int类型,右边是long类型,不一样
long 类型交给 int类型存储,不是符合知道类型转换的规则
不能发生自动类型转换!要想编译成功就必须使用强制类型转换
格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据;
*/
int num = (int) 100L;
System.out.println(num);//100
// long强制转换成为int类型,可能发生数据溢出。
int num2 = (int) 6000000000L;
System.out.println(num2); // 1705032704
// double 强制类型转成为 int,会发生精度损失。这并不是四舍五入,所有的小数位都会被舍弃掉
int num3 = (int) 3.99;
System.out.println(num3); // 3
/*
这是一个字符型变量,里面是大写字母A
计算机的底层会用一个数字(二进制)来代表字符A,就是65
一旦char类型进行了数学运算,那么字符就会按照一定的规则翻译成为一个数字
*/
byte b1 = 40;
short s = 60;
/*
byte + short --> int + int --> int
数据范围大的类型强制转换为数据范围小的类型:
注意必须保证逻辑上真实大小本来就没有超过short范围,否则会发生数据溢出
*/
short result = (short) (b1 + s);
System.out.println(result); // 100
}
}
字符串类型:String
- String不是基本数据类型,属于引用数据类型
- 使用方式与基本数据类型一致。例如:String str = “abcd”;
- 一个字符串可以串接另一个字符串,也可以直接串接其他类型的数据。
- 对于字符串String来说,加号代表字符串连接操作。任何数据类型和字符串进行连接的时候,结果都会变成字符串
- 通常,字符串不能直接转换为基本类型,但通过基本类型对应的包装类则可 以实现把字符串转换成基本类型。
举例:
/*
String类型变量的使用
1. String属于引用数据类型,翻译为:字符串
2. 声明String类型变量时,使用一对""
3. String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+ 运算的结果仍然是String类型
*/
class StringTest {
public static void main(String[] args) {
//练习1
char c = 'a';//97
int num = 10;
String str = "a";
System.out.println(c + num + str);//107a
System.out.println(c + str + num);//aa10
System.out.println(c + (num + str));//a10a
System.out.println((c + num) + str);//107a
System.out.println(str + num + c);//a10a
//练习2
//* *
System.out.println("* *");//* *
System.out.println('*' + '\t' + '*');//93
System.out.println('*' + "\t" + '*');//* *
System.out.println('*' + '\t' + "*");//51*
System.out.println('*' + ('\t' + "*"));//* *
String str1 = 123 + "";
System.out.println(str1);//"123"
//字符串转换为int类型
int num1 = Integer.parseInt(str1);
System.out.println(num1);//123
}
}
关于进制
所有数字在计算机底层都以二进制形式存在。
对于整数,有四种表示方式:
- 二进制(binary):0,1 ,满2进1.以0b或0B开头。
- 十进制(decimal):0-9 ,满10进1。
- 八进制(octal):0-7 ,满8进1. 以数字0开头表示。
- 十六进制(hex):0-9及A-F,满16进1. 以0x或0X开头表示。此处的A-F不区分大小写。 如:0x21AF +1= 0X21B0
package demo.binary;
class BinaryTest {
public static void main(String[] args) {
//二进制(binary):0,1 ,满2进1.以0b或0B开头。
int num1 = 0b110;
//十进制(decimal):0-9 ,满10进1。
int num2 = 110;
//八进制(octal):0-7 ,满8进1. 以数字0开头表示。
int num3 = 0127;
//十六进制(hex):0-9及A-F,满16进1. 以0x或0X开头表示。此处的A-F不区分大小写。
int num4 = 0x110A;
System.out.println("num1 = " + num1);//num1 = 6
System.out.println("num2 = " + num2);//num2 = 110
System.out.println("num3 = " + num3);//num3 = 87
System.out.println("num4 = " + num4);//num4 = 4362
}
}
二进制
- Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位; 当是long类型时,二进制默认占64位,第64位是符号位
二进制的整数有如下三种形式:
- 原码:直接将一个数值换成二进制数。最高位是符号位
- 负数的反码:是对原码按位取反,只是最高位(符号位)确定为1。
- 负数的补码:其反码加1。
计算机以二进制补码的形式保存所有的整数。
正数的原码、反码、补码都相同
负数的补码是其反码+1
为什么要使用原码、反码、补码表示形式呢?
- 计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂! 于是 人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正 数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有 减法, 这样计算机运算的设计就更简单了。
- 对于正数来讲:原码、反码、补码是相同的:三码合一。
- 计算机底层都是使用二进制表示的数值
- 计算机底层都是使用的数值的补码保存数据的。