码迷,mamicode.com
首页 > 编程语言 > 详细

java中的12个语法糖

时间:2019-07-16 10:53:10      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:collect   阶段   移除   并且   strong   返回   java 7   ret   通过   

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个语法糖

标签:collect   阶段   移除   并且   strong   返回   java 7   ret   通过   

原文地址:https://www.cnblogs.com/xueyunqing/p/11193138.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!