【JavaSE专栏6】Java 基本类型转换、包装类、自动装箱、自动拆箱

简介: 【JavaSE专栏6】Java 基本类型转换、包装类、自动装箱、自动拆箱

一、基本数据类型转换

在学习基本数据类型转换之前,首先要了解为什么要进行基本数据类型转换

1.1 为什么要进行转换

上一节课时中,提到了 Java 数据类型的层级,如下图所示。

Java 作为一个强类型的编程语言,在不同数据类型之间进行转换时,需要进行手动 / 自动转换。

byte 的数据范围是 -128 到 127,如果将数值 128 直接赋值给 byte 类型的数据,IntelliJ IDEA 会编译报错,如下图所示。

所以需要进行数据转换,请看以下代码:

public class Main {
    public static void main(String[] args) {
        int a = 128;
        byte b = (byte) a;
        System.out.println("答案 = " + b);
    }
}

最终输出结果为:

答案 = -128

因为 128 超过了 byte 的数据范围,则重新计数赋值,第一个值为 -128

通过以上一个简单的例子,同学们只需简单了解下为什么要进行数据类型转换即可。

只要参与运算的基本数据类型不一致时,就会发生数据类型的转换

Java 中基本数据类型的转换主要分为两类

  • 自动转换类型(隐式转换)
  • 强制转换类型(显示转换)

接下来逐个讲解。


1.2 自动类型转换(隐式转换)

自动类型转换,顾名思义就是自动进行数据类型转换。

由 Java 编译器进行自动处理,Java 代码不需要经过任何处理

小类型到大类型是自动提升的,那什么是小类型和大类型呢?如下图所示,箭头非被指结点为相对小类型,反之箭头被指结点为相对大类型,如 short 相对于 int 来说就是小类型。


1.2.1 自动类型转换1——直接赋值

小类型变量赋值给大类型时,会触发自动类型转换,比如:

public class Main {
    public static void main(String[] args) {
        long a = 1;
    }
}

数值 1int 类型,而承载的变量为 long 类型,则数值 1 会被自动转换为 1L


1.2.2 自动类型转换2——运算时转换

小类型变量和大类型变量进行运算时,会将小类型提升为大类型,再进行数学运算,如下所示。

public class Main {
    public static void main(String[] args) {
        int a = 1;
        long b = 5L + a;
    }
}

比如变量 a 为 int 类型,在计算 5L + a 时,会首先将 a 转换为 1L,再计算 5L + 1L = 6L,最终得出 6L 结果。

简单来说 long + int 会自动转换为 long + long 再进行计算。

同理 int + double 也会自动转换为 double + double 再进行计算,如下代码所示。

public class Main {
    public static void main(String[] args) {
        int a = 1;
        double b = 3.14 + a;
    }
}

1.3 强制类型转换(显示转换)

大类型转为小类型时,需要强制类型转换,可能会导致数据丢失。

比如 int 类型的取值范围是 -2^31到2^31-1byte 类型的取值范围是 -2^7到2^7-1

int 类型转换为 byte 类型时,会出现数据溢出的情况,如下代码所示。

public class Main {
    public static void main(String[] args) {
        int a = 128;
        byte b = (byte) a;
        System.out.println("b = " + b);
    }
}

最终输出的结果为 b = -128,即发生了数据溢出情况,也可以理解为数据丢失。

同理,在 double 类型强制转换为 int 时,也会出现数据精度丢失(数据丢失),如下代码所示。

public class Main {
    public static void main(String[] args) {
        double a = 3.1415926;
        int b = (int) a;
        System.out.println("b = " + b);
    }
}

输出结果为 b = 3,即发生了数据精度丢失情况,也可以理解为数据丢失。


1.3 类型转换小结

关于 Java 的数据类型转换,同学们需要理解以下三点:

  • 大转小:强制类型转换,如下:
int a = 6;
byte b = (byte) a;

