说明
阅读HashMap 时遇到很多final修饰的方法参数的情况,当时查阅一些文章没太理解精髓,近日接受新项目发现每个方法都是如此修饰的,激发了好奇心,想深入学习一下这个为你。
一、final关键字介绍
1、final 修饰类
- final修饰类的时候,被修饰的类不能被继承,注意final类中的所有成员方法都会被隐式地指定为final方法,继承编译不通过
2、final 方法
final修饰的方法根据《java变成思想》中的说明:
“使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。“
因此,如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。
注:类的private方法会隐式地被指定为final方法。
3、final 修饰变量
对于变量,不可在对其赋值,否则编译不通过。基本类型:
引用类型:
对于修饰的变量会变为常量,编译期即可确定其值,个人理解如果再次赋值会改变该引用的指向,就失去了"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
原因:
变量a指的是字符串常量池中的 hello2;
变量 b 是 final 修饰的,变量 b 的值在编译时候就已经确定了它的确定值,换句话说就是提前知道了变量 b 的内容到底是个啥,相当于一个编译期常量;
变量 c 是 b + 2得到的,由于 b 是一个常量,所以在使用 b 的时候直接相当于使用 b 的原始值(hello)来进行计算,所以 c 生成的也是一个常量,a 是常量,c 也是常量,都是 hello2 而 Java 中常量池中只生成唯一的一个 hello2 字符串,所以 a 和 c 是相等的!
d 是指向常量池中 xiaomeng,但由于 d 不是 final 修饰,也就是说在使用 d 的时候不会提前知道 d 的值是什么,所以在计算 e 的时候就不一样了,e的话由于使用的是 d 的引用计算,变量d的访问却需要在运行时通过链接来进行,所以这种计算会在堆上生成 hello2 ,所以最终 e 指向的是堆上的 hello2 , 所以 a 和 e 不相等。
总得来说就是:a、c是常量池的hello2,e是堆上的hello2
二、问题结果
用final修饰形参是为了保证在方法中不能对传入对象做任何修改,不能我传入mytest.NewTeacher@3830f1c0,返回mytest.NewTeacher@3830f1c1或者其它。目的可能是假如方法比较大,入参在前面的方法被修改了会影响其他方法,给修改者一个提示作用吧。