java 基本数据类型与包装类

  • 基本类型

    1.整型

    名称宽度范围
    byte8-128 ~ 127
    short16-32768 ~ 32767
    int32-2 147 483 648 ~ 2 147 483 647
    long64-9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807

    整型字面值可以写为十进制,十六进制,八进制,二进制

    //十进制
    int x = 10;
    //十六进制 (加前缀0X或0x)
    int y = 0x20;
    //八进制 (加前缀0)
    int z = 017;
    //二进制 (加前缀OB或Ob)
    int u  0b0111;
    

    要将一个值赋给long类型时,在数字的后面要加上后缀字母L或l。

    2.浮点型

    名称宽度范围
    float321.4e-045 ~ 3.4e+038
    double644.9e-324 ~ 1.8e+308

    float: float类型表示使用32位存储的单精度数值,在某些处理器上,单精度运行速度更快,并且占用的空间是双精度的一半,但是当数值非常大或者非常小时会变得不精确。如果需要用到小数,且精度要求不高时可以考虑用float。
    double: double类型表示使用64位存储的双精度数值,在sin()、cos()和sqrt()这类数学函数中,返回值都是double类型。如果需要在很多次迭代运算中保持精度,或是操作非常大的数值时,double类型是最佳选择。

    3.字符型

    名称宽度范围
    char160~65536

    char: 由于java采用了Unicode标准来表示字符,Unicode定义了一个完全国际化的字符集,能够表示全部人类语言中的所有字符,为此需要使用十六位宽度来存储。

    4.布尔型

    名称字节数
    boolean1个字节

    boolean: boolean 只有true和false两个值。


  • 基本数据类型转换

    1.默认转换:
    byte,short,char—int—long—float—double
    byte,short,char相互之间补转换,他们参与运算首先转换为int类型

    2.强制转换:
    格式: 目标类型 变量名 = (目标类型)值或变量名

    int a = (int) 15.7f;
    

    3.加宽转换:
    当从一种基本类型转换向另一种基本类型时,如果后者的大小和前者相同或者更大,就叫做加宽转换,加宽转换不会造成信息丢失,且加宽转换是隐式发生的,不需要在代码里做额外操作。例如:

    int a=10;
    long b=a;
    

    4.收窄转换:
    当从一种基本类型转换向另一种基本类型时,如果后者的大小比前者更小,就叫做收窄转换,收窄转换需要显示调用,用圆括号指定目标类型,例如

    long a=10;
    int b=(int)a;
    

    如果被转换的值比目标类型的容量还要大的话,收窄转换将导致信息丢失,例如:

    long a=9876543210L;
    int b=(int)a;
    System.out.println(b);//输出值是1286608618
    

    5.自动类型提升:
    我们在表达式中进行计算时,中间值要求的精度有时候会超出操作数的范围。例如:

    byte a = 40;
    byte b = 50;
    byte c = 100;
    int d = a * b / c;
    

    中间部分 a * b 很容易超出byte操作数的范围。为了解决这类问题,当对表达式求值时,Java会自动将每个byte,short或char操作数提升为int类型。这意味着使用int类型而不是byte类型执行子表达式a * b。因此,即时a和b都被指定为byte类型,中间表达式(50 * 40)的结果2000是合法的。自动类型提升很有用,但有时候会导致难以理解的编译时错误。例如:

    byte b=10;
    //错误
    b= b*2;
    

    如上代码试图将 10 * 2 的结果(一个完全有效的byte值)保存到byte变量中,但是编译器却提示错误。当计算表达式的值时,操作数被自动提升为int类型,所以结果也被提升为int类型。因此,现在是试图将一个int类型值转为byte变量,如果不使用强制类型转换,就不能将结果赋给byte变量。

    Java中定义了几个应用于表达式的类型提升规则:
    1.对于一元操作符来说,如果操作数的类型是byte,short或char,运算结果提升为int类型
    2.对与二元操作符来说,提升规则是从以下几条依次选择一条执行:
    如果操作数类型均为byte、short或char,那么两个数均转为int类型,结果数也将为int类型
    如果操作数包含double类型,那么另一个操作数也转为double,结果数也将为double类型
    如果操作数包含float类型,那么另一个操作数也转为float,结果数也将为float类型
    如果操作数包含long类型,那么另一个操作数也转为long,结果数也将为long类型


  • 包装类

    基本类型对应的包装类
    byteByte
    shortShort
    intInteger
    longLong
    floatFloat
    doubleDouble
    charCharacter
    booleanBoolean

    数值型包装类都继承至Number,而字符型和布尔型继承至Object

    1.基本类型与包装类的区别 (以int和Integer为例)

    • Integer必须实例化后才能使用,而int变量不需要
    • Integer实际是对象的引用,new 一个Integer时实际上是生成一个指针指向此对象;而int则是直接存储数据值
    • Integer的默认值是null,int 的默认值是0

    2.基本类型与包装类的比较 (以int和Integer为例)

    • 两个new Integer()变量比较时:由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远不相等

    • Integer变量与int变量比较时:只要Integer变量的值与int变量值相等,则返回true(比较时,Integer会自动拆包为int)

    • 非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)

      Integer i = new Integer(100);
      Integer j = 100;
      System.out.print(i == j); //false
      
    • 对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。(因为java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100);,而java API中对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了)

      Integer i = 100;
      Integer j = 100;
      System.out.print(i == j); //true
      
      Integer i = 128;
      Integer j = 128;
      System.out.print(i == j); //false
      
      

    3.装箱与拆箱
    装箱:将基本数据类型转换为包装器类型;
    拆箱:将包装器类型转换为基本数据类型。

    以Integer和int为例,了解装箱与拆箱的实现

    int num = 5;	//拆箱 通过调用Integer的intValue方法实现
    Integer num = 5;	//装箱	通过调用Integer的valueOf方法实现
    

    装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)

    建议避免无意中的装箱、拆箱行为,尤其是在性能敏感的场合,创建 10 万个 Java 对象和 10 万个整数的开销可不是一个数量级的,不管是内存使用还是处理速度,光是对象头的空间占用就已经是数量级的差距了。

  • 延伸

    Integer的值缓存原理
    在创建新的 Integer 对象之前会先在 IntegerCache.cache (是个Integer类型的数组)中查找。有一个专门的类来负责 Integer 的缓存。这个类是用来实现缓存支持,并支持 -128 到 127 之间的自动装箱过程。最大值 127 可以通过 JVM 的启动参数- XX:AutoBoxCacheMax=size 修改。 缓存通过一个 for 循环实现。从小到大的创建尽可能多的整数并存储在一个名为 cache 的整数数组中。这个缓存会在 Integer 类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。

    哪些类型是线程安全的
    Java自带的线程安全的基本类型包括: AtomicInteger, AtomicLong, AtomicBoolean, AtomicIntegerArray,AtomicLongArray等

    基本数据类型存储位置
    基本数据类型储存的位置,取决于基本类型在哪里声明。
    例如:

    • 在方法中声明的变量(局部变量),每当系统调用方法时,系统都会为这个方法建立一个方法栈, 方法中声明的方法也会放在这个栈中,基本数据类型的变量名和值都会放在java虚拟栈中,引用类型的变量会存放指向对象的内存地址值在java虚拟栈中,该地址指向的对象则是放在堆内存中。方法结束后,该栈被释放,对应的局部变量也会随着栈的释放而销毁。
    • 在类中声明的成员变量(全局变量),是放在堆内存中的,基本类型的变量名和值都会被存放在堆中,而引用类型依然会保存指向对象的内存地址值在堆中,引用变量名和对应的对象仍然储存在相应的堆中。
    • 被static修饰的变量(静态变量)是存储在JVM的方法区中,静态变量在类被加载的时候进行初始化,然后存储到JVM的方法区中,整个内存中只有一个静态变量的拷贝,可以使用类名直接访问,也可以使用类实例化后的对象访问。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值