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个语法糖的主要内容,如果未能解决你的问题,请参考以下文章

java中的12个语法糖

JVM:Java中的语法糖

Java 中的语法糖

Java 中的 6 颗语法糖

什么是语法糖?Java中有哪些语法糖?

Java基础Java中的语法糖