提示:对于 byte 和 int 类型之间的转换中需要注意,当把一个 int 数值赋值给 byte 变量时,不管是否超过范围,都需要强制转换。

  • 小转大:自动类型转换,如下:
int a = 6;
long c = a;
  • 默认定义类型

整数的默认类型为 int

整数带有后缀 L 时类型为 long

浮点数的默认类型为 double

浮点数带有后缀 f 时类型为 float

提示:关于 String 的类型转换,将在后续的课时中讲解,因为 String 不属于 Java 的基本数据类型。


二、自动装箱和自动拆箱

在学习自动装箱和自动拆箱之前,首先了解什么是包装类。

2.1 包装类是什么?

在 jdk1.4 中,新增了 8 个基本数据类型的对应包装类,如下表所示。

基本类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

基本数据类型的对应包装类的方式基本相同,但在 JVM 上的分配有所不同,具体将在后续的课时中讲解,同学们只需知道在时间或空间上,基本数据类型优于对应包装类即可。


2.2 为什么要用包装类?

从 jdk1.5 开始,定义集合需要使用包装类。定义普通数组,使用基本类型和包装类都可,如下代码所示。

public class Main {
    public static void main(String[] args) {
        /**
         * 普通数组的定义方法
         */
        int[] a = new int[10];
        /**
         * 集合的定义方法
         */
        List<Integer> arr = new ArrayList<>();
        /**
         * 对基本类型的集合定义需要转为包装类
         */
        // List<int> arr = new ArrayList<>(); // 编译错误
    }
}

关于集合的用法,会在下面的课时中讲解,同学们只需要了解包装类的使用场景即可。


2.3 自动装箱

自动装箱是什么?基本类型自动转换为包装类型就是自动装箱

请看以下代码:

public class Main {
    public static void main(String[] args) {
        /**
         * 直接赋值
         */
        Integer a = 666;
        /**
         * 包装类的静态工厂方法
         */
        Integer b = Integer.valueOf(666);
        /**
         * 构造器赋值,在现有 JDK 中已被废弃
         */
        Integer c = new Integer(666);
    }
}

在对 Integer 类型的变量赋值时,666 这是一个基本数据类型,而变量 abc 为包装类。

自动装箱,就是将一个基本类型直接赋值给包装类型的过程。

如果没有自动装箱,以上代码无法通过 JVM 编译。


2.4 自动拆箱

自动拆箱是什么?包装类型自动转换为基本类型就是自动拆箱

请看以下代码:

public class Main {
    public static void main(String[] args) {
        Integer a = 666;
        int b = 666;
        System.out.println("判断 1 = " + (a == b));
        System.out.println("判断 2 = " + Objects.equals(a,b));
    }
}

代码中分别定义基本类型和包装类,赋同样的值,最后判断是否相等,输出为:

判断 1 = true
判断 2 = true

其中变量 a 在比较之前,自动拆箱为基本类型,然后在于 b 进行比较,最后得出 true 的结果。

如果不进行自动拆箱,两个不同类型的变量无法进行比较

就好比拿 苹果电视 比较性能,这是不可行的。

Java 只能将包装类 Integer 拆箱为 int 才能和 int 值进行比较。

这就是 自动拆箱


2.5 性能比较

同学们学习自动装箱、自动拆箱之后,还需要了解它们的性能差距。

因为,这将影响你在实战开发中,决定常用哪个,最终影响你的程序性能。


2.5.1 测试基本类型

首先对基本数据类型进行测试,代码如下所示。

public class Main {
    private static final long MAX_NUMBER = 1000000000;
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        long sum = 0;
        for(long i = 0; i < MAX_NUMBER; i ++) {
            sum += i;
        }
        long end = System.currentTimeMillis();
        System.out.printf("耗时 = " + (end - start) + ",计算结果 = " + sum);
    }
}

最后输出结果:

耗时 = 304,计算结果 = 499999999500000000

