• java 语法糖中的坑


    语法糖

    java中的语法糖

    • switch 支持 String 与枚举(Java 7开始支持String,String的本质还是数值)
    • 泛型(jvm在编译阶段采用类型擦除的方式解糖)
    • 自动拆装箱
    • 可变长参数(一个方法中只能有一个可变长参数,如果有其他参数,可变长参数必须放在最后)
    • 枚举
    • 内部类
    • 条件编译
    • 断言
    • 数值字面量(支持整数和浮点数,只是为了方便阅读)
    • for-each(只是简化书写,本质还是用for循环和迭代器实现)
    • try-with-resource(优化try-catch-finally结构)
    • lambda(简化函数式接口书写)

    语法糖中的坑点

    泛型

    一、当泛型遇到重载 public class GenericTypes {

        public static void method(List<String> list) {  
            System.out.println("invoke method(List<String> list)");  
        }  
    
        public static void method(List<Integer> list) {  
            System.out.println("invoke method(List<Integer> list)");  
        }  
    }  
    

    上面这段代码,有两个重载的函数,因为他们的参数类型不同,一个是List另一个是List ,但是,这段代码是编译通不过的。因为我们前面讲过,参数List和List编译之后都被擦除了,变成了一样的原生类型List,擦除动作导致这两个方法的特征签名变得一模一样。

    二、当泛型遇到catch 泛型的类型参数不能用在Java异常处理的catch语句中。因为异常处理是由JVM在运行时刻来进行的。由于类型信息被擦除,JVM是无法区分两个异常类型MyException<String>MyException<Integer>

    三、当泛型内包含静态变量

    public class StaticTest{
        public static void main(String[] args){
            GT<Integer> gti = new GT<Integer>();
            gti.var=1;
            GT<String> gts = new GT<String>();
            gts.var=2;
            System.out.println(gti.var);
        }
    }
    class GT<T>{
        public static int var=0;
        public void nothing(T x){}
    }
    

    以上代码输出结果为:2!由于经过类型擦除,所有的泛型类实例都关联到同一份字节码上,泛型类的所有静态变量是共享的。

    自动装箱与拆箱

    对象相等比较

    public class BoxingTest {
        public static void main(String[] args) {
            Integer a = 1000;
            Integer b = 1000;
            Integer c = 100;
            Integer d = 100;
            System.out.println("a == b is " + (a == b));
            System.out.println(("c == d is " + (c == d)));
        }
    }
    

    输出结果:

    a == b is false
    c == d is true
    

    在Java 5中,在Integer的操作上引入了一个新功能来节省内存和提高性能。整型对象通过使用相同的对象引用实现了缓存和重用。

    转载补充:阿里开发手册中有讲到Integer包装类的这个坑!!!

    image-20200509152448665.

    适用于整数值区间-128 至 +127。

    只适用于自动装箱。使用构造函数创建对象不适用。

    增强for循环

    ConcurrentModificationException

    for (Student stu : students) {    
        if (stu.getId() == 2)     
            students.remove(stu);    
    }
    

    会抛出ConcurrentModificationException异常。

    Iterator是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出java.util.ConcurrentModificationException异常。

    所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法remove()来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。

    总结

    前面介绍了12种Java中常用的语法糖。所谓语法糖就是提供给开发人员便于开发的一种语法而已。但是这种语法只有开发人员认识。要想被执行,需要进行解糖,即转成JVM认识的语法。当我们把语法糖解糖之后,你就会发现其实我们日常使用的这些方便的语法,其实都是一些其他更简单的语法构成的。
    有了这些语法糖,我们在日常开发的时候可以大大提升效率,但是同时也要避免过渡使用。使用之前最好了解下原理,避免掉坑。
    原文参考
    贴上引用地址,如需自取:https://developer.aliyun.com/article/702384?spm=a2c6h.12873639.0.0.49cc54aa3ayibH

  • 相关阅读:
    Mysql系列(十二)—— 索引下推优化
    Mysql系列(十一)—— 性能分析其他常用监控
    套路篇(一)之软件配置
    Mysql中的变量
    Mysql系列(十一)—— 性能分析慢查询日志
    Mysql系列(十)—— 性能分析工具profiling
    Mysql系列(九)—— 性能分析explain执行计划
    secure-file-priv特性
    Levenberg-Marquardt优化和zipf分布
    关于ADM和高维空间下距离度量的问题
  • 原文地址:https://www.cnblogs.com/bky-min/p/12857592.html
Copyright © 2020-2023  润新知