Java的final关键字在日常工作中经常会用到,比如定义常量的时候。如果是C++程序员出身的话,可能会类比C++语言中的define或者const关键字,但其实它们在语义上差距还是挺大的。

在Java中,final可以用来修饰类、方法和变量(包括成员变量和局部变量)。我们先来简单介绍一下final关键字的这几个用法。

一、final修饰类

常见的一个例子就是String类。当用final修饰一个类时,表明这个类不能被继承,并且final类中的所有成员方法都会被隐式地指定为final方法,但成员变量不会变。

一般来说,我们还是尽量不要将类设计为final类,除非我们出于某些因素的考虑必须这么做。比如不希望类被继承,也就是说不希望类被修改语义。如果我们继承String类,那么就可以定义一个可被修改的String类,这对于String类的使用者来说近乎是一种灾难。

二、final修饰方法

使用final修饰方法有两个原因:

  1. 是把方法锁定,以防任何继承类修改它的含义;

  2. 是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。

同final类相似,只有在想明确禁止该方法在子类中被覆盖的情况下才将方法设置为final。另外,类的private方法会隐式地被指定为final方法,其语义要求private方法不能被重新定义。

三、final修饰变量

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

由于final变量初始化之后无法修改,针对这个特性,Java编译器对此进行了优化。当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。这个优化通常对于程序逻辑没有太多影响,但如果用==比较的时候,可能会出乎意料。具体可以参考之前的文章《Java自动装箱和拆箱》

综上所述,final在修饰类和方法时,代表不能再修改其定义,而在修饰变量时,则类似C++中的const关键字,用于表示常量。

一个好的编程习惯是我们应该尽量将变量声明为final的,除非变量必须是可变的。例如当你在方法中不需要改变作为参数的变量时,可以使用final进行声明,这样可以防止你无意的修改,尤其是当你的方法很长很复杂的时候。当然是否用final修饰参数,都不会影响方法之外的变量。

使用final关键字还有个好处,是它能确保初始化过程的安全性,可以不受限制的访问不可变对象,并在多线程共享这些对象时无须同步。当我们有多个基本类型的变量,他们之前需要保持数据一致的时候,通常的办法是使用synchronized关键字来保证对这些变量操作的原子性。如果使用final关键字,我们可以定义新类,包含这些变量(用final修饰),这样这些变量就成了常量,变量修改操作就成了赋值操作(是原子操作),这样就避免了使用加锁同步。当然不可修改的变量也会导致很多小对象的生成,加重垃圾回收的负担,相较而言可以忽略了。

最后,我们知道,在匿名内部类的方法参数只能访问final类型的局部变量,编译器也强制要求这一点,这是为什么呢?其根本原因在于局部变量的生命周期与匿名内部类对象的生命周期不一致。局部变量所在的方法执行完之后,匿名内部类对象仍然存在,这时匿名内部类对象就无法访问到该局部变量,因为该局部变量的生命周期已经结束。使用final修饰局部变量,其实是将局部变量“复制”了一份,复制品直接作为局部内部中的数据成员,这样就解决的生命周期不一致的问题。

聊聊Java的final关键字的更多相关文章

  1. JAVA面向对象-----final关键字

    JAVA面向对象-–final关键字 1:定义静态方法求圆的面积 2:定义静态方法求圆的周长 3:发现方法中有重复的代码,就是PI,圆周率. 1:如果需要提高计算精度,就需要修改每个方法中圆周率. 4 ...

  2. java之final关键字

    final关键字(可以读不可以写.只读) 1.final的变量的值不能够被改变 ①.final的成员变量 ②.final的局部变量(形参) //意思是“实参”一旦传进我的方法里面,就不允许改变 2.f ...

  3. Java的final关键字详解

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  4. java中final 关键字的作用

    final 关键字的作用 java中的final关键字可以用来声明成员变量.本地变量.类.方法,并且经常和static一起使用声明常量. final关键字的含义: final在Java中是一个保留的关 ...

  5. Java基础 -- final关键字

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

  6. Java中final关键字修饰变量、方法、类的含义是什么

    Java中的关键字final修饰变量.方法.类分别表示什么含义? 先看一个简单的介绍 修饰对象 解释说明 备注 类 无子类,不可以被继承,更不可能被重写. final类中的方法默认是final的 方法 ...

  7. java浅析final关键字

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. ...

  8. 关于Java中final关键字的详细介绍

    Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...

  9. java基础---->final关键字的使用

    这里介绍一些java基础关于final的使用,文字说明部分摘自java语言规范.心甘情愿这四个字,透着一股卑微,但也有藏不住的勇敢. Final关键字的说明 一.关于final变量规范说明 .A fi ...

随机推荐

  1. matlab for 运算的提速

    [1]主要思想:matlab是按列存储,定义s(nums,1)比定义s(1,nums)要快哦                       需要重复query的元素看看能不能再for之前就定义好 经典案 ...

  2. js小功能记录

    个人日常中遇到的js小功能记录,方便查看. /** * 判断是否包含字符串某字符串 * @param {[type]} str [被检测的字符串] * @param {[type]} substr [ ...

  3. C++模式学习------原型模式

    原型模式: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.意思就是从A的实例得到一份与A内容相同,但是又互不干扰的实例B. class base { public : base(co ...

  4. MySQL 测试工具(基准测试、压力测试)

    1.sysbench sysbench是跨平台的基准测试工具,支持多线程,支持多种数据库: 主要包括以下几种测试: cpu性能 磁盘io性能 调度程序性能 内存分配及传输速度 POSIX线程性能 数据 ...

  5. windows和Ubantu双系统安装图解

    Win7 U盘安装Ubuntu16.04 双系统详细教程 安装主要分为以下几步: 一. 下载Ubuntu 16.04镜像软件: 二. 制作U盘启动盘使用ultraISO: 三. 安装Ubuntu系统: ...

  6. 015 反射中的 Class.forName() 与 ClassLoader.loadClass() 的区别

    作者:nnngu GitHub:https://github.com/nnngu 博客园:http://www.cnblogs.com/nnngu 简书:https://www.jianshu.com ...

  7. Divisibility by 25 CodeForces - 988E(模拟)

    遇见模拟题 有两种做法 例如这题: 1.直接去算次数(统计哪个数在第几位,然后去运算) 2.模拟操作 贴一个别人的代码...https://blog.csdn.net/weixin_39453270/ ...

  8. Ifter Party LightOJ - 1014(水题)

    题意:有C个人,给P个食物,每人吃Q个,剩L个.然后给你P和L(Q>L),让你求Q的可能情况,如果有多种可能,从小到大输出:如果不存在,输出impossible 就是求写出公式 遍历c求P-L的 ...

  9. variant conversion error for variable v23

    excel数据导入到oracle数据库出现的问题 V23指的是excel列.,这列的数据长度超出或者类型与数据库表不一致导致的 解决方法,1.清空该列,再建个新列 2.用access  SQL查出长度 ...

  10. 批量更新 A表的PK_ID字段

    UPDATE  ASET PK_ID=(SELECT ID FROM  B WHERE A.TAB_NAME=B.TAB_NAME AND B.IS_KEY='1' ) AB表 以TAB_NAME 做 ...