zoukankan      html  css  js  c++  java
  • Java语法糖(一)

    概述

      语法糖(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语法糖系列。

      

  • 相关阅读:
    练习题
    练习
    2.15
    数组
    java聊天工具12.4
    11.13(2)
    11.13
    10.30 作业
    10.23
    面向对象
  • 原文地址:https://www.cnblogs.com/zaizhoumo/p/7644447.html
Copyright © 2011-2022 走看看