基本数据类型转换
自动类型转换:容量小的类型自动转换为容量大的数据类型就是自动类型转换
有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算。
byte,short,char之间不会相互转换,他们三者在计算时首先转换为int类型。
boolean类型不能与其它数据类型运算。
当把任何基本数据类型的值和字符串(String)进行连接运算时(+),基本数据类型的值将自动转化为字符串(String)类型。
数据类型按容量大小排序为:
代码演示,自动类型转换
/*
当数据类型不一样时,将会发生数据类型转换。
自动类型转换(隐式)
1. 特点:代码不需要进行特殊处理,自动完成。
2. 规则:数据范围从小到大。
强制类型转换(显式)
*/
public class Demo01DataType {
public static void main(String[] args) {
System.out.println(1024); // 这就是一个整数,默认就是int类型
System.out.println(3.14); // 这就是一个浮点数,默认就是double类型
// 左边是long类型,右边是默认的int类型,左右不一样
// 一个等号代表赋值,将右侧的int常量,交给左侧的long变量进行存储
// int --> long,符合了数据范围从小到大的要求
// 这一行代码发生了自动类型转换。
long num1 = 100;
System.out.println(num1); // 100
// 左边是double类型,右边是float类型,左右不一样
// float --> double,符合从小到大的规则
// 也发生了自动类型转换
double num2 = 2.5F;
System.out.println(num2); // 2.5
// 左边是float类型,右边是long类型,左右不一样
// long --> float,范围是float更大一些,符合从小到大的规则
// 也发生了自动类型转换
float num3 = 30L;
System.out.println(num3); // 30.0
byte b = 1;
short s = 2;
char c = '3';
//byte + short +char --->int + int + int -->int
int result = b + s + c;
System.out.println(result);//54
}
}
强制类型转换:自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型就是强制类型转换。
特点:代码需要进行特殊的格式处理,不能自动完成。
格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据;
代码演示,强制类型转换:
public class Demo02DataType {
public static void main(String[] args) {
// 左边是int类型,右边是long类型,不一样
// long --> int,不是从小到大
// 不能发生自动类型转换!
// 格式:范围小的类型 范围小的变量名 = (范围小的类型) 原本范围大的数据;
int num = (int) 100L;
System.out.println(num);//100
}
}
强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出
public class Demo03DataType {
public static void main(String[] args) {
// long强制转换成为int类型,数据溢出
int num2 = (int) 6000000000L;
System.out.println(num2); // 1705032704
// double --> int,强制类型转换,精度损失
int num3 = (int) 3.99;
System.out.println(num3); // 3,这并不是四舍五入,所有的小数位都会被舍弃掉
}
}
注意事项
强制类型转换不推荐使用
浮点转成整数,直接取消小数点,可能造成数据损失精度。
范围大的数据类型的值超过了范围小的数据类型的最大范围,则会出现数据溢出。
编译器的2个优化
优化1:对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(char)。
如果没有超过左侧的范围,编译器补上强转。
如果右侧超过了左侧范围,那么直接编译器报错。
代码演示:
public class DemoNotice {
public static void main(String[] args) {
// 右侧确实是一个int数字,但是没有超过左侧的范围,就是正确的。
// int --> byte,不是自动类型转换
byte num1 = /*(byte)*/ 30; // 右侧没有超过左侧的范围
System.out.println(num1); // 30
// byte num2 = 128; // 右侧超过了左侧的范围
// int --> char,没有超过范围
// 编译器将会自动补上一个隐含的(char)
char zifu = /*(char)*/ 65;
System.out.println(zifu); // A
}
}
优化2:在给变量进行赋值的时候,如果右侧的表达式当中全都是常量,没有任何变量,那么编译器javac将会直接将若干个常量表达式计算得到结果。short result = 5 + 8; // 等号右边全都是常量,没有任何变量参与运算编译之后,得到的.class字节码文件当中相当于【直接就是】:short result = 13;右侧的常量结果数值,没有超过左侧范围,所以正确。这称为“编译器的常量优化”。但是注意:一旦表达式当中有变量参与,那么就不能进行这种优化了。
代码举例
public class DemoNotice {
public static void main(String[] args) {
short num1 = 10; // 正确写法,右侧没有超过左侧的范围,
short a = 5;
short b = 8;
// short + short --> int + int --> int
// short result = a + b; // 错误写法!左侧需要是int类型
// 右侧不用变量,而是采用常量,而且只有两个常量,没有别人
short result = 5 + 8;
System.out.println(result);
short result2 = 5 + a + 8; // 18
}
}
基本数据类型之间是存在固定的转换规则的,现总结出以下 6 条规则,无论是哪个程序,将这 6 个规则套用进去,问题迎刃而解:
八种基本数据类型中,除 boolean 类型不能转换,剩下七种类型之间都可以进行转换;
如果整数型字面量没有超出 byte,short,char 的取值范围,可以直接将其赋值给byte,short,char 类型的变量;
小容量向大容量转换称为自动类型转换,容量从小到大的排序为:byte < short(char)
大容量转换成小容量,称为强制类型转换,编写时必须添加“强制类型转换符”,但运行时可能出现精度损失,谨慎使用;
byte,short,char 类型混合运算时,先各自转换成 int 类型再做运算;
多种数据类型混合运算,各自先转换成容量最大的那一种再做运算;
关于进制
所有数字在计算机底层都以二进制形式存在。
对于整数,有四种表示方式:
二进制(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
代码演示,进制的基本使用:
/*
程序当中输出:
输出整数常量
小数常量
布尔常量
字符常量
字符串常量
*/
public class Demo03{
public static void main(String[] args){
//输出整数 十进制
System.out.println(50);//50
//输出整数,二进制, 数字开头0B
System.out.println(0B11);//3
//输出整数,八进制,数字开头0
System.out.println(051);//41
//输出整数,十六进制,数组开头0X 0-9 A-F
System.out.println(0XE);//14
//输出浮点数据
System.out.println(5.0);//5.0
//输出布尔数据,只有2个值,true,false 关键字
System.out.println(true);//true
System.out.println(false);//false
//输出字符常量,单引号包裹,只能写1个字符
System.out.println('a');//a
//输出字符串常量,双引号包裹,可以写0-n个字符
System.out.println("HelloWorld");//HelloWorld
}
}
二进制
Java整数常量默认是int类型,当用二进制定义整数时,其第32位是符号位; 当是long类型时,二进制默认占64位,第64位是符号位
二进制的整数有如下三种形式:
原码:直接将一个数值换成二进制数。最高位是符号位
负数的反码:是对原码按位取反,只是最高位(符号位)确定为1。
负数的补码:其反码加1。
计算机以二进制补码的形式保存所有的整数。
正数的原码、反码、补码都相同
负数的补码是其反码+1
为什么要使用原码、反码、补码表示形式呢?
计算机辨别“符号位”显然会让计算机的基础电路设计变得十分复杂!于是 人们想出了将符号位也参与运算的方法.我们知道,根据运算法则减去一个正 数等于加上一个负数,即: 1-1 = 1 + (-1) = 0 ,所以机器可以只有加法而没有 减法,这样计算机运算的设计就更简单了。