zoukankan      html  css  js  c++  java
  • 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使其引用恒定不变,但是对象自身却可以自由修改变换。

     

  • 相关阅读:
    SharePoint 2013 安装.NET Framework 3.5 报错
    SharePoint 2016 配置工作流环境
    SharePoint 2016 站点注册工作流服务报错
    Work Management Service application in SharePoint 2016
    SharePoint 2016 安装 Cumulative Update for Service Bus 1.0 (KB2799752)报错
    SharePoint 2016 工作流报错“没有适用于此应用程序的地址”
    SharePoint 2016 工作流报错“未安装应用程序管理共享服务代理”
    SharePoint JavaScript API in application pages
    SharePoint 2016 每天预热脚本介绍
    SharePoint 无法删除搜索服务应用程序
  • 原文地址:https://www.cnblogs.com/wgy1/p/13585672.html
Copyright © 2011-2022 走看看