JAVA不像PHP,JS,Python,它是一门强类型语言。强类型的语言有以下几个要求:
- 变量或常量必须有类型:要求声明变量或常量时必须声明类型,而且只能在声明以后才能使用;
- 赋值时类型必须一致:值的类型必须和变量或常量的类型完全一致;
- 运算时类型必须一致:参与运算的数据类型必须一致才能运算。
但是在实际生产中,经常需要在不同类型的值之间进行操作,这就需要一种新的语法来适应这种需要,这个语法就是数据类型转换。作为基础中的基础,今天带大家重温一下:
正文
JAVA基本数据类型:byte,short,int,long为整型;float,double为浮点型;char为字符型;boolean 为布尔类型;
JAVA引用数据类型:类class,接口interface,数组[];
如此,我们也分两大块来讲解类型的转换问题:
1. 基本类型之间的转换
在数值处理这部分,计算机和现实的逻辑不太一样。对于现实来说,1和 1.0 没有什么区别,但是对于计算机来说,1 是整数类型,而 1.0 就是浮点类型,其在内存中的存储方式以及占用的空间都不一样,所以类型转换在计算机内部是必须的。
Java 语言中,基本数据类型的转换分两种:
- 自动类型转换::编译器自动完成类型转换,不需要在程序中编写代码;
- 强制类型转换:强制编译器进行类型转换,必须在程序中编写代码。
由于基本数据类型中 boolean 类型不是数字型,所以基本数据类型的转换是除了 boolean 类型以外的其它 7 种类型之间的转换。
自动类型转换
自动类型转换,也称隐式类型转换,是指不需要书写代码,由系统自动完成的类型转换。由于实际开发中这样的类型转换很多,所以 Java 语言在设计时,没有为该操作设计语法,而是由 JVM 自动完成。
转换规则:从存储范围小的类型到存储范围大的类型;
具体规则为:byte → short(char) → int → long → float → double;
注意问题:
- JAVA将byte,short,char表示范围归为一个层次,因此byte,short,char不会相互转换,这三者在计算的时候都会首先转换成int型;
- 有多种数据类型进行混合运算时,JAVA会先将所有数据类型转换成表示范围大的那一种数据类型在进行运算;
- 浮点型(如:3.14)常量默认的数据类型为double型,整型常量(如:520)默认为int型;
//基本类型:自动类型转换
@Test
public void testAuto() {
//1.JVM首先将b的值转换成short类型,然后再赋值给s;
byte b = 13;
short s = b;
//2.在类型转换的时候也可以跳跃,就是byte也可以自动转换为更高的类型;
int i = b;
double d = b;
//3.虽然b1 b2都是byte型,但是运算的时候首先会转换成int型;
byte b1 = 13;
byte b2 = 14;
byte b3 = (byte)(b1 + b2); //27
//4.整型溢出:此时的 b4+b5 > 127,超出byte表示范围,
// 127 + 1 = -128,再加的话以此类推,环形往复;
byte b4 = 66;
byte b5 = 67;
byte b6 = (byte)(b4 + b5); //-123
//5.浮点型溢出:超出表示范围时会出现INF无穷大;
float f1 = 3.2f/1f; //3.2
float f2 = 3.2f/0; //Infinity(正无穷)
float f3 = -3.2f/0; //-Infinity(负无穷)
}
强制类型转换
强制类型转换,也称显式类型转换,是指必须书写代码才能完成的类型转换。该类类型转换很可能存在精度的损失,所以必须书写相应的代码,并且能够忍受该种损失时才进行该类型的转换。
转换规则:从存储范围大的类型到存储范围小的类型。
具体规则为:double → float → long → int → short(char) → byte
语法格式为:(转换到的类型)需要转换的值
//基本类型:强制类型转换
@Test
public void testForced() {
//强制类型转换通常都会存储精度的损失,所以使用时需要谨慎
double d1 = 3.14159265358979;
double d2 = 1227;
float f = (float) d1; //3.1415927 (精度损失)
int i1 = (int) d1; //3 (精度损失)
int i2 = (int) d2; //1227 (精度无损失)
}
2. 与String类型的互转
Java的字符串String属于一个类,所以它属于引用数据类型。因为在引用数据类型中,只存在String与基本数据类型的互转。因为基本数据类型与String互转原理相同,方法相似,所以这里以int为例,讲解一下规则和原理:
int转String有三种方法
- num + “”
- Integer.toString(num)
- String.valueOf(num)
//int -> String :三种方法
@Test
public void testIntToString() {
int num = 20180721;
//1. num + ""
long start = System.currentTimeMillis(); //得到开始运行时系统时间
for(int i=0; i<100000; i++){
String str = num + "";
}
long end = System.currentTimeMillis(); //得到结束运行时系统时间
System.out.println("num + \"\" : " + (end - start));
//2. String.valueOf(num)
start = System.currentTimeMillis();
for(int i=0; i<100000; i++){
String str = String.valueOf(num);
}
end = System.currentTimeMillis();
System.out.println("String.valueOf(num) : " + (end - start));
//3. Integer.toString(num)
start = System.currentTimeMillis();
for(int i=0; i<100000; i++){
String str = Integer.toString(num);
}
end = System.currentTimeMillis();
System.out.println("Integer.toString(num) : " + (end - start));
}
程序执行结果:
可以发现,第一种方式与后面两种方式运行的时间相差比较大,这里简单说一下区别:
num + “”:先将数字toString()转成字符串,然后进行字符串的拼接,效率自然很低,且过程中会产生两个String对象;
Integer.toString():采用Integer.toString()的基础是Object.toString(),因为java.lang.Object类中已有public方法toString(),所以对任何严格意义上的Java对象都可以调用此方法,但使用时需要注意,必须保证object不是null值,否则将会抛出NullPointerException异常;
String.valueOf():直接使用String类的静态方法,只产生一个对象,基础仍是Object.toString()方法,JDK中String.valueOf(object)源码:
public static String valueOf(Object obj){
return (obj==null)?"null":obj.toString();
}
所以使用该方法不必担心object为null的情况,但同时也要注意:当object为null时,该方法返回字符串"null",而非null,此处是个坑!!
String 转 Int有两种方法
- Integer.parseInt(str)
- Integer.valueOf(str).intValue()
//String -> int :两种方法
@Test
public void testStringToInt() {
String s = "20181227";
//1.Integer.parseInt(str)
long start = System.currentTimeMillis(); //得到开始运行时系统时间
for(int i=0; i<100000; i++){
int n = Integer.parseInt(s);
}
long end = System.currentTimeMillis(); //得到结束运行时系统时间
System.out.println("Integer.parseInt(str) : " + (end - start));
//2.Integer.valueOf(str).intValue()
start = System.currentTimeMillis();
for(int i=0; i<100000; i++){
int n = Integer.valueOf(s).intValue();
}
end = System.currentTimeMillis();
System.out.println("Integer.valueOf(str).intValue() : " + (end - start));
}
程序执行结果:
可以发现,两者运行时间差距虽有但不大,可以忽略,但是执行原理确是天差地别,解释一下:
Integer.valueOf(str).intValue():此方法运用了包装类的拆装箱操作,先是将String -> Integer -> int,即将String包装类型转化为Integer包装类型,再将包装类型转化为基本类型, 等价于 new Integer(Integer.parseInt(str)),过程中会产生额外的一个对象。
Integer.parseInt():直接使用String类的静态方法,只产生一个对象;
小结
- 基本数据类型的互转,在大转小时要注意值域,由于存储精度的不同,可能造成数据精度的损失或者溢出;
- int转String 建议使用String.valueOf()方法,需要注意object为null时,返回值为字符串的"null";
- String 转 Int 两种方法效率虽然差不多,但是建议使用Integer.parseInt()方法;
更多精彩,请关注我的"今日头条号":Java云笔记
随时随地,让你拥有更新,更便捷的掌上云服务