Java基础面试题day02——数据类型
1.八种基本的数据类型?
Java支持的数据类型分为两类:基本数据类型和引用数据类型
基本数据类型:
- 数值型:整数类型byte、short、int、long 浮点类型float、double
- 字符型:char
- 布尔型:boolean
2.long和int可以互转吗?
可以;由于long类型的范围比int类型大,因此将int转换为long是安全的,而将long转换为int可能会导致数据丢失或者溢出。
将int转换为long可以通过直接赋值或强制类型转换来实现。例如:
int intValue = 10;
long longValue = intValue; // 自动转换,安全的
将long转换为int需要使用强制类型转换,但需要注意潜在的数据丢失或溢出问题。
long longValue = 100L;
int intValue = (int) longValue; // 强制类型转换,可能会有数据丢失或溢出
3.数据类型转换方式你知道哪些?
- 自动转换类型(隐式转换):当目标类型的范围大于源类型时,Java会进行自动转换。例如将int转为long、将float转为double等。
- 强制转换类型(显示转换):当目标类型的范围小于源类型时,需要使用强制类型转换将源类型转换为目标类型。但这可能导致数据丢失或者溢出。例如将long转换为int、将double转为int等。
- 字符串转换:Java提供了将字符串表示的数据转换为其他类型数据的方法。例如,将字符串转换为整型int,可以使用Integer.parseInt()方法;将字符串转换为浮点型double,可以使用Double.parseDouble()方法等。
- 数值之间的转换:Java提供了一些数值类型之间的转换方法,如将整型转换为字符型、将字符型转换为整型等。这些转换方式可以通过类型的包装类来实现,例如Character类、Integer类等提供了相应的转换方法。
4.类型互转会出现什么问题吗?
- 数据丢失:当将一个范围较大的数据类型转换为一个范围较小的数据类型时,可能会发生数据丢失。例如,将一个long类型的值转换为int类型时,如果long值超出了int类型的范围,转换结果将是截断后的低位部分,高位部分的数据将丢失。
- 数据溢出:与数据丢失相反,当将一个范围较小的数据类型转换为一个范围较大的数据类型时,可能会发生数据溢出。例如,将一个int类型的值转换为long类型时,转换结果会填充额外的高位空间,但原始数据仍然保持不变。
- 精度损失:在进行浮点数类型的转换时,可能会发生精度损失。由于浮点数的表示方式不同,将一个单精度浮点数(float)转换为双精度浮点数(double)时,精度可能会损失。
- 类型不匹配导致的错误:在进行类型转换时,需要确保源类型和目标类型是兼容的。如果两者不兼容,会导致编译错误或运行时错误。例如:int和boolean类型不能相互转换。
5.为什么用bigDecimal 不用double ?
double会出现精度丢失的问题,因为double执行的是二进制浮点运算,二进制有些情况下不能准确的表示一个小数,就好比十进制不能准确的表示1/3(0.3333…),也就是说二进制表示小数时只能够表示能够用1/(2n)的和的任意组合,但是0.1不能够精确表示,因为它不能表示成1/(2n)的和的形式。
比如:
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.3 / 100);
输出:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
这就是Java进行浮点运算时产生的精度丢失的问题。
而 Decimal 是精确计算 , 所以一般牵扯到金钱的计算 , 都使用 Decimal。
例子:
import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("0.1");
BigDecimal num2 = new BigDecimal("0.2");
BigDecimal sum = num1.add(num2);
BigDecimal product = num1.multiply(num2);
System.out.println("Sum: " + sum);
System.out.println("Product: " + product);
}
}
//输出
Sum: 0.3
Product: 0.02
需要注意的是,在创建BigDecimal对象时,应该使用字符串作为参数,而不是直接使用浮点数值,以避免浮点数精度丢失。
6.装箱和拆箱是什么?
装箱(Boxing)和拆箱(Unboxing)是将基本数据类型和对应的包装类之间进行转换的过程。
自动装箱主要发生在两种情况,一种是赋值时,另一种是在方法调用的时候。
赋值时:
//after java5
Integer iObject = 3; //autobxing - primitive to wrapper conversion
int iPrimitive = iObject; //unboxing - object to primitive conversion
方法调用时:
当我们在方法调用时,我们可以传入原始数据值或者对象,同样编译器会帮我们进行转换。
public static Integer show(Integer iParam){
System.out.println("autoboxing example - method invocation i: " + iParam);
return iParam;
}
//autoboxing and unboxing in method invocation
show(3); //autoboxing
int result = show(3); //unboxing because return type of method is Integer
自动装箱的弊端:
自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。
Integer sum = 0; for(int i=1000; i<5000; i++){ sum+=i; }
上面的代码sum+=i可以看成sum = sum + i,但是+这个操作符不适用于Integer对象,首先sum进行自动拆箱操作,进行数值相加操作,最后发生自动装箱操作转换成Integer对象。其内部变化如下
int result = sum.intValue() + i; Integer sum = new Integer(result);
由于我们这里声明的sum为Integer类型,在上面的循环中会创建将近4000个无用的Integer对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。
7.Java为什么要有Integer?
Integer对应是int类型的包装类,就是把int类型包装成Object对象,对象封装有很多好处,可以把属性也就是数据跟处理这些数据的方法结合在一起,比如Integer就有parseInt()等方法来专门处理int型相关的数据。
另一个非常重要的原因就是在Java中绝大部分方法或类都是用来处理类类型对象的,如ArrayList集合类就只能以类作为他的存储对象,而这时如果想把一个int型的数据存入list是不可能的,必须把它包装成类,也就是Integer才能被List所接受。所以Integer的存在是很必要的。
8.说一下 integer的缓存?
Java的Integer类内部实现了一个静态缓存池,用于存储特定范围内的整形数值对应的Integer对象。
默认情况下,这个范围是-128 - 127。当通过Integer.ValueOf(int)方法创建一个在这个范围内的整数对象时,并不会每次都生成新的对象实例,而是复用缓存中的现有对象,会直接从内存中取出,不需要创建一个对象。