为了账号安全,请及时绑定邮箱和手机立即绑定

final关键字

标签:
Java

    final是Java中的一个修饰符,可以用来修饰类,变量,方法。而对于final的理解,也主要围绕这三者来进行。

一、final修饰类

    被final修饰的类我们称为不可变类,例如Java中的String类就是不可变类,他表示该类不能被继承,并且该类

中的方法会默认为final类型,但被final修饰的类中的成员属性并不会默认为final,我们在变成中可根据需求,确定属性

是否为final的。将类设计为final是出于该类不可被继承和一些安全性的考虑。否则就不要将类设计为final了。

二、final修饰方法

    使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在

早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。

在最近的Java版本中,不需要使用final方法进行这些优化了

三、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));    }}

结果:

truefalse

这个例子可以很完美体现出二者之间的区别。final修饰基本数据类型或者String类型,要么在定义处进行初始化赋值,要么在

构造器中进行初始化赋值,否则编译报错,赋值之后这个值便不能再被改变,因此Java的编译器很人性化的做了这样一个功能,

就是编译时优化,凡是被final修饰的变量都会进行编译期优化,因为他们的值在编译期已经确定了,因此String c = b + 2直接被

优化为"hello2",而且这个hello2是在字符串常量池中创建的,然而String a = "hello2",已经在字符串常量池中创建了一个hello2,

因此c就不会再创建了,而是直接指向了a所指向的那个hello2,因此a == c为true。而a == e为什么为false是因为当进行

String e = d + 2操作时相当于进行的是new String("hello2"),此时的e指向的是堆中的一个hello2对象,而a指向的是常量池中的,

因此为false。

换应该注意,只有在编译期确切知道变量值才会进行优化,否则则不会进行优化。

public class Test {    public static void main(String[] args)  {        String a = "hello2";         final String b = getHello();        String c = b + 2;         System.out.println((a == c));     }         public static String getHello() {        return "hello";    }}

结果:

false
  • 被final修饰的引用变量所指向的对象的内容是可变的

  • final与static修饰变量的区别?

public class Test {    public static void main(String[] args)  {        MyClass myClass1 = new MyClass();        MyClass myClass2 = new MyClass();        System.out.println("final i:" + myClass1.i);        System.out.println("static j:" + myClass1.j);        System.out.println("final i:" + myClass2.i);        System.out.println("static j:" + myClass2.j);     }} class MyClass {    public final double i = Math.random();    public static double j = Math.random();}

结果:

final i:0.19008381769339489static j:0.04553435249234561final i:0.24184639133515862static j:0.04553435249234561

观察发现,尽管调用了两次j,但是值是一样的,所以可知,final修饰变量强调的是该变量不可再被修改,而static修饰变量强调的是

该变量是全局的,静态的,整个类中只能存在一份静态的j,所有该类的实例对象对它的调用都调用的是同一份数据。

  • final也可以修饰方法中的参数

    同理上面也讲过了,当为值传递时,在该方法内这个参数不能再被修改,当为引用传递时,引用的指向不能再被改变,但对象内容还是可以改变的

三、final与线程安全

    final修饰引用或变量表示不可变,而且该引用或变量也不能被缓存,所以缓存变量的问题也不复存在,因此java可以让你安全的访问

final的属性而无需同步。因此他与volatile不能连用。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消