前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java语法糖(一)

Java语法糖(一)

作者头像
在周末
发布2019-09-11 15:53:08
5360
发布2019-09-11 15:53:08
举报
文章被收录于专栏:在周末的专栏在周末的专栏

概述

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

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

语法糖之一:泛型(Generics)

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

  例如:

代码语言:javascript
复制
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、变长参数

  例如:

代码语言:javascript
复制
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);
    } 
     */
}

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

代码语言:javascript
复制
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())));
       }
    }
    */
}

语法糖之三:条件编译

  栗子:

代码语言:javascript
复制
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语法糖系列。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-10-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 语法糖之一:泛型(Generics)
  • 语法糖之二:自动拆箱和装箱、Foreach、变长参数
  • 语法糖之三:条件编译
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档