2.5.2 测试包装类

接着对包装类进行测试,代码如下所示。

public class Main {
    private static final Long MAX_NUMBER = 1000000000L;
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        Long sum = 0L;
        for(Long i = 0L; i < MAX_NUMBER; i ++) {
            sum += i;
        }
        Long end = System.currentTimeMillis();
        System.out.printf("耗时 = " + (end - start) + ",计算结果 = " + sum);
    }
}

最后输出结果:

耗时 = 6374,计算结果 = 499999999500000000

2.5.3 测试小结

由此可见,使用包装类虽然简便,但频繁自动装拆箱会带来性能低下的问题。

所以在实战开发中,建议使用基本数据类型

如果一定要使用包装类的场景下,再去使用包装类。

在 2.1 小节 也提到过,基本类型无论是在时间还是空间上都是优于引用类型(如包装类)的。


三、课时小结

在本节课时中,讲解了低转高、高转低的 Java 基本类型转换,接着学习了包装类的概念,再引申出自动装箱、自动拆箱的概念,最后分别进行了性能测试。在下节课时中,将学习 Java 变量、常量及其作用域的知识。

相关文章
|
15天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
39 4
|
2月前
|
Java 编译器 容器
Java——包装类和泛型
包装类是Java中一种特殊类,用于将基本数据类型(如 `int`、`double`、`char` 等)封装成对象。这样做可以利用对象的特性和方法。Java 提供了八种基本数据类型的包装类:`Integer` (`int`)、`Double` (`double`)、`Byte` (`byte`)、`Short` (`short`)、`Long` (`long`)、`Float` (`float`)、`Character` (`char`) 和 `Boolean` (`boolean`)。包装类可以通过 `valueOf()` 方法或自动装箱/拆箱机制创建。
37 9
Java——包装类和泛型
|
1月前
|
Java 编译器
【一步一步了解Java系列】:探索Java基本类型转换的秘密
【一步一步了解Java系列】:探索Java基本类型转换的秘密
37 3
|
1月前
|
Java 编译器 C语言
【一步一步了解Java系列】:探索Java基本类型与C语言的区别
【一步一步了解Java系列】:探索Java基本类型与C语言的区别
44 2
|
2月前
|
Java 编译器 程序员
Java自动类型转换的妙用
Java中的自动类型转换(隐式类型转换)是指编译器在无需显式指定的情况下自动将一种数据类型转换为另一种类型。这一特性简化了代码,提高了可读性,并在多态中发挥了重要作用。例如,在数学运算时,较小类型会自动转换为较大类型以避免精度损失;在面向对象编程中,子类对象可以自动转换为父类引用,增强了代码的灵活性和兼容性。此外,它还使得数组和集合的使用更加方便,整体上让编程更加优雅和高效。
|
1月前
|
Java
【Java】什么是泛型?什么是包装类
【Java】什么是泛型?什么是包装类
18 0
|
3月前
|
Java
【Java基础面试九】、说一说自动装箱、自动拆箱的应用场景
这篇文章介绍了Java中的自动装箱和自动拆箱概念:自动装箱允许将基本类型赋值给对应的包装类对象,而自动拆箱允许将包装类对象赋值给基本类型,从而简化了两者之间的转换过程。
【Java基础面试九】、说一说自动装箱、自动拆箱的应用场景
|
3月前
|
Java 程序员
【Java基础面试八】、为啥要有包装类?
这篇文章解释了Java中存在包装类的原因:为了让基本数据类型具备对象的特性,使得它们可以被用作对象,以符合Java"一切皆对象"的设计理念,并简化将基本数据类型作为Object类型参数传递的问题。
【Java基础面试八】、为啥要有包装类?
|
2月前
|
存储 Java 测试技术
Java零基础教学(10):包装类
【9月更文挑战第1天】Java零基础教学篇,手把手实践教学!
42 1
|
6天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####