【Java—超详细的数据类型转换及运算符】
目录
- 2 类型转换
-
- 2.1 常量
-
- 2.1.1 字面量常量
- 2.1.2 final 关键字修饰的常量
- 2.2 类型转换
-
- 2.2.1 int -> long
- 2.2.2 int->double
- 2.2.3 int -> byte
- 2.2.4 int char
- 2.2.5 int String
- 2.3 数据类型的默认值
- 3 运算符
-
- 3.1 算数运算符
- 3.2 增量赋值运算
- 3.3 自增和自减运算符
- 3.4 关系运算符
- 3.5 逻辑运算符
- 3.6 位运算符
- 3.7 移位运算
- 3.8 条件运算符(唯一一个三目运算符)
- 3.9 注释
2 类型转换
在学习类型转换之前,我们先来学习什么是常量?
2.1 常量
常量是指运行时类型不能发生改变。
常量主要有两种体现形式:
2.1.1 字面量常量
10 // int 字面量常量(十进制)010// int 字面量常量(八进制),由数字0开头的0x10 // int 字面量常量(十六进制),由数字0x开头10L// long字面量常量,也可以写为10l(小写的L)1.0// double字面量常量1.5e2 // double字面量常量,科学计数法表示:1.5 * 10^21.0f // float 字面量常量,也可写为1.0Ftrue // boolean字面量常量,还有False'a'// char 字面量常量,单引号中只能写一个字符"abc" // String 字面量常量,双引号中可以有多个字符
2.1.2 final 关键字修饰的常量
public class Test { public static void main(String[] args){ final int a = 10; a = 20; //不能进行修改 System.out.println(a); }}
运行上面的代码,就会编译出错:
java: 无法为最终变量a分配值
2.2 类型转换
不同数据类型间(只有相同数据类型之间可以转换,数值型之间)的转换有:
-
小类型转为大类型
小类型转为大类型是自动提升的,比如:
a. 小类型的变量值赋值给大类型时,
long b = 20; // 20默认为int字面量,此时int 类型提升为 long类型
b. 小类型和大类型进行数学运算时,首先会将小类型提升为大类型而后进行数学运算
public class Test { public static void main(String[] args){ int a = 10; double b = 2.0; System.out.println(a / b); //输出为 5.0 }}
-
大类型转为小类型
大类型转换为小类型时需要强制类型转换,可能会丢失精度。(数据溢出或者数据部分丢失)
public class Test { public static void main(String[] args){ double a = 4.2; int b = (int)a; System.out.println(b); //编译结果为 4 }}
2.2.1 int -> long
public class Test { public static void main(String[] args) { int a = 10; //这里有一个隐藏的类型转换,整型字面量默认都是int,int->long //属于是小类型转换为大类型,自动提升 long b = 20; //将int->long,自动提升 b = a; //将long->int,无法直接转换,需要进行强制类型转换 a = b; //此时会报错 a = (int)b; //需要进行强制类型转换 }}
a是一个整型,b是long类型,把一个long类型的变量赋值给int类型可能会导致整型变量放不下b的值
看下面这段代码
public class Test { public static void main(String[] args) { int a = Integer.MAX_VALUE; //int类型的最大值:2147483647 long b = a+1; System.out.println(b);//编译结果为:-2147483648 }}
有人会问了,为什么最后结果和预想的不一样,不是已经变为long类型了么?
这是因为程序执行代码都是从右向左执行的,a(int) + 1(int) = int,此时已经溢出了,变为 -2147483648,long 接收的就是一个溢出后的值,并不是long类型放不下。
那我们应该怎么进行解决呢?
public class Test { public static void main(String[] args) { int a = Integer.MAX_VALUE; long b = a+1l; //在常量1 后加 l(小写的L),变为long类型 System.out.println(b); //此时编译结果为:2147483648 }}
2.2.2 int->double
int :4字节
double: 8字节
属于小类型转变为大类型, int -> long 为自动提升
int / double -> double/double
小类型和大类型进行数学运算,会将小类型提升为大类型
2.2.3 int -> byte
byte : 1字节
int : 4字节
转换时,还是遵循大转小,强制转换;小转大,自动提升。
看下面代码:
byte a = 120; //正常编译byte b = 130; //此时报错,超过byte类型的数据大小,需要强制类型转换
在这里会有一个疑问?120 默认为int 字面量,属于 大转小,为什么不需要强制转换
这是因为对于数值型和字符型来说,小于4字节的数据类型(byte\char\short),在存储时会转换为4字节,byte类型在保存时会转为int类型。
在这里需要注意:
当把byte类型保存区间(-128 ~ 127)之内的整数赋值给byte时,可以直接赋值。超出
byte的范围,仍然需要强制类型转换
那么将一个int类型的变量赋值给byte时,可不可以直接赋值呢?
答案是:不可以,当把一个int变量赋值给byte时,无论是否超过保存范围,都需要进行强制类型转换。
byte a = 10;byte b = 20;byte c = a + b; //此时会报错
这里报错是因为, byte类型保存数据时会提升为int 类型保存的;小于4字节的数据类型(byte\char\short)CPU在读写数据时,都是以4字节为单位进行进行读取和写入的
所以需要强制类型转换。
byte a = 10;byte b = 20;byte c = (byte)(a + b); //输出:30
请看下面使用 final 修饰的变量
public class Test { public static void main(String[] args) { final byte a = 20; //被final修饰,存储时还是byte 类型 final byte b = 10; byte c = a + b; //此时编译器不会报错 System.out.println(c); }}
因为,被final 修饰的变量除了数据值不能更改,类型也不能提升。
2.2.4 int char
int : 4字节
char : 2字节(字符类型)
二者之间可以相互转化
计算机的内部都是0和1,char 字符会按照不同的编码规则转为int 类型存储
char ch = 'a';int b = ch; //char -> int 自动提升,按照Unicode编码将'a'转变为 int int c = 98;char ch1 = (char)c;System.out.println(b); //输出:97System.out.println(ch1); //输出:'b'
Unicode编码就是把不同的文字和字符按照一定的规则转为数字。
2.2.5 int String
String : 字符串类型
int -> String的转换:
- 直接使用String对象 + int类型,进行拼接
- 使用String的
valueOf
方法
public class Test { public static void main(String[] args) { int a = 10; //使用String的valueOf方法 String str1 = String.valueOf(a); //使用String对象 + 其他类型 ,转变为字符串 String str2 = "" + a; System.out.println(str1); System.out.println(str2); }}
String -> int的转换:
调用int 包装类的Intager.parseInt()
方法
public class Test { public static void main(String[] args) { String str1 = "123"; String str2 = "12sd34"; int a = Integer.parseInt(str1); int b = Integer.parseInt(str2); System.out.println(a); //输出为:123 System.out.println(b); //编译出错 }}
**注意:**当字符串包含了非数字时,转换会出错
2.3 数据类型的默认值
在Java中,所有数据类型都有默认值,定义变量后没有赋值的话,会有默认值
(只存在于类变量中,方法中的局部变量没有默认值)
public class Test { int a; long b; short c; byte d; char e; double f; float j; boolean h; String str; public static void main(String[] args) { System.out.println("int " + new Test().a); System.out.println("long " + new Test().b); System.out.println("short " + new Test().c); System.out.println("byte " + new Test().d); System.out.println("char " + new Test().e); System.out.println("double " + new Test().f); System.out.println("float " + new Test().j); System.out.println("boolean " + new Test().h); System.out.println("String "+ new Test().str); }}
输出结果是:
int 0long 0short 0byte 0char double 0.0float 0.0boolean falseString null
3 运算符
3.1 算数运算符
算数运算符:+ - * / %
使用运算符时,要记住的点有:
- 相同类型进行数学运算,得到的值仍然是本类型
- 小类型和大类型进行数学运算时,先把小类型会提升为大类型,再进行运算
- 在除法运算中,0不能作为除数
% 称为取模运算,取余运算,不仅可以用于整数,小数也可以
有一个数 255,用取模运算得到它的个位,十位,百位?
个位:255%10 = 5
十位:255/10 = 25 25%10 = 5
百位:255/100 = 2
在这里, int / int = int ; 不想要被除数的几位,就除以10^n
3.2 增量赋值运算
增量赋值运算: += 、*= 、/= 、%=
a += 1 等同于 a = a+1
a %= 10 等同于 a = a %10
3.3 自增和自减运算符
自增: ++
自减: –
a++ : 先取a的值,再进行自增
++a:先自增,再取a的值
3.4 关系运算符
关系运算符:运算之后得到的都是布尔值
== | 相等 |
---|---|
!= | 不等 |
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
3.5 逻辑运算符
逻辑运算符:运算后得到的是布尔值
**&& 逻辑与 ** (全真为真,有假则假)
两个操作数都是true,结果返回true;有一个false,就返回false
**|| 逻辑或 ** (有真为真,全假为假)
两个操作数有一个为true,就返回true;都是false才会返回false
&& 和 || 都属于短路操作符
当使用多个条件逻辑与(&&)时,从左到右,有一个表达式为false,剩下的表达式就不用继续判断了,直接返回 false
当使用多个条件逻辑或(||)时,从左到右,有一个表达式为true,剩下的表达式就不用继续判断了,直接返回true
多个运算数为布尔值时,& 和 | 也可以表示逻辑运算,但是不满足短路操作符,所有的条件都要判断一遍。一般不推荐使用
! 取反
操作数为true,返回false;操作数为false,返回true
3.6 位运算符
位运算符:直接在二进制位上进行操作的运算符
**按位与:& **
有0出0,全1为1
按位或: |
有1为1,全0则0
按位取反: ~
该位为1,变为0; 该位为0,变为1
按位异或: ^
相异为1,相同为0
A ^ A = 0
A ^ B ^ A = A
3.7 移位运算
移位运算:
<< :左移
最左侧位不要了,最右侧位补0
20<<1 20的二进制位向左移动1位
>>:右移
最右侧位不要了,最左侧位补符号位(正数补0,负数补1)
20>>1 20的二进制位向右移动1位
>>>:无符号位右移
最右侧位不要了,最左侧位补0
巧记:
左移1位相当于原数字*2
右移一位相当于原数字/2
3.8 条件运算符(唯一一个三目运算符)
表达式1 ?表达式2 :表达式3
当表达式1 为true时,取表达式2的值,否则取表达式3的值
3.9 注释
单行注释:一般用在方法中,给某一行做特殊说明 // 快捷键:ctrl
+ /
多行注释:不推荐 /* */
文档注释:一般用在方法和类的声明之前,告知用户该方法和类的使用原则 /** */