概述
文章目录
- 一、基本数据类型
- 1、基本数据类型之间的转换
- 1.自动转换
- 2.强制转换
- 3.类型自动提升
- 5.包装类过渡类型转换
- 2、相关面试题
- 1.问题1
- 2.问题2
- 3.问题3
- 4.问题4
- 二、引用类型
- 1.对象的实例化过程
- 三、包装类
- 1.Integer
- 2.Float
- 3.Double
一、基本数据类型
- 8大基本数据类型:byte、int、short、long、float、double。
- 基本数据类型所能表示的值的大小范围
浮点型的取值范围,注意:0到±Float.MIN_VALUE之间的值float类型无法表示
float : 3.4e-45~1.4e38
double :4.9e-324~1.8e308
默认浮点类型为double,所以double类型可以不加d,而float类型必须加f
1、基本数据类型之间的转换
自动转换和强制转换。
1.自动转换
小范围数据可以向大范围数据自动转换.
(byte,short,char) < int < long < float < double
具体地讲,当一个较"小"数据与一个较"大"的数据一起运算时,系统将自动将"小"数据转换成"大"数据,再进行运算。
①下面的语句可以在Java中直接通过:
byte b;
int i=b;
long l=b;
float f=b;
double d=b;
②如果低级类型为char型,向高级类型(整型)转换时,会转换为对应ASCII码值,例如
char c='c';
int i=c;
System.out.println("output:"+i);//输出:output:99;
③对于byte,short,char三种类型而言,他们是平级的,因此不能相互自动转换,可以使用下述的强制类型转换
。
short i=99;
char c=(char)i;
System.out.println("output:"+c);//输出:output:c;
2.强制转换
将"大"数据转换为"小"数据时,必须强制类型转换。
int n=(int)3.14159/2;
这种转换会导致溢出或精度的下降。
3.类型自动提升
表达式的数据类型自动提升, 关于类型的自动提升,注意下面的规则。
①所有的byte,short,char
型的值将被提升为 int
型;
②如果有一个操作数是long型,计算结果是long型;
③如果有一个操作数是float型,计算结果是float型;
④如果有一个操作数是double型,计算结果是double型;
byte b;
b=3;
b=(byte)(b*3);//必须声明(byte)
《Java核心技术卷1》41页:数值类型之间得转换问题
int n = 123456789;
float f = n; //1.23456789E8
float sum = n + f;
当使用上面两个数值进行二元操作时 ( 例如 n + f, n 是整数 , f是浮点数 ), 先要将两个操作数转换为同一种类型, 然后再进行计算 。
5.包装类过渡类型转换
①当希望把float型转换为double型时:
float f1=100.00f;
Float F1=new Float(f1);
double d1=F1.doubleValue();//F1.doubleValue()为Float类的返回double值型的方法
②当希望把double型转换为int型时:
double d1=100.00;
Double D1=new Double(d1);
int i1=D1.intValue();
简单类型的变量转换为相应的包装类,可以利用包装类的构造函数。即:
new Boolean(boolean value)、//构造器参数都可以接收对应的基本类型
Character(char value)、
Integer(int value)、
Long(long value)、
Float(float value)、
Double(double value)
而在各个包装类中,总有形为 xxValue()
的方法,转换为对应的简单类型数据。利用这种方法,也可以实现不同数值型变量间的转换。
补充:
字符串与其它类型间的转换
- 其它类型向字符串的转换
①调用类的串转换方法:X.toString();
②自动转换:X+"";
③使用String的方法:String.volueOf(X);
- 字符串作为值,向其它类型的转换
①先转换成相应的封装器实例,再调用对应的方法转换成其它类型
例如,字符中"32.1"转换double型的值的格式为:new Float(“32.1”).doubleValue()。也可以用:Double.valueOf(“32.1”).doubleValue()
②静态parseXXX方法
String s = "1"; byte b = Byte.parseByte( s ); short t = Short.parseShort( s ); int i = Integer.parseInt( s ); long l = Long.parseLong( s ); Float f = Float.parseFloat( s ); Double d = Double.parseDouble( s );
③Character的 getNumericValue(char ch) 方法
char ch ='A'; int value = Character.getNumericValue(ch);//10 /** * getNumericValue()将实际表示数字的字符(如普通数字0-9字符)转换为其int型数字值 */
2、相关面试题
1.问题1
byte b1=3,b2=4,b;
b=b1+b2;
b=3+4;
//哪句是编译失败的呢?为什么呢?
- b=b1+b2; 编译失败: byte 运算先变成int,再计算,再赋值给byte类型,很明显 int类型不能自动转成 byte类型。
- 知识点:byte,char,short编译时都是需要转成int,才可运算。
- 变量相加,必须考虑基本数据类型的转换能不能转。
- b=3+4; 编译正确: 因为他们都是常量 具有常量类型优化机制 可以直接识别为byte,两个常量相加,先计算常量数值,然后判断是否满足类型范围,再赋值。
- 常量相加,优化机制,直接看计算结果在不在byte类型所允许的范围内。
2.问题2
short s=1;
s = s + 1; //(错误)默认类型提升,提升为int类型,,不能用short去接收int类型的数据
// 解决方案:强制类型转换
对于扩展的赋值运算符
s+=1
不等价于 :s = s +1 ;
等价于: s = (short)(s+1) ;
扩展的赋值运算符隐藏了强制类型转换!
//上面两个代码有没有问题,如果有,哪里有问题
3.问题3
byte可以用在switch语句的表达式?
long可以作为switch语句的表达式?
String可以作为switch语句的表达式?
答:
switch语句后面的表达式:能跟的类型:byte,short,int,char
byte的存储范围小于int,可以向int类型进行隐式转换,所以switch可以作用在byte上
long的存储范围大于int,不能向int进行隐式转换,只能强制转换,所以switch不可以作用在long上
string在1.7版本之前不可以,1.7版本之后switch就可以作用在string上了。
4.问题4
java 中 char 类型变量能不能储存一个中文的汉字,为什么?
答:
java 的 char 类型变量是用来储存 Unicode 编码字符的,Unicode 字符集包含了汉字,所以 char类型自然就能存储汉字,
但是在某些特殊情况下某个生僻汉字可能没有包含在 Unicode 编码字符集中,这种情况下 char类型就不能存储该生僻汉字了。
java 中 3*0.1 == 0.3
将会返回什么?true 还是 false?
答:
false,因为浮点数运算不能完全精确的表示出来,一般都会损失精度。
二、引用类型
1.对象的实例化过程
Java有 5种引用类型(对象类型):类 、接口、 数组 、枚举 、标注
创建一个对象的过程:
Student stu = new Student();
上例实现步骤:
JVM加载Student.class 到方法区
new Student()在堆空间分配空间并创建一个Student实例
将此实例的地址赋值给栈空间的变量引用 stu
三、包装类
1.Integer
- 构造方法
public Integer(int value)
public Integer(String s) //数字字符串转换成integer
//进制转换
Integer.toBinaryString(int i)
Integer.toOctalString(int i)
Integer.toHexString(int i)
- 自动装箱
public class IntegerDemo {
public static void main(String[] args) {
Integer i = 100; //自动装箱
i += 200; //自动拆箱、再自动装箱
System.out.println("i : " + i);
//通过反编译后的代码
Integer i = Integer.valueOf(100); //由此可见,自动装箱的步骤是调用了 valueOf方法
i = Integer.valueOf(i.intValue() + 200);
System.out.println(new StringBuilder("i : ").append(i).toString());
}
}
- valueOf方法的缓存
通过valueOf,可以实现将int、String类型的字符转换为Integer。
下面看一下valueof的源码,会发现一个问题——IntegerCache
/**
* 当参数中的基本类型i在 -128~127 范围内时,使用的是缓存区中的实例
* 超出范围的一律 new 构建新对象
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
其实,除了 Integer类型,其他的整数类型都有valueOf 方法,也都有一个自己的范围内缓冲区。
其他类型的缓存范围为:
Integer类型有缓存-128-127的对象。(缓存上限可以通过配置jvm更改 )
Byte,Short,Long类型有缓存(-128-127)
Character缓存0-127 Boolean缓存TRUE、FALSE
其他浮点型包装类valueOf方法没有用到缓存。
尤其需要特别注意的是,只有
valueOf
方法构造对象时会用到缓存,new
方法等不会使用缓存!
面试题中经常会出现这样的判断:
Double i1 = Double.valueOf(0.1);
Double i2 = Double.valueOf(0.1);
System.out.println(i1 == i2); //false, valueOf方法内部实际上也是new
System.out.println(Integer.valueOf(1) ==Integer.valueOf(1)); //true
System.out.println(Integer.valueOf(999) ==Integer.valueOf(999)); //false
Integer i4 = Integer.valueOf(1);//手动装箱
Integer i5 =1;//自动装箱
System.out.println(i4 == i5); //true
Integer i7 = Integer.valueOf(999);
Integer i8 = 999;
System.out.println(i7 == i8); //false
Integer与int的区别
- nteger是int的包装类,int 则是java的一种基本数据类型
- Integer变量必须实例化后才能使用,而int变量不需要
- Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int 则是直接存储数据值
- Integer的默认值是null,int的默认值是0
Integer与int的转换
- Integer.valueof(i) //integer ii; int i
- ii.intValue()
Integer与String的转换
- integer.parseInt(s) //string—>int
- new Integer(s) //string—>integer
- ii.toString() //integer—>string
- String.valueof(i) //int—>string
2.Float
浮点数精度问题
public class FloatPrimitiveTest {
public static void main(String[] args) {
float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
if (a == b) {
System.out.println("true");
} else {
System.out.println("false");
}
}
}
// true or false?
//答:false
float a = 1.0f - 0.9f;
System.out.println(a); // 0.100000024
float b = 0.9f - 0.8f;
System.out.println(b); // 0.099999964
加上两条打印语句后,我明白了,原来发生了精度问题。
Java 语言支持两种基本的浮点类型:float 和 double ,以及与它们对应的包装类 Float 和 Double 。它们都依据 IEEE 754 标准,该标准用科学记数法以底数为 2 的小数来表示浮点数。
但浮点运算很少是精确的。虽然一些数字可以精确地表示为二进制小数,比如说 0.5,它等于 2-1;但有些数字则不能精确的表示,比如说 0.1。因此,浮点运算可能会导致舍入误差,产生的结果接近但并不完全等于我们希望的精确结果。
public class FloatWrapperTest {
public static void main(String[] args) {
Float a = Float.valueOf(1.0f - 0.9f);
Float b = Float.valueOf(0.9f - 0.8f);
if (a.equals(b)) {
System.out.println("true");
} else {
System.out.println("false");
}
}
}
// true or false?
//答:false,valueof包装方法,不会解决精度问题
Float a = Float.valueOf(1.0f - 0.9f);
System.out.println(a); // 0.100000024
Float b = Float.valueOf(0.9f - 0.8f);
System.out.println(b); // 0.099999964
Float的包装器,没有缓存也没有解决精度,只是将基础类型转为了包装类,使用new创建新的对象。
public static Float valueOf(float f) {
return new Float(f);
}
3.Double
//1. 传入字符串时没有精度问题
BigDecimal a = new BigDecimal(0.1);
System.out.println(a); // 0.1000000000000000055511151231257827021181583404541015625
BigDecimal b = new BigDecimal("0.1");
System.out.println(b); // 0.1
//BigDecimal装箱后,没有精度问题
double a = 0.1;
System.out.println(new BigDecimal(String.valueOf(a))); // 0.1
System.out.println(BigDecimal.valueOf(a)); // 0.1
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。
Tips:
由此可得,在使用浮点型数据时要时刻注意精度问题,稍不注意就可能导致你输入的小数和程序运行时实际的小数值是不一样的。
通过使用上面的BigDecimal 类型,可以帮助我们。
查看BigDecimal.valueOf源码不难发现,
只要在输入浮点数时,记住——用字符串更靠谱!
public static BigDecimal valueOf(double val) {
return new BigDecimal(Double.toString(val));
}
最后
以上就是柔弱帅哥为你收集整理的【JavaSE】《基础篇001》基本数据类型、包装类、类型转换一、基本数据类型二、引用类型三、包装类的全部内容,希望文章能够帮你解决【JavaSE】《基础篇001》基本数据类型、包装类、类型转换一、基本数据类型二、引用类型三、包装类所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复