导语

在java的关键字中,staticfinal是两个我们必须掌握的关键字。不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。

关于static请查阅前一篇文章:夯实基础:详解static关键字和4类场景应用

下面我们来了解一下final关键字及其用法。

final关键字

在java中,final的含义在不同的场景下有细微的差别,但总体上来说,它指的是“这是不可变的”。下面,我们来讲final的四种主要用法。

1.修饰数据

在编写程序时,我们经常需要说明一个数据是不可变的,我们成为常量。在java中,用final关键字修饰的变量,只能进行一次赋值操作,并且在生存期内不可以改变它的值。更重要的是,final会告诉编译器,这个数据是不会修改的,那么编译器就可能会在编译时期就对该数据进行替换甚至执行计算,这样可以对我们的程序起到一点优化。不过在针对基本类型和引用类型时,final关键字的效果存在细微差别。我们来看下面的例子:

 1 class Value { 2 int v; 3 public Value(int v) { 4 this.v = v; 5 } 6 } 7  8 public class FinalTest { 9 10 final int f1 = 1;11 final int f2;12 public FinalTest() {13 f2 = 2;14 }15 16 public static void main(String[] args) {17 final int value1 = 1;18 // value1 = 4;19 final double value2;20 value2 = 2.0;21 final Value value3 = new Value(1);22 value3.v = 4;23 }24 }

上面的例子中,我们先来看一下main方法中的几个final修饰的数据,在给value1赋初始值之后,我们无法再对value1的值进行修改,final关键字起到了常量的作用。从value2我们可以看到,final修饰的变量可以不在声明时赋值,即可以先声明,后赋值。value3时一个引用变量,这里我们可以看到final修饰引用变量时,只是限定了引用变量的引用不可改变,即不能将value3再次引用另一个Value对象,但是引用的对象的值是可以改变的,从内存模型中我们看的更加清晰:

上图中,final修饰的值用粗线条的边框表示它的值是不可改变的,我们知道引用变量的值实际上是它所引用的对象的地址,也就是说该地址的值是不可改变的,从而说明了为什么引用变量不可以改变引用对象。而实际引用的对象实际上是不受final关键字的影响的,所以它的值是可以改变的。

另一方面,我们看到了用final修饰成员变量时的细微差别,因为final修饰的数据的值是不可改变的,所以我们必须确保在使用前就已经对成员变量赋值了。因此对于final修饰的成员变量,我们有且只有两个地方可以给它赋值,一个是声明该成员时赋值,另一个是在构造方法中赋值,在这两个地方我们必须给它们赋初始值。

最后我们需要注意的一点是,同时使用static和final修饰的成员在内存中只占据一段不能改变的存储空间。

2.修饰方法参数

前面我们可以看到,如果变量是我们自己创建的,那么使用final修饰表示我们只会给它赋值一次且不会改变变量的值。那么如果变量是作为参数传入的,我们怎么保证它的值不会改变呢?这就用到了final的第二种用法,即在我们编写方法时,可以在参数前面添加final关键字,它表示在整个方法中,我们不会(实际上是不能)改变参数的值:

public class FinalTest { /* ... */ public void finalFunc(final int i, final Value value) { // i = 5; 不能改变i的值 // v = new Value(); 不能改变v的值 value.v = 5; // 可以改变引用对象的值 }}

3.修饰方法

第三种方式,即用final关键字修饰方法,它表示该方法不能被覆盖。这种使用方式主要是从设计的角度考虑,即明确告诉其他可能会继承该类的程序员,不希望他们去覆盖这个方法。这种方式我们很容易理解,然而,关于private和final关键字还有一点联系,这就是类中所有的private方法都隐式地指定为是final的,由于无法在类外使用private方法,所以也就无法覆盖它。

4.修饰类

了解了final关键字的其他用法,我们很容易可以想到使用final关键字修饰类的作用,那就是用final修饰的类是无法被继承的。

上面我们讲解了final的四种用法,然而,对于第三种和第四种用法,我们却甚少使用。这不是没有道理的,从final的设计来讲,这两种用法甚至可以说是鸡肋,因为对于开发人员来讲,如果我们写的类被继承的越多,就说明我们写的类越有价值,越成功。即使是从设计的角度来讲,也没有必要将一个类设计为不可继承的。Java标准库就是一个很好的反例,特别是Java 1.0/1.1中Vector类被如此广泛的运用,如果所有的方法均未被指定为final的话,它可能会更加有用。如此有用的类,我们很容易想到去继承和重写他们,然而,由于final的作用,导致我们对Vector类的扩展受到了一些阻碍,导致了Vector并没有完全发挥它应有的全部价值。

总结

final关键字是我们经常使用的关键字之一,它的用法有很多,但是并不是每一种用法都值得我们去广泛使用。它的主要用法有以下四种:

  1. 用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
  2. 用来修饰方法参数,表示在变量的生存期中它的值不能被改变;
  3. 修饰方法,表示该方法无法被重写;
  4. 修饰类,表示该类无法被继承。

上面的四种方法中,第三种和第四种方法需要谨慎使用,因为在大多数情况下,如果是仅仅为了一点设计上的考虑,我们并不需要使用final来修饰方法和类。

final关键字_夯实基础:Java中final关键字的几种用法相关推荐

  1. java中常量final的用法_详解Java中final的用法

    本文主要介绍了Java中final的使用方法,final是java的关键字,本文就详细说明一下它的使用方法,需要的朋友可以参考下 概念 final 具有"不可改变的"的含义,可以修 ...

  2. java中的标识符和关键字_浅谈java中的标识符、修饰符和关键字

    合法标识符 Java语言中,对于变量,常量,函数,语句块均有名字,我们统统称之为Java标识符.标识符是用来给类.对象.方法.变量.接口和自定义数据类型命名的. 组成:Java标识符由数字,字母和下划 ...

  3. java 死锁 内存消耗_详解Java中synchronized关键字的死锁和内存占用问题

    先看一段synchronized 的详解: synchronized 是 java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并 ...

  4. python中list[1啥意思_详解Python中list[::-1]的几种用法

    本文主要介绍了Python中list[::-1]的几种用法,分享给大家,具体如下: s = "abcde" list的[]中有三个参数,用冒号分割 list[param1:para ...

  5. python的上下文管理用哪个关键字_正确理解python中的关键字“with”与上下文管理器...

    正确理解python中的关键字"with"与上下文管理器 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  正确理解python中的关键字&quo ...

  6. java volatile有什么用_深入解析Java中volatile关键字的作用

    在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...

  7. java 夯实基础_夯实基础-java equals使用,和 == 的区别

    在研究hashcode的用法,发现自己对equals的理解还不够深,废话少说,继续专研,记录如下: 要想搞清楚equals和==的区别,就先要搞清楚JAVA的数据类型: java的数据类型只要分两大类 ...

  8. python无限循环的关键字_零基础学python-12.2 关键字pass,else,break,continue

    关键字pass,else,break,continue pass:不做任何事情,只占位 else:当正常跳出循环时执行 break:满足某些条件跳出循环,不再执行任何东西 continue:满足某些条 ...

  9. Java中for循环的几种用法

    参考一些博客整理的资料笔记,以备后续查看. 目录 1 常用的几种方法 1.1 for(; ; ) 1.2 Collection for( Iterator i=kindsList.iterator() ...

最新文章

  1. thinkphp_ajax分页实现_无需整理
  2. 【重磅】杨强,陈云霁团队提名2020年度国家科学技术奖!!!
  3. 验证视图MAC失败 Validation of ViewState MAC Failed
  4. PHP与SQL注入***(实战篇五)
  5. FastDFS扩展开发说明
  6. python手机版iphone-Python编程狮下载
  7. 【Python】又一个Jupyter神器,操作Excel自动生成Python代码!
  8. bzoj 3343 教主的魔法 分块
  9. CodeForces - 551C GukiZ hates Boxes(二分+贪心)
  10. 【PAT甲级 删除字符串中的指定字符】1050 String Subtraction (20 分) C++
  11. [MM9]复制格式的快捷操作
  12. mysql timestamp类型比较_MySQL timestamp 类型比较的测试
  13. 学Python必须背的42个常见单词
  14. 绘制grib2格式大气数据(windows下 GrADS wgrib2 g2ctl perl)
  15. Linux - vim编辑器,tmux的简单使用
  16. python制作二维码并打印_通过python扫描二维码/条形码并打印数据
  17. 【vpn异地组网专题】爱快ikuai软路由-VM虚拟机安装教程
  18. python_opencv_haze加雾处理
  19. 【Mac使用技巧】Mac的VMware虚拟机系统时间如何调成不同步
  20. Elasticsearch:理解 Elasticsearch 中的 Percolator 数据类型及 Percolate 查询

热门文章

  1. 解决mysql从windows迁移到centos出现乱码问题
  2. jvm lock低性能分析
  3. hdu 1176:免费馅饼
  4. 五大领域总目标指南_每日干货 | 五大领域 学前社会教育1
  5. go web框架_golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web
  6. 报告PPT|Python网络程序设计教学要点与案例分享(含音频)
  7. Python+pandas填充缺失值的几种方法
  8. 详解Python变量作用域
  9. Python+tkinter实现任意多层级关系的组合框
  10. sdk版本过低怎么办_区块链中的“块”是什么?区块链网络拥堵怎么办?-Gemini双子新约...