zoukankan      html  css  js  c++  java
  • 类型转换及包装类拆装箱

    1. 基本类型

    2. 基本类型之间的类型转换

      (1)自动类型转换

      (2)强制类型转换

      (3)运算时类型提升

      (4)类型转换中的符号扩展及“多重转型”

    3. 基本类型到对应包装类

      (1)包装类

      (2)自动装箱与拆箱

      (3)缓存

    4.基本类型和String之间的转换

      (1)基本类型 -> String

      (2)String -> 基本类型

    5.instanceof

    1. 基本类型

    类型

    占用存储空间

    表示数的范围

    byte

    1字节

    -128~127

    short

    2字节

    -215~215-1(-32768~32767)

    int (integer)

    4字节

    -231~231-1(-2147483648~2147483647)21亿

    long

    8字节

    -263~263-1

    float

    4字节

    -3.403E38~3.403E38

    double

    8字节

    -1.798E308~1.798E308

     

      逻辑型boolean(1位,默认初始值为false)虽然用1位就可以表示,但是Java中至少使用1个字节保存,原因见下文

      Note:与其他高级语言不同,java中的布尔值和数字之间不能来回转换,即falsetrue不对应于任何零或非零的整数值

      byte类型

      由于不同的机器对于多字节数据的存储方式不同,可能是从低字节高字节存储,也可能是从高字节向低字节存储,这样,在分析网络协议或文件格式,为了解决不同机器上的字节存储顺序问题,用byte类型来表示数据是比较合适的。而通常情况下,由于其表示的数据范围很小,容易造成溢出,因此要尽量少使用。

      浮点型double float

      不要使用浮点数判断相等,可用于大小判断。

      Float:小数点后7位,double16

      浮点数默认类型为double,默认初始值为0.0浮点数运算过程中不会因溢出而导致异常处理出现下溢,则结果为0.0如果上溢,则结果为正或负无穷大。非法数表示NaN

      正无穷大(infinity):正数除以0(整数除以0会报错:15/0

      负无穷大(-infinity):负数除以0

      NaN0.0除以0.0 或 对一个负数开方

      所有正无穷大数值都相等,所有负无穷大数值都相等,NaN不与任何数值相等,甚至和NaN都不相等

    2. 基本类型之间的类型转换

    1)自动类型转换:A->B,当B的表示范围大于等于A时(原值保留)

      int, char, shout, byte也可互转,只要表示的数值没有超过数值范围。

      为什么intfloat会有精度丢失,而转double不会?

    java 的浮点类型都依据 IEEE 754 标准。IEEE 754 定义了32 位和 64 位双精度两种浮点二进制小数标准。

    对于32 位浮点数float用 第1 位表示数字的符号,用第2至9位来表示指数,用 最后23 位来表示尾数,即小数部分。

    对于64 位双精度浮点数,用 第1 位表示数字的符号,用 11 位表示指数,52 位表示尾数。

    即如果int的值在23位内表示,则float可以精确表示,超过23位则float的23位不够表示,但是double拥有52位可以精确表示整数,完全包含了32位的int。

    (2)强制类型转换:B->AA的表示范围比B小(会丢失信息)

    (3)运算时类型提升,避免计算中值溢出(类型转换放第一个)

      为什么两个short类型相加会自动提升为int

      s1 + s2系统会自动将它们提升为int再运算,结果为int类型,赋给short类型,编译报错;s3 = s2 + 1也是同样的原因;s3 = 4 + 45,系统选计算4+45=50,也就是变为s3 = 5050short表示的范围内,自动转型为short。但是为什么java在两个short型运算时自动提升为int,即使它们没有超过表示范围?

    Stack Overflow

      使用较小类型运算没有性能优势,消除较小的类型使得字节码更简单,并且使得具有未来扩展空间的完整指令集仍然适合单个字节中的操作码。因此,较小的类型通常被视为Java设计中的二等公民,在各个步骤转换为int,因为这简化了一些事情。

    Why does the Java API use int instead of short or byte?

    https://stackoverflow.com/questions/27122610/why-does-the-java-api-use-int-instead-of-short-or-byte

     

      答案可能只与Java虚拟机指令集有关。较小的类型(byteshort)基本上只用于数组。

      If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte

      为较小的类型引入专用的算术逻辑单元不值得付出努力:它需要额外的晶体管,但它仍然只能在一个时钟周期内执行一次加法。 JVM设计时的主流架构是32位,适合32int

    (4)类型转换中的符号扩展及“多重转型”

      https://blog.csdn.net/qq_38962004/article/details/80025619

     

    3. 基本类型到对应包装类

    (1)包装类

    java保留基本类型:开发运行效率高

    (2)自动装箱与拆箱

      基本数据类型有一些约束:所有引用类型变量都继承了Object类,都可当成Object类型变量使用。但基本数据类型变量就不可以,如果有个方法需要Object类型的参数,但实际需要的值却是23等数值,这可能就比较难以处理,为了解决8个基本数据类型的变量不能当做Object类型变量使用的问题,java提供了包装类的概念。

    JDK1.5之前:

      基本类型  ---new Integer(125)----> 包装类

      包装类    ---对象.xxxValue()方法------>  基本类型

    自动装箱(JDK5.0之后):

      把基本数据类型变量包装成包装类实例是通过对应包装类的构造器来实现的。除Character之外,其他均可通过传入一个字符串参数来构建包装类对象。

      包装类还可实现将基本类型和字符串之间的转换:int = Integer.parseInt(intStr)String类里也提供了多个重载valueOf()方法,将基本类型转为字符串。

    (3)缓存

      -128~127之间的数,当做基本数据类型处理,提高效率

        public static void main(String[] args) {
            Integer i1 = 59;
            Integer i2 = 59;
            System.out.println(i1 == i2);  // true
            System.out.println(i1.equals(i2));  // true
            System.out.println("==================");
            Integer i3 = -129;
            Integer i4 = -129;
            System.out.println(i3 == i4);     // false
            System.out.println(i3.equals(i4));  // true
        }
    public class TestNuke {
    
        public static void main(String[] args) {
            Integer i01 = 59;
            int i02 = 59;
            Integer i03 = Integer.valueOf(59);
            Integer i04 = new Integer(59);
            System.out.println(i01 == i02);    // true
            System.out.println(i01 == i03);    // true
            System.out.println(i01 == i04);    // false
            System.out.println(i02 == i03);    // true
            System.out.println(i02 == i04);    // true
            System.out.println(i03 == i04);    // false
            System.out.println(i01.hashCode());  // 59
            System.out.println(i03.hashCode());  // 59
            System.out.println(i04.hashCode());  // 59
        }
    }

    JVM中一个字节以下的整型数据会在JVM启动的时候加载进内存,除非用new Integer()显式的创建对象,否则都是同一个对象

    Integer i01 = 59;会调用 Integer 的 valueOf 方法:

    这个方法就是返回一个 Integer 对象,只是在返回之前,作了一个判断,判断当前 i 的值是否在 [-128,127] 区别,且 IntegerCache 中是否存在此对象,如果存在,则直接返回引用,否则,创建一个新的对象。

    在这里的话,因为程序初次运行,没有 59 ,所以,直接创建了一个新的对象。

    int i02=59 ,这是一个基本类型,存储在栈中。

    Integer i03 =Integer.valueOf(59); 因为 IntegerCache 中已经存在此对象,所以,直接返回引用

    Integer i04 = new Integer(59) ;直接创建一个新的对象。

    System. out .println(i01== i02); i01  Integer 对象, i02  int ,这里比较的不是地址,而是值。 Integer 会自动拆箱成 int ,然后进行值的比较。所以,为真。

    System. out .println(i01== i03); 因为 i03 返回的是 i01 的引用,所以,为真。

    System. out .println(i03==i04); 因为 i04 是重新创建的对象,所以 i03,i04 是指向不同的对象,因此比较结果为假。

    System. out .println(i02== i04); 因为 i02 是基本类型,所以此时 i04 会自动拆箱,进行值比较,所以,结果为真。

    IntegerCache.cache是在Integer类加载时就初始化好的,在[-128127]范围内的valueOf(i),直接去数组中拿对象,而不是首次初始化时才创建。而new Integer(x),不管x的大小,都是新建对象,不去找cache

    基本数据类型和包装类的比较。
    1. 只要涉及到基本数据类型,一直进行的是值比较。也就是说,只要==号左边或者右边有一个是基本数据类型,那么就是值比较。
    2. 如果==号左右两边都是包装,那么==号表示引用类型所指地址是否一致。

     注意:

            1. 因为Integer这个包装类比较特殊,内部有一个数组cache数组,保存了-128127的值,也就是Integer i = n,只要n-128127之间,都是直接从cache数组中获取,不会再创建新的对象。
            2. 对于其他的包装类,比如Double d = 2.1;那么2.1会被自动装箱,也就是调用valueOf方法,这个方法内部还是new了一个Double对象的。
            3. 同时需要注意,自动装箱可不提供向上转型,也就是Double d = 11不会先自动向上转成double然后再装箱,会直接编译错误,因为Double这个包装类中就没有形参是int的构造器,其他包装类也是一样的。
            4. 包装类的equals方法,不提供类型转换。例如Byte b = 100Integer i = 100i.equals(b);返回false
                 equals方法先比较类型,再比较值。

     

    4.基本类型和String之间的转换

    https://www.cnblogs.com/rrttp/p/7922202.htmlchar---String

    1)基本类型 -> String

    ①利用包装类的toString()String str = Integer.toString(45);  

    str = new Double(1.55).toString();

    String类的valueOf()str = String.valueOf(54);

    ③加上空串:str = ‘g’ + “”;  

         该方法效率最低,实际上为new StringBuilder().append(‘g’).append(“”).toString();

    ④将char-->Stringstr = String.valueOf(new char[]{‘f’});

                        str = new String(new char[]{‘h’});

    (2)String -> 基本类型

    ① 包装类的parseXxx()int a = Integer.parseInt(“45”);

    ② 包装类的valueOf()double d = Double.valueOf(“4.54”);

    ③ String-->charString.charAt(index)(返回值为char

                    String.toCharArray()(返回值为char[]

     

    5.instanceof

      Instanceof运算符前面操作数的编译时类型要么与后面的类相同,要么是后面类的父类,否则会引起编译错误。(true:同类或父类

  • 相关阅读:
    2019 年值得关注的 23 个开发者博客
    牛津词典 2018 年度词汇 ——「有毒」!
    17 个关于雪花的有趣事实🌨❄️❄️❄️
    Google 里的软件工程学
    作为软件工程师,如何进行知识管理
    x == (x = y) 不等于 (x = y) == x ?
    Docker-compose编排微服务顺序启动
    Ubuntu 20.04 修改字体、调整缩放
    How To Upgrade Ubuntu To 20.10
    写给工程师的 Ubuntu 20.04 最佳配置指南
  • 原文地址:https://www.cnblogs.com/datamining-bio/p/10739179.html
Copyright © 2011-2022 走看看