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

Java语法糖(一)

时间:2017-10-12 10:24:40      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:val   stat   sys   char   结果   关系   参与   描述   oid   

概述

  语法糖(Syntactic Sugar):主要作用是提高编码效率,减少编码出错的机会。

  解语法糖发生在Java源码被编译成Class字节码的过程中,还原回简单的基础语法结构。

语法糖之一:泛型(Generics)

  Java中的泛型又称为类型擦除,它只在Java源码中存在,被编译成字节码后,就已经替换为原生类型了,并在相应的地方加入强制类型转换。

  例如:

public class GenericTypes {
    /*
     * 两个mothod1方法不能被编译,因为List<Integer>和List<String>被编译成class文件后都被擦除了,
     * 变成了一样的原生类型List<T>,擦除之后两个方法的签名一样。
     */
    public static void mothod1(List<Integer> list) {
        
    }
    public static void mothod1(List<String> list) {
        
    }
    
    /*
     * 在jdk1.7
     * 两个mothod2方法不能被编译,因为List<Integer>和List<String>被编译成class文件后都被擦除了,
     * 变成了一样的原生类型List<T>,擦除之后两个方法的签名一样。返回值不参与重载选择
     * 
     * Sun JDK1.6中Javac才能编译成功
     * 在Class文件格式中,只要描述符不是完全一致的两个方法就可以共存。
     */
    public static String mothod2(List<String> list) {
        return "";
    }
    public static Integer mothod2(List<Integer> list) {
        return 1;
    }
}

 

语法糖之二:自动拆箱和装箱、Foreach、变长参数

  例如:

public class Foreach_Varargs {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4);//变长参数(Varargs)
        int sum = 0;
        for(int i : list) { //遍历循环Foreach
            sum += i;
        }
        System.out.println(sum);
    }
    /*
     * 反编译之后的代码
     * 1、变长参数还原为数组类型的参数:Arrays.asList(...)  ---->  new Integer[]{...}
     * 2、Foreach还原为迭代器实现
     * 3、自动拆箱和装箱还原为Integer.valueOf()和Integer.intValue()方法
     * 
     public static void main(String[] args) {
        java.util.List<Integer> list = java.util.Arrays.asList(new Integer[] {
                Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3),
                Integer.valueOf(4) });
        int sum = 0;
        for (Iterator localIterator = list.iterator(); localIterator.hasNext();) {
            int i = ((Integer) localIterator.next()).intValue();
            sum += i;
        }
        System.out.println(sum);
    } 
     */
}

  一个更复杂的自动装箱拆箱的栗子:

public class Autoboxing {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        System.out.println(c == d); //(1)
        System.out.println(e == f); //(2)
        System.out.println(c == (a + b)); //(3)
        System.out.println(c.equals(a + b)); //(4)
        System.out.println(g == (a + b)); //(5)
        System.out.println(g.equals(a + b)); //(6)
    }
    /*
     * 反编译后的代码
     * 
     * 包装类的“==”运算在不遇到算数运算的情况下不会自动拆箱;
     * equals方法不处理数据转型的关系。
     * 
     * 在 Java 中,== 比较的是对象引用,而 equals 比较的是值。
     * 
     * 一、(1)为true,(2)为false原因:
     *      IntegerCache:把-128到127(可调)的整数都提前实例化了,不管创建多少个这个范围内的Integer用ValueOf出来的都是同一个对象;
     *      用来节省内存和提高性能。这种 Integer缓存策略仅在自动装箱(autoboxing)的时候有用,使用构造器创建的 Integer 对象不能被缓存。
     *      这个缓存会在 Integer 类第一次被使用的时候被初始化出来.是什么原因选择这个 -128 到 127 这个范围呢?因为这个范围的整数值是使用最广泛的。
     *      Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 可以通过参数改变范围外,其它的都不行
     *      
     *      不在缓存范围的会新new Integer对象。
     * 二、(3)为true,(5)为true
     *      自动拆箱,相当于数值类型int
     * 三、(4)为true
     *      a,b先拆箱计算数值和,再将计算结果装箱为Integer
     * 四、(5)为false
     *      g为Long类型,a + b为Integer,类型不一致
     * 五、(6)为false, g为Long类型,a + b为Integer,类型不一致,返回false
            public boolean equals(Object obj) {
                if (obj instanceof Long) {
                    return value == ((Long)obj).longValue();
                }
                return false;
            }     
     *      
     public class Autoboxing {
       public static void main(String[] args) {
          Integer a = Integer.valueOf(1);
          Integer b = Integer.valueOf(2);
          Integer c = Integer.valueOf(3);
          Integer d = Integer.valueOf(3);
          Integer e = Integer.valueOf(321);
          Integer f = Integer.valueOf(321);
          Long g = Long.valueOf(3L);
          System.out.println(c == d);
          System.out.println(e == f);
          System.out.println(c.intValue() == a.intValue() + b.intValue());
          System.out.println(c.equals(Integer.valueOf(a.intValue() + b.intValue())));
          System.out.println(g.longValue() == (long)(a.intValue() + b.intValue()));
          System.out.println(g.equals(Integer.valueOf(a.intValue() + b.intValue())));
       }
    }
    */
}

 

语法糖之三:条件编译

  栗子:

public class ifdef {
    public static void main(String[] args) {
        final boolean isCompile = true;
        if(isCompile) {
            System.out.println("11111");
        } else {
            System.out.println("2222");
        }
    }
    /*
     * 条件编译
     * System.out.println("2222"); 不会编译
     * Java只能实现语句基本块级别的条件编译,而无法实现根据条件调整整个Java类的结构。
     * 
     * 反编译后的代码:
     * public class ifdef {
           public static void main(String[] args) {
              boolean isCompile = true;
              System.out.println("11111");
           }
        }
     */
}

 

除以上外,语法糖还有:内部类、枚举类、断言语句、对枚举和字符串的switch支持(1.7)、try语句中定义和关闭资源(1.7)等,接下来继续Java语法糖系列。

  

 

Java语法糖(一)

标签:val   stat   sys   char   结果   关系   参与   描述   oid   

原文地址:http://www.cnblogs.com/zaizhoumo/p/7644447.html

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