Java语法糖-String类型的switch、泛型和自动拆箱装箱原理

本文深入探讨Java中的语法糖,如泛型、自动装箱拆箱、条件编译、可变参数,以及String和枚举类型的switch语法糖。解析了这些语法糖在编译阶段的实现原理,展示了它们如何提升代码的可读性和编写效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是语法糖?

语法糖是指在计算机语言中添加的某种语法,这种语法对语言的功能并没有什么影响,但是更方便程序员使用,使得程序的可读性更强

解析语法糖

在编译阶段,语法糖会被编译器自动还原为最简单的基础语法结构。比如在java中,使用javac命令用来将我们书写的java文件编译成class字节码文件,而在这个阶段正是将我们使用的java语法糖还原成了简单语法。

Java中的语法糖

java中的常用语法糖主要有泛型、基本类型的自动拆装箱、条件编译、可变参数等

1.String和枚举类型的switch语法糖

1.1 问题:switch语句是如何比较值的?

首先来看switch语句支持的基本数据类型:char、byte、short、int,对于char比较的是ASCII码的值,可以看出,switch语句其实根本上支持的是数值的比较

1.2 switch如何支持其他数据类型?

JDK1.5后又支持了Character、Byte、Short、Integer等封装数据类型,而在JDK1.7以后,switch语句支持的数据类型除了原始数据及其封装类外,又支持了String数据类型和枚举数据类型

之前我们提到,switch实际比较的是数值类型,对于基本数据的封装类,Java的自动拆箱和装箱机制可以将其封装类转换成对应的基本数据类型,进而支持了switch的比较。

同样的思路,如果想要switch支持String类型的比较,那么必须将String类型的数据转换成一个对应的数值,很容易我们就可以想到hashCode() 方法,此方法可以将一个类映射成一个整数类型。但是,我们应当注意到,数据的hash值是有可能发生碰撞的,也就是两个不同的数据的hash值可能相同,所以最终还需要比较的是String字符串的内容

有了这个思路后,我们就可以看一下Java的语法糖是如何实现switch支持String的。
Switch中使用String类型

public class StringSwitch {
	public StringSwitch() {
	}

	public static void main(String args[]) {
		String keyword = "Vincent";
		switch (keyword) {
			case "Vincent":
            	System.out.println("Vincent");
            	break;
       		case "Amy":
            	System.out.println("Amy");
            	break;
        	default:
            	break;
		}
	}
}

反编译后的内容

import java.io.PrintStream;

public class StringSwitch {
    public static void main(String[] paramArrayOfString) {
        String str1 = "Vincent";
        String str2 = str1;
        int i = -1;
        switch (str2.hashCode()) {
            case 2126603299:
                if (str2.equals("Vincent")) i = 0;
                break;
            case 65965:
                if (str2.equals("Amy")) i = 1;
        }
        switch (i) {
            case 0:
                System.out.println("Vincent");
                break;
            case 1:
                System.out.println("Amy");
        }
    }
}

我们可以看到Java在解析语法糖时,首先将String的hashCode进行比较,在case语句中再使用equals()方法进行进一步比较。具体的语句执行则是使用了一个临时变量i进行的。

类似的,枚举类型的则是使用getValue()方法进行的

2.泛型语法糖

java中的泛型是一种叫做code sharing的方法,这种方式会为所有的泛型类型创建一个唯一的字节码表示,并且将泛型类型的实例映射到字节码表示上,并且使用了一种类型擦除的技术

Java虚拟机其实根本不认识泛型,泛型是在编译的时候进行语法糖才能支持的!

例如源代码:

Map<String, String> userMap = new HashMap<>();
map.put("username", "123456");

经过反编译后:

Map userMap = new HashMap();
map.put("username", "123456");

可以看出,编译过程中编译器将泛型类型自动抹去,只留下了顶级父类型,在实际执行过程中则是通过类型强制转换来实现的

泛型类型不能重载
public static void method(List<String> list) {
    System.out.println("invoke method(List<String> list)"); 
} 

public static void method(List<Integer> list) { 
    System.out.println("invoke method(List<Integer> list)"); 
} 

3.自动装箱和拆箱语法糖

Java中的自动装箱和拆箱机制指的是在某些情况下基本数据类型和其对应封装类型相互转换

自动装箱代码:

int i = 0;
Integer n = i;

反编译后:

int i = 0;
Integer n = Integer.valueOf(i);

自动拆箱代码:

Integer n = 0;
int i = n;

反编译后:

Integer n = Integer.valueOf(0);
int i = n.intValue();

可见自动拆箱和装箱语法糖解析是通过调用包装类的intValue()和valueOf()方法实现的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值