Java中的final变量 final修饰变量 final修饰方法 final修饰类 final和String的关系

导读:本篇文章讲解 Java中的final变量 final修饰变量 final修饰方法 final修饰类 final和String的关系,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

引言

在开发的过程中,经常会使用String类来处理字符串相关的数据,如下获取文件名称代码:

public static void main(String[] args) {
   String filePath = "C:/Users/zxy/Desktop/test.docx";
   String fileName = StringUtils.substring(filePath, filePath.lastIndexOf("/")+1);
   System.out.printf("fileName = %s,fileName = %s", filePath, fileName);
 }

但今天去看String源代码时,发现这个类是用final修饰的,于是,决定去探究final关键字。

final修饰变量

final修饰变量,不可再改变量的值

final关键字可用于变量声明,一旦当前变量被设定,就不可以再改变当前变量的值,如下图所示:

在这里插入图片描述

当我试图去修改fileName的值,编辑器报出这个错误:Cannot assign a value to final variable 'fileName',翻译成中文就是不能给final修改的变量fileName赋值

final修饰对象,能否修改对象属性值

但是,当我们用final来修饰对象,能否修改对象属性的值呢,如下图所示:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Student {
  private String name;
  private int age;

  public static void main(String[] args) {
    final Student student = new Student("陈希尔", 18);
    System.out.println("student -- > " + student);

    student.name = "张韶涵";
    student.age = 23;
    System.out.println("student -- > " + student);

    // 报错:Cannot assign a value to final variable 'student'
    // student = new Student("程晨",12);
  }
}

输错结果:

在这里插入图片描述

由上可知,final修饰的对象不能重新指向新的对象,但是修饰的对象可以修改其属性值,如上述Student类。

final全局静态变量

在Java中定义全局常量,通常使用public static final修饰,这样的常量只能在定义时被赋值。

  public static final String APP_ID = "1234567890";

被定义为final的常量定义时需要使用大写字母命名,并且中间使用下划线进行连接。

final修饰方法

首先,我们应该了解定义为final的方法不能被重写,如下定义父类代码:

@Setter
@Getter
public class Animal {

  private String name;

  public Animal(String name) {
    this.name = name;
  }

  public final void introduce() {
    System.out.printf("我是 s% 动物 \n", name);
  }
}

在定义Dog子类,重写父类中的introduce()方法,如下图所示:
在这里插入图片描述

编辑器报出个错误:'introduce()' cannot override 'introduce()' in 'com.example.demo.finaldesc.Animal' ;overridden method is final,翻译成中卫便是:无法重写父类com.example.demo.finaldesc.Animal的introduce(),因为introduce()方法是用final修饰的

将方法定义为final类型可以防止任何子类修改该类的定义与实现方式,同时定义为final的方法执行效率要高于非final方法。

在修饰权限中曾经提到过private修饰符,如果一个父类的某个方法被设置为private修饰符,子类将无法访问该方法,自然无法覆盖该方法,所以一个定义为private的方法隐式被指定为final类型,这样无须将一个定义为private的方法再定义为final类型。

如果使用父类中的introduce(),如下代码所示:

private void introduce() {
 	System.out.printf("我是 s% 动物 \n", name);
}

在这里插入图片描述
此时Dog类中报出的错误是不能重写父类中的方法

final修饰类

定义为final的类不能被继承,比如上文所说的String类。

如果希望一个类不允许任何类继承,并且不允许其他人对这个类有任何改动,可以将这个类设置为final形式,如下代码所示:

@Setter
@Getter
public final class Animal {

  public void introduce() {
    System.out.printf("我是所有动物的父类 \n");
  }
}

我们再看dog类,如下图所示:
在这里插入图片描述
编辑器报出个错误:cannot inhreit from final 'com.example.demo.finaldesc.Animal',翻译成中卫便是:无法继承被final修饰的父类com.example.demo.finaldesc.Animal

如果将某个类设置为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。

重要总结

final关键字的好处

  • final关键字提高了性能。JVM和Java应用都会缓存final变量。

  • final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。

  • 使用final关键字,JVM会对方法、变量及类进行优化。

  • final修饰的类是不可变类。不可变类是指它的对象一旦被创建了就不能被更改了。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销等等。

final的重要知识点

  1. final关键字可以修饰成员变量、本地变量、方法以及类。
  2. final成员变量必须在声明时,初始化或者在构造器中初始化,否则就会报编译错误。
  3. 你不能够对final变量再次赋值。
  4. final修改的对象不能重新指向新的引用,但是可以修改其属性值。
  5. 本地变量必须在声明时赋值。
  6. 在匿名类中所有变量都必须是final变量。
  7. final方法不能被重写。
  8. final类不能被继承。
  9. final关键字不同于finally关键字,后者用于异常处理。
  10. final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
  11. 接口中声明的所有变量本身是final的。
  12. final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
  13. final方法在编译阶段绑定,称为静态绑定(static binding)。
  14. 没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
  15. 将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
  16. 按照Java代码惯例,final变量就是常量,而且通常常量名要大写。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99278.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!