类型转换及包装类拆装箱

Posted datamining-bio

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类型转换及包装类拆装箱相关的知识,希望对你有一定的参考价值。

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

 

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

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

技术图片

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

(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:同类或父类

技术图片

技术图片

以上是关于类型转换及包装类拆装箱的主要内容,如果未能解决你的问题,请参考以下文章

包装类与自动拆装箱

自动拆装箱,string和基本数据类型的相互转换

java包装类和自动拆装箱

基本类型包装拆装箱

java中的自动拆装箱

Java包装类的自动拆装箱