• Java 关键字 final 知识点巩固


    Java中关键字 final

    这个关键字在代码中使用的很多,但其原理跟多人不会关注。

    一位面试官朋友闲聊是曾说过,他常问的关于final的一个问题是,“当Java中final修饰HashMap集合时,HashMap集合数据能修改吗?向这个HashMap集合add数据的时候,程序会不会报错。”这个问题,80% 的面试人员会答错。

    在此再整理下关于final的用法。

     

    1、基本用法

    基本用法,final可以修饰类、方法、变量(成员变量+局部变量)

    修饰类:

    用final修饰类,表明该类不能被继承。final类中成员变量可以根据需要设置为final,但是final类中所有成员方法都会隐式指定为final方法。

     

     

    要谨慎使用final修饰类,除非这个类真的在以后不会用来继承。

    修饰方法:

    用final修饰方法,会把方法锁定,以防止任何继承类修改它的含义。只有在想明确禁止该方法在子类中被覆盖的情况才将方法设置为final。

    类的private方法会隐式的指定为final方法。

    修饰变量:

    用final修饰变量,如果是基本数据类型,数值一旦初始化之后就不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

     

     

    2、深入理解

    类的final变量和普通变量的区别

    当final作用于类的成员变量时,成员变量必须在定义时或者构造器中进行初始化赋值,且final变量一旦被初始化赋值,就不能再被赋值了。

    import com.google.common.collect.Maps;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * @author wgy
     * @version 1.0
     * @description
     * @date 2020/8/30 15:54
     */
    public class TestFinal {
        private static Logger log = LoggerFactory.getLogger(TestFinal.class);
        public static void main(String[] args) {
            String str_1 = "test_1";
            final String str_2 = "test_";
            String str_3 = "test_";
    
            /** 这里访问 final str_2 是直接访问它的值 ,相当于 "test_" + 1 */
            String val_1 = str_2 + 1;
            String val_2 = "test_" + 1;
    
            /** 这里访问str_3是根据连接进行, */
            String val_3 = str_3 + 1;
    
            log.info("str_1 == val_1 : {}" , (str_1 == val_1));
            log.info("str_1 == val_2 : {}" , (str_1 == val_2));
            log.info("str_1 == val_3 : {}" , (str_1 == val_3));
            log.info("str_1 eq val_3 : {}" , (str_1.equals(val_3)));
        }
    }

    输出结果:

    16:18:19.304 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 == val_1 : true
    16:18:19.310 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 == val_2 : true
    16:18:19.310 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 == val_3 : false
    16:18:19.310 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 eq val_3 : true

     

    当final变量是基本数据类型以及String类型时,如果编译期间能知道它的确切值,则编译器会把它当作编译期常量使用。注意是确切知道final变量值,才会这样。

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    /**
     * @author wgy
     * @version 1.0
     * @description
     * @date 2020/8/30 15:54
     */
    public class TestFinal {
        private static Logger log = LoggerFactory.getLogger(TestFinal.class);
        public static void main(String[] args) {
            String str_1 = "test_1";
            final String str_2 = getStrVal();
            String str_3 = "test_";
    
            /** 这里访问 final str_2 是直接访问它的值 ,相当于 "test_" + 1 */
            String val_1 = str_2 + 1;
            String val_2 = "test_" + 1;
    
            /** 这里访问str_3是根据连接进行, */
            String val_3 = str_3 + 1;
    
            log.info("str_1 == val_1 : {}" , (str_1 == val_1));
            log.info("str_1 == val_2 : {}" , (str_1 == val_2));
            log.info("str_1 == val_3 : {}" , (str_1 == val_3));
            log.info("str_1 eq val_3 : {}" , (str_1.equals(val_3)));
        }
    
        public static String getStrVal(){
            return "test_";
        }
    }

    输出结果:

    16:20:35.015 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 == val_1 : false
    16:20:35.019 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 == val_2 : true
    16:20:35.019 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 == val_3 : false
    16:20:35.019 [main] INFO com.ycb.iot.finaltest.TestFinal - str_1 eq val_3 : true

    被final修饰的引用变量内容是否可变

    引用变量被final修饰后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的。

    /**
     * @author wgy
     * @version 1.0
     * @description
     * @date 2020/8/30 15:54
     */
    public class TestFinal {
        private static Logger log = LoggerFactory.getLogger(TestFinal.class);
        public static void main(String[] args) {
            final TestFinalVal testFinalVal = new TestFinalVal();
            int value_1 = testFinalVal.value + 10;
            log.info("value_1 : {} ", value_1);
        }
    }
    
    class TestFinalVal{
        public int value = 100;
    }

     输出结果:

    16:26:52.604 [main] INFO com.ycb.iot.finaltest.TestFinal - value_1 : 110 

    3、对于开头的问题:

    很多人第一反应: HashMap一旦存进去值,就不能变了。结果是错的,存进去之后还能变。

    第二反应:HashMap第一次初始化之后,它的各项属性值不能变了,比如Capacity、size等。结果还是错的,这些属性还是可以变化。

    当final修饰基本类型和String时,变量值不可变。当修饰其他类型的对象时,final使其引用恒定不变,但是对象自身却可以自由修改变换。

     

  • 相关阅读:
    (转载)构建public APIs与CORS
    SpringMVC 参数注入
    java删除文件夹
    idea 自动提示生成 serialVersionUID
    JSP自定义tag
    gradle中使用嵌入式(embedded) tomcat, debug 启动
    spring in action 4th --- quick start
    Date, TimeZone, MongoDB, java中date的时区问题
    spring boot 添加拦截器
    HTTP status code
  • 原文地址:https://www.cnblogs.com/wgy1/p/13585672.html
Copyright © 2020-2023  润新知