Java八股文——数据类型

数据类型

基本数据类型

char的默认值只能是单引号\u0000表示NUL

在代码中没有任何上下文的0和0.0分别默认为int和double类型。

refvar:引用变量本身。均占用4B空间

refobj:引用指向的实际对象。无论是多么小的对象,最小占用的存储空间是12B(用于存储基本信息,称为对象头);由于存储空间分配需要是8B的整数倍,所以初始分配的空间至少是16B

注意,当计算一个对象的大小时,实例占用的空间并不计算在本对象内,依然只计算引用变量大小4字节。

//以下的例子只计算引用变量大小4个字节
RefObject o1 = new RefObject();

对象由对象头、实例数据和填充数据组成:

  • 对象头:对象标记+类元信息
    • 对象标记:存储对象本身运行时的数据。哈希码、GC标记、锁信息和线程关联信息等。
    • 类元信息:对象指向它的类元数据(Klass)的首地址,占用四字节。
  • 实例数据:本类对象的实例成员变量和所有可见的父类成员变量。
  • 填充数据:分配单位为8个字节。

包装类型

除了Float和Double外,其余都有缓存,会复用已有对象。

缓存机制

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False

两种浮点数类型的包装类 Float,Double 并没有实现缓存机制。

所有整型包装类对象之间值的比较,全部使用 equals 方法比较

Integer是唯一可以修改缓存范围的包装类:在VM options中加入参数-XX:AutoBoxCacheMax=777

装箱和拆箱

  • 装箱:将基本类型用它们对应的引用类型包装起来;
  • 拆箱:将包装类型转换为基本数据类型;

从字节码中,我们发现装箱其实就是调用了 包装类的valueOf()方法,拆箱其实就是调用了 xxxValue()方法。

因此,

  • Integer i = 10 等价于 Integer i = Integer.valueOf(10)
  • int n = i 等价于 int n = i.intValue();

注意:**如果频繁拆装箱的话,也会严重影响系统的性能。我们应该尽量避免不必要的拆装箱操作。

如何解决浮点数运算的精度丢失问题?

BigDecimal 可以实现对浮点数的运算,不会造成精度丢失。通常情况下,大部分需要浮点数精确运算结果的业务场景(比如涉及到钱的场景)都是通过 BigDecimal 来做的。

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");

BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);

System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */

超过 long 整型的数据应该如何表示?

基本数值类型都有一个表达范围,如果超过这个范围就会有数值溢出的风险。

在 Java 中,64 位 long 整型是最大的整数类型。

BigInteger 内部使用 int[] 数组来存储任意大小的整形数据。

相对于常规整数类型的运算来说,BigInteger 运算的效率会相对较低。

public void testCompare() {
   BigInteger bigNum1 = new BigInteger("52");
   BigInteger bigNum2 = new BigInteger("27");
   BigInteger c=new BigInteger("5");
   BigInteger d=new BigInteger("3");

   //1.compareTo():返回一个int型数据(1 大于; 0 等于; -1 小于)
   int num = bigNum1.compareTo(bigNum2);           //1

   //2.max():直接返回大的那个数,类型为BigInteger
   //原理:return (compareTo(val) > 0 ? this : val);
   BigInteger compareMax = bigNum1.max(bigNum2);   //52
   System.out.println("d-c="+d.subtract(c));
}

选择基本数据类型还是包装类型

  1. 所有POJO类属性必须使用包装类型
  2. RPC方法的返回值和参数必须使用包装数据类型
  3. 所有的局部变量推荐使用基本数据类型

字符串

String对象赋值操作后,会在常量池中进行缓存,如果下次申请创建对象时缓存中有,那么会直接返回相应引用。

StringBuffer:线程安全

StringBuilder:线程不安全,效率更高

String tempStr = "test";
for (int i = 0; i < 5; i++) {
    tempStr = tempStr + " hello";
}

通过+号拼接字符串效率不高,如上,内部实现逻辑会转换成每次循环new一个StringBuilder,然后调用append(),最后再toString()返回String对象。造成了内存资源的浪费并且性能差。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值