倚楼听风雨
淡看江湖路

Java面向对象之final修饰符

书接上回《Java面向对象之类成员浅析》,老四引出了同学提出的一个探讨问题。关于final修饰符其实涉及到的知识点还是比较多比较杂的,所以老四也是想了一些时日,目的是希望能写的更清晰一些,方便理解和复查知识点。希望能对你有一点点帮助吧,写完final的知识点之后会顺便抛出几个面试中经常被提及到的面试/笔试题供你参考,最后会详细给出关于"为什么final static"经常连用的一些理由供你参考。

首先,你经常看到的或者听到的final修饰的变量不能被赋值这种说法是错误的!严格的说法是: final修饰的变量不可被改变,一旦获得了初始值,该final变量的值就不能被重新赋值了。

final可以可用于修饰类、变量(类变量、实例变量、局部变量以及形参)和方法,表示被final修饰的类、变量和方法不可改变。

1.final修饰变量

--final修饰成员变量(类变量和实例变量)

成员变量是随类初始化或对象初始化而初始化的。如果final修饰的成员变量没有指定初始值或者没有通过静态块、构造方法指定初始值,那么final的修饰就失去了意义,所以Java的语法规定我们码农使用final修饰的成员变量必须显式的指定初始值。final修饰类变量、实例变量能指定初始值的方式如下:

  • 类变量: 必须在静态初始块中指定初始值或声明该类变量时指定初始值,而且只能二选一。
  • 实例变量: 必须在非静态初始化块、声明该实例或者构造器中指定初始值,三选一。

--final修饰局部变量

众所周知,局部变量本身就要求我们高科技代码编写人员显式初始化,所以对于final修饰局部变量,既可以在定义的时候指定默认值,也可以不指定,不指定的时候可以在后面指定且只能指定一次,不允许重复指定。

注意: final修饰的形参不能被赋值,形参的值由根据传入的参数进行初始化。

--final修饰基本类型和引用类型

  • final修饰基本类型变量,不能对及基本类型变量重新赋值,基本类型变量的值不能被改变。
  • final修饰引用类型变量,保存的仅仅是一个引用,保证这个引用类型变量所引用的地址不变,但引用的对象或者引用的值是完全可以变的。

上面也解释了文章开头所说的"final修饰的变量不能被赋值"是错误的原因。

这里在补一些关于final变量"宏替换"的相关知识点,其实"final int glorze = 8;"这句话对于程序来说变量glorze是根本不存在的,这里面final相当于定义了一个宏变量"a",用这个"a"来代替5,这种宏变量还包含基本的算术表达式以及基本的字符串连接。我们都知道字符串: "高老四博客" = "高老四" + "博客"其实是一回事,他们都直接引用String常量池中的"高老四博客",然而

我们知道,因为无法在编译的时候确定s4的值,所以s4无法指向常量池中的"高老四博客",所以结果为false。当给s2和s3加上final修饰符来达到宏替换的目的,这样的话你就会看到输出的结果是true了。如果不太懂的话,可以好好研究一下。

2.final修饰方法

final修饰的方法不可以被重写,但是可以重载。最典型的例子就是Object中的getClass方法就是final修饰的。所以如果父类有final的方法,而子类也存在,那并不是重写,而是属于子类自己定义的,跟爷爷长得像而已。

3.final修饰类

final修饰的类不能有子类,Java.lang.Math就是活生生的例子。  我们知道Java的8个包装类是不可变类(创建该类的实例后,该实例的实例变量是不可改变的),他们底层都使用了final,同样我们自定义不可变的类需要哪些条件呢?

  • 使用private和final修饰符来修饰该类的成员变量。
  • 提供带参数的构造器,根据入参初始化成员变量。
  • 只提供getter方法
  • [可选]重写hashCode()和equals()方法。

然而,我们所说的不可变的类,根据前面所讲的,只是引用地址不变,值或者类型都是可变的,那么如何保证真正意义上的不可变呢?这里不做细讲,给一些提示: 构造方法中直接使用目标对象作为入参,使用目标对象的get方法实例化目标对象。。。(你就当没看见这句话。。。)

关于final修饰类,这里在引申一些东西,那就是缓存实例的不可变类。相信你们搞Java的都见过这段代码:

其实这里面就涉及到了不可变类的缓存技巧,底层也是使用final定义的不可变类实现缓存池利用先进先出的规则对数据进行处理,有兴趣也可以了解一下实现原理。

好了,基本的只是就算是说完了,告一段了,接下来在说为什么"static final"经常连用之前写几个关于final修饰经常被提及到的面试/笔试题,先当做基础知识的复习和标记。

1.final, finally, finalize的区别?

就特么因为长得像就放在一起问,也不知道哪个创始人出这种问题,不过咱们得受着,毕竟可以复习到知识,也能获取到相关修饰符的知识点。回答一下这三个词基本干啥的就行了,反正他们彼此互斥,没什么Jimmy Butler关系。。。

final就不说了,简单说一下finally和finalize:

  • finally: 异常块的一部分,不管什么情况里面的代码块都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally
  • finalize: Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用。

2.final关键字有哪些用法?

仔细看文章。

3.final与static 关键字可以用于哪里?它们的作用是什么?

仔细看这篇文章以及文章开篇的链接提到的关于static的文章。

4.能否在运行时向 static final 类型的赋值?

有的能,有的不能。至于为啥?仔细看文章!

5.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?

根据传统的中国封建制度,对象不能变啊。白头到老。

6.一个类被声明为final类型,表示了什么意思?

表明了这个类是final的人了,要动她,先问问铜锣湾final答不答应!!!

所以,static final为什么经常连用呢?

首先说连用的目的:static代表静态,final不允许重新赋值,所以就是说我们需要的是静态常量。那么我们使用静态常量的意义是什么呢?显而易见了,静态常量因为一直存放在静态空间中,因为final的原因不会被释放,一直存在内存当中,当一个常数、字符串或者对象是我们需要一直在程序中为我们所用的时候,就可以考虑使用静态常量,避免内存重复的申请和释放空间。说白了,这么问没有多么高深,只不过是一种情景之下的一种应对策略而已,为优化而考虑。

更博不易,喜欢的老铁有能力烦请赞助盒烟钱,点我去赞助。抱拳。

赞(83) 给你买杜蕾斯
本站原创文章受自媒体平台原创保护,未经允许不得转载高老四博客 » Java面向对象之final修饰符
分享到: 更多 (0)

开始你的表演 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下老四,鼓励我更好的创作

支付宝扫一扫打赏

微信扫一扫打赏