JavaSE:数据类型转换、运算符
一、数据类型转换(Conversion)
基本数据类型之间的转换(基本<==>基本)
引用数据类型之间的转换(引用<==>引用)
基本数据类型和包装类型之间的转换(基本<==>包装)
基本数据类型和字符串类型之间的转换(基本<==>字符串)
基本数据类型之间的转换
七种数值类型之间的转换:
自动类型转换(隐式类型转换)
强制类型转换(显式类型转换)
基本数据类型取值范围从小到大的顺序
byte < short < int < long < float < double
char < int < long < float < double
面试题:long类型在内存中占8个字节,float类型在内存中占4个字节,为什么long还要比float小呢?
基本数据类型之间的转换和占用内存没有关系
long取值范围最大值 < 2^63
float取值范围的最大值 > 3.4 * 10^38
> 2 * 10^38
> 2 * 8^38
= 2 * (2^3)^38
= 2 * 2^114
= 2^115
自动类型转换(隐式类型转换)
将取值范围较小的数据类型转换取值范围较大的数据类型
强制类型转换(显式类型转换)
将取值范围较大的类型转换为取值范围较小的数据类型
格式:
取值范围较小的数据类型 变量名 = (取值范围较小的数据类型)取值范围较大的数据类型的数据值;
int num01 = (int)3.999;//num01=3(精度缺失)
byte num02 = (byte)130;//num02=-126(数据溢出),130超出byte数据类型取值范围,由原反补原理计算出的-126
基本数据类型转换的注意事项:
1.在进行转换的时候,最后的结果数据取决于前面的数据类型
2.基本数据类型之间转换是7种数值类型之间的转换,所以boolean类型不可以转换
3.强制类型转换一般不推荐使用,因为有可能发生精度损失、数据溢出
4.byte,short,char在参与数学运算的时直接发生越级提升,先转换为int类型,再参与运算
byte b1 = 3;
byte b2 = 4;
byte sum = (byte)(b1 + b2);//7
System.out.println(sum);
//byte sum = b1 + b2;//错误: 不兼容的类型: 从int转换到byte可能会有损失
二、常量(Constant)、变量(Variable)
常量 (Constant)
在程序运行的过程中,其值不可以发生改变的量
常量的分类:
自定义常量:通过final关键字定义(面向对象的时候讲解)
字面值常量:
就是单独的一个值,没有任何的实际意义,需要借助其它语句进行使用
字面值常量分类:
字符串字面值常量("HelloWorld")
整数字面值常量(123)
小数字面值常量(12.3)
字符字面值常量('A')
布尔字面值常量(true ,false)
空字面值常量(null)
null不可以用输出语句直接进行打印
常量使用时的注意事项
1.在程序中,如果给byte,short,char进行声明初始化赋值的时候,右面初始化值需要满足字面值常量,另外这个字面值常量的取值范围还需要在该数据类型的取值范围内,JVM中的常量区自动将其优化给对应的数据类型(常量优化机制一)
2.在针对字面值常量运算操作的时候,如果符号两边都是字面值常量,在编译时期JVM中的常量区自动将其运算完毕(常量优化机制二)
//byte num01 = 123.0;报错,超出byte取值范围
char num03 = 65;
System.out.println(num03);//A
byte b1 = 3;
byte b2 = 4;
byte sum = 3 + 4; // 3+4在编译时期已经计算出结果,在运行java时运行的是byte sum = 7;(常量优化机制二)
变量(Variable)
在程序执行的过程中,其值可以发生改变的量
变量的定义格式:
数据类型 变量名 = 数据值;
两种常见的输出语句
直接输出语句:输出内容,不后续处理
System.out.print(输出内容);
换行输出语句:输出内容,然后做换行处理
System.out.println(输出内容);
注意事项:
1.换行输出语句如果没有任何输出内容,直接做换行处理
2.直接输出语句如果没有任何输出内容,编译报错
public class Basic {
public static void main (String[] args) {
System.out.println("Hello");
System.out.println();
//System.out.print(); 错误: 对于print(没有参数), 找不到合适的方法
System.out.println("World");
}
}
三、运算符(Operator)
运算符的分类
运算符:在程序中进行连接常量或者变量的符号
表达式:在程序中用运算符连接起来的式子
例如:a + b
1、算术运算符
四则运算、求余运算、自增自减
[+ 、 - 、 * 、 / 、 % 、 ++ 、 --]
被除数 / 除数 = 商 ...... 余数
/ 和 % 区别:("/"在整数型数据运算过程中为求商)
/ : 两个数相除的商
% : 两个数相除的余数
+号的多种用法:
加法运算
字符串连接符
当+的两边有任意一边存在字符串的时候,+号不在是加法运算符了,变成字符串连接符
System.out.println("Hello" + 5 + 20);//Hello520
System.out.println(5 + 20 + "Hello");//25Hello
System.out.println('a' + 1);//98
System.out.println("a" + 1);//a1
System.out.println("" + 'a' + 1);//a1
+ +和- -(自增和自减)
格式:
++变量名, 变量名++;
使用分类:
单独使用
无论++在前还是++在后,运算的结果都是一样的
复合使用
如果++在前,先自增,后运算
如果++在后,先运算,后自增
int x = 3;
int y = x++ + ++x;
// 3(x=4) + 5(x=5)
int z = ++x + x++;
// 4(x=4) + 4(x=5)
/*
练习:获取一个四位数的个位,十位,百位,千位
分析:
1.声明初始化一个四位整数
2.分别求出四位数的个位,十位,百位,千位
3.分别打印四位数的个位,十位,百位,千位
规律:
求一个整数某个位上数字其实就用这个数除以这个位上的权重,对10进行取余运算
*/
public class OperatorDemo02 {
public static void main (String[] args) {
//1.声明初始化一个四位整数
int num = 1234;
//2.分别求出四位数的个位,十位,百位,千位
int ge = num / 1 % 10;
int shi = num / 10 % 10;
int bai = num / 100 % 10;
int qian = num / 1000 % 10;
//3.分别打印四位数的个位,十位,百位,千位
System.out.println("四位数个位上数字是:" + ge);
System.out.println("四位数十位上数字是:" + shi);
System.out.println("四位数百位上数字是:" + bai);
System.out.println("四位数千位上数字是:" + qian);
}
}
2、赋值运算符
基础的赋值运算符:=
扩展的赋值运算符: += 、 -=、 *= 、/= 、%=
将符号左边的内容和右边的内容进行运算操作,将结果赋值给符号左边的变量
注意事项:
使用扩展的赋值运算符将运算后的结果赋值给左边的变量之前,隐含做了一步强制类型转换
a = 3;
b = 4;
a += b * 5;//23(“+=”符号左侧内容与右侧内容相加赋值给左侧变量)
int b1 = 3;
byte b2 = 4;
//b2 = b2 + b1;不兼容的类型: 从int转换到byte可能会有损失
b2 += b1;
3、关系运算符
[ < ,<= ,> ,>= ,== ,!= ]
注意事项:
关系表达式的结果一定是boolean值(true 或者 false)
千万不要将==写成=或者不要将=写成==
== 判断两个基本数据类型的数据值是否相等,等则true
!= 判断两个基本数据类型的数据值是否不等,不等则true
4、逻辑运算符
逻辑运算符,是用来连接两个布尔类型结果的运算符( ! 除外),运算结果一定是boolean值 true 或者 false
& 和 && 区别
&和&&的结果是一样的;
&&具有短路效果,如果&&前面的表达式结果为false时,后面表达式不会被运行;
&的话无论前面的表达式结果是什么,后面的表达式都会执行
| 和 || 区别
| 和||的结果是一样的;
|| 具有短路效果,如果||前面的表达式结果为true时,后面表达式不会被运行;
| 的话无论前面的表达式结果是什么,后面的表达式都会执行
5、三元运算符(三目运算符)
含有三个未知量的运算符
格式:
关系表达式 ? 结果1 : 结果2
执行流程:
1.先确认关系表达式的结果是true还是false
2.如果是true,执行结果1;
如果是false,执行结果2
需求:求两个数中较大值
注意事项:当三元运算符根据布尔值选择结果值后,另外一个结果值不做任何执行
int a = 3;
int b = 4;
//求两个数中较大值
int max = a > b ? a : b;//4
System.out.println("max = " + max);
//当三元运算符根据布尔值选择结果值后,另外一个结果值不做任何执行
max = a > b ? ++a : ++b;
System.out.println("a = " + a);//3
System.out.println("b = " + b);//5
6、原码,反码,补码(了解)
原码,反码,补码都是计算机中对数字的二进制定点表示方法
原码:计算机中看见的数据的二进制
反码:在计算机中,将所有原码和补码进行转换的中间量
补码:在计算机中,所有的数据的计算都是以数据的补码的形式进行计算的。
原,反,补码运算规则:
如果数据是正整数,数据的原反补是一样
如果数据是负整数:
原码:在普通二进制的基础上,增加符号位,正数为0,负数为1
反码:在原码的基础上进行取反,符号位保持不变
补码:在反码的基础上进行+1运算
byte num02 = (byte)130;//num02=-126(数据溢出)
int类型130的原码:00000000 00000000 00000000 10000010
int类型130的反码:00000000 00000000 00000000 10000010
int类型130的补码:00000000 00000000 00000000 10000010
针对补码进行强转:(4字节>>>1字节)
//在计算机中,所有的数据的计算都是以数据的补码的形式进行计算的。
byte类型结果的补码:10000010
byte类型结果的反码:10000001
byte类型结果的原码:11111110 (-126)
7、位运算符(了解)
& | ^ 这三个运算符是所有运算符中的"墙头草",当这三个符号两边的结果是布尔值,就是逻辑运算符,如果两边是数据值,就是位运算符
& :按位与,当两位同为1时才返回1
| :按位或,只要有一位为1即可返回1
^ :按位异或。当两位相同时返回0,不同时返回1(包括符号位)
~ :按位非,将操作数的每个位(包括符号位)全部取反
<< :左移运算符 将指定的数据往左移动指定的位数
格式:指定的数据 << 指定的位数
特点:当低位出现了空位,直接进行补0,符号位也随之移动
>> :右移运算符 将指定的数据往右移动指定的位数
格式:指定的数据 >> 指定的位数
特点:当高位出现了空位,直接补和符号位相同的数字
>>> :无符号右移 将指定的数据往右移动指定的位数
格式:指定的数据 >>> 指定的位数
特点:当高位出现了空位,不需要考虑符号位,直接补0,符号位也随之移动
public class OperatorDemo08 {
public static void main (String[] args) {
//& | ^两边是数据值,就是位运算符
//位运算所有的数据的计算都是以数据的补码的形式进行计算的
//&:按位与,当两位相同时为1时才返回1
System.out.println(5 & 9);//1
System.out.println(-5 & -9);//-13
System.out.println("=============================");
//|:按位或,只要有一位为1即可返回1
System.out.println(5 | 9);//13
System.out.println(-5 | -9);//-1
System.out.println("=============================");
//^:按位异或。当两位相同时返回0,不同时返回1
System.out.println(5 ^ 9);//12
System.out.println(-5 ^ -9);//12
System.out.println("=============================");
//~:按位非,将操作数的每个位(包括符号位)全部取反
System.out.println(~5);//-6
System.out.println(~-5);//4
System.out.println("=============================");
//<<:左移运算符 将指定的数据往左移动指定的位数,当低位出现了空位,直接进行补0,符号位也随之移动
System.out.println(5 << 2);//20
System.out.println(-5 << 2 );//-20
System.out.println(1073741823 << 2);//-4
System.out.println("=============================");
//>>:右移运算符 将指定的数据往右移动指定的位数,当高位出现了空位,直接补和符号位相同的数字
System.out.println(5 >> 2);//1
System.out.println(-5 >> 2);//-2
System.out.println("=============================");
//>>>:无符号右移运算符 将指定的数据往右移动指定的位数,当高位出现了空位,不需要考虑符号位,直接补0,符号位也随之移动
System.out.println(5 >>> 2);//1
System.out.println(-5 >>> 2);//1073741822
}
}
8、运算符的优先级
注意事项:
不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成;
不要过多的依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用()来控制表达式的执行顺序
int i = 3;
i = i++;
System.out.println("i = " + i);//3