java中的12个语法糖
Posted xueyunqing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中的12个语法糖相关的知识,希望对你有一定的参考价值。
01 switch 支持 String 与枚举
从 Java 7 开始,Java 语言中的语法糖在逐渐丰富,其中一个比较重要的就是 Java 7 中 switch 开始支持 String。
在开始 coding 之前先科普下,Java 中的 swith 自身原本就支持基本类型。比如 int、char 等。
对于 int 类型,直接进行数值的比较。对于 char 类型则是比较其 ascii 码。
所以,对于编译器来说,switch 中其实只能使用整型,任何类型的比较都要转换成整型。比如 byte。short,char(ackii 码是整型)以及 int。
那么接下来看下 switch 对 String 的支持,有以下代码:
String str = "world"; witch (str) case "hello": System.out.println("hello"); break; case "world": System.out.println("world"); break; default: break;
反编译后内容如下:
String str = "world"; String s; switch((s = str).hashCode()) default: break; case 99162322: if(s.equals("hello")) System.out.println("hello"); break; case 113318802: if(s.equals("world")) System.out.println("world"); break;
看到这个代码,你知道原来字符串的 switch 是通过 equals()和hashCode()方法来实现的。还好 hashCode()方法返回的是 int,而不是 long。
仔细看下可以发现,进行 switch 的实际是哈希值,然后通过使用 equals 方法比较进行安全检查,这个检查是必要的,因为哈希可能会发生碰撞。因此它的性能是不如使用枚举进行 switch 或者使用纯整数常量,但这也不是很差。
02 泛型
我们都知道,很多语言都是支持泛型的,但是很多人不知道的是,不同的编译器对于泛型的处理方式是不同的。
通常情况下,一个编译器处理泛型有两种方式:Code specialization和Code sharing。
C++和C#是使用 Code specialization 的处理机制,而 Java 使用的是 Code sharing 的机制。
Code sharing 方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。将多种泛型类形实例映射到唯一的字节码表示是通过类型擦除(type erasue)实现的。
也就是说,对于 Java 虚拟机来说,他根本不认识 Map<String, String> map 这样的语法。需要在编译阶段通过类型擦除的方式进行解语法糖。
类型擦除的主要过程如下:
1. 将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
2. 移除所有的类型参数。
以下代码:
Map<String, String> map = new HashMap<String, String>(); map.put("name", "xuexue"); map.put("age", "100"); map.put("blog", "**.**.com");
解语法糖之后会变成:
Map map = new HashMap(); map.put("name", "xuexue");
map.put("age", "100");
map.put("blog", "**.**.com");
以下代码:
public static <A extends Comparable<A>> A max(Collection<A> xs) Iterator<A> xi = xs.iterator(); A w = xi.next(); while (xi.hasNext()) A x = xi.next(); if (w.compareTo(x) < 0) w = x; return w;
类型擦除后会变成:
public static Comparable max(Collection xs) Iterator xi = xs.iterator(); Comparable w = (Comparable)xi.next(); while(xi.hasNext()) Comparable x = (Comparable)xi.next(); if(w.compareTo(x) < 0) w = x; return w;
虚拟机中没有泛型,只有普通类和普通方法,所有泛型类的类型参数在编译时都会被擦除,泛型类并没有自己独有的Class类对象。比如并不存在List<String>.class或是List<Integer>.class,而只有 List.class。
03 自动装箱与拆箱
自动装箱就是 Java 自动将原始类型值转换成对应的对象,比如将 int 的变量转换成 Integer 对象,这个过程叫做装箱,反之将 Integer 对象转换成 int 类型值,这个过程叫做拆箱。
原始类型 byte, short, char, int, long, float, double 和 boolean 对应的封装类为 Byte, Short, Character, Integer, Long, Float, Double, Boolean。
先来看个自动装箱的代码:
int i = 10; Integer n = i;
反编译后代码如下:
int i = 10; Integer n = Integer.valueOf(i);
再来看个自动拆箱的代码:
Integer i = 10; int n = i;
反编译后代码如下:
Integer i = Integer.valueOf(10); int n = i.intValue();
从反编译得到内容可以看出,在装箱的时候自动调用的是 Integer的valueOf(int)方法。而在拆箱的时候自动调用的是 Integer 的 intValue 方法。
所以,装箱过程是通过调用包装器的 valueOf 方法实现的,而拆箱过程是通过调用包装器的 xxxValue 方法实现的。
04 方法变长参数
以上是关于java中的12个语法糖的主要内容,如果未能解决你的问题,请参考以下文章