final关键字的相关使用

28 阅读4分钟

1. final关键字基本使用

  1. 修饰类

    1. 作用:表示类不可以被继承
    2. 特点:final类中的所有成员方法都会被隐式地指定为final方法。
    3. 核心:在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类
  2. 修饰方法

    1. 原因

      1. 方法锁定:以防任何继承类修改他的含义
      2. 效率:早起内嵌调用优化提升效率
    2. 特点

      1. 如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final
      2. 类的private方法会隐式地被指定为final方法。
  3. 修饰变量

    1. 场景

      1. 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改——基本数据类型 值不可以变
      2. 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象——引用类型 不可以指向其他变量对象 但是可以改变该指向对象的值
    2. 不能再对定义的变量重新初始化值

2. final与其他内容的区别

2.1 类的final变量和普通变量有什么区别

  1. final的特点

    • 当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)
    • 必须在定义时或者构造器中进行初始化赋值
    • 而且final变量一旦被初始化赋值之后,就不能再被赋值了。
  2. 核心

    1. final是基本数据类型或者是string类型

      • 当编译期间能知道他的确切值——使用final能让他确定值当做常量使用
    2. 当这个final修饰的变量是通过方法传递过来的

      • 就是引用这个变量地址,在编译期间不确定
  3. 例子

    • 当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。
    • 也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。
    • 这种和C语言中的宏替换有点像。
    • 因此在上面的一段代码中,由于变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的 值。
    • 而对于变量d的访问却需要在运行时通过链接来进行
    • 想必其中的区别大家应该明白了,不过要注意,只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化
    public class Test {
        public static void main(String[] args)  {
            String a = "hello2"; 
            final String b = "hello";
            String d = "hello";
            String c = b + 2; 
            String e = d + 2;
            System.out.println((a == c));
            System.out.println((a == e));
        }
    }
    ​
    true
    false
    
  4. 不会被优化的情景

    public class Test {
        public static void main(String[] args)  {
            String a = "hello2"; 
            final String b = getHello();
            String c = b + 2; 
            System.out.println((a == c));
     
        }
         
        public static String getHello() {
            return "hello";
        }
    }
    false
    

2.2 被final修饰的引用变量指向的对象内容可变吗

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

  2. 样例

    public class Test {
        public static void main(String[] args)  {
            final MyClass myClass = new MyClass();
            System.out.println(++myClass.i);
     
        }
    }
     
    class MyClass {
        public int i = 0;
    }
    1
    

2.3 final和static

  1. static

    1. 方便在没有创建对象的情况下来进行调用(方法/变量)
  2. 区别

    1. static:static作用于成员变量用来表示只保存一份副本

      • static跟着类创生,类使用时候就恒定不变
    2. final:final的作用是用来保证变量不可变

      • final根据实际对象创生,对象不变值指向的对象就不变
  3. 样例

    public class Test {
        public static void main(String[] args)  {
            MyClass myClass1 = new MyClass();
            MyClass myClass2 = new MyClass();
            System.out.println(myClass1.i);
            System.out.println(myClass1.j);
            System.out.println(myClass2.i);
            System.out.println(myClass2.j);
     
        }
    }
     
    class MyClass {
        public final double i = Math.random();
        public static double j = Math.random();
    }
    

2.4 关于final参数的问题

  1. 核心:当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法外的变量

    • java参数传递核心是值传递
    • 整体使用可以对final修饰的值进行更改
    • 但在方法内部不可以对该值进行更改