Java的final关键字详解

final 在 java 中有什么作用?

一般有五种用法

  • final修饰类

    格式:

    public final class 类名称{
            //.. 
    }
    

    限制:

    • 被修饰的类不能有任何子类
    • 也就意味着所有方法都不能被重写
    • 类中不能有抽象方法或者不能与抽象类并存

    注意:一个类是final的,那么所有成员方法都无法进行覆盖重写,final类中的成员变量可以根据需要设置成final,但是final类下的所有方法都会隐式的指定为final方法,在使用final修饰类的的时候,一定要慎重选择,除非这个类以后不会用来继承或者出于安全考虑,尽量不要将类设计成final类

  • final修饰方法

    格式:

    修饰符 final 返回值类型 方法名称(){
      .....
    }
    
    • 当final用来修饰一个方法的时候,这个方法就是最终方法,那么很明显就是说不能被覆盖重写

    使用final修饰方法的原因:1.把方法锁死,防止任何继承类修改他的含义。2.效率。在早期的Java实现版本中,会将final方法转为内嵌调用。如果方法过于庞大,可能看不到内嵌调用的带来的任何性能提升。在最近的java版本中,不需要用final方法进行这些优化。

    此外还要注意一点:因为重写的前提是子类可以从父类中继承此方法,如果父类方法中final修饰的方法同时访问的权限为private,将会导致子类中不能直接继承到此方法,因此,此时可以在子类中定义相同名字和参数的方法。此时不在产生重写的与final的矛盾,而在子类中重新定义新的方法。(注:类的private方法会隐式的指定final方法)

  • final修饰变量

    格式:

    final 变量类型 变量名称=变量值
    

    限制:

    • 基本数据类型:第一次赋值后面就不能改变了。
    • 引用数据类型:第一次被赋值(对象的地址值),该引用的地址值将无法改变。

    final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常由final定义的变量称为常量,常量名一般推荐使用大写字母表示,如果变量名有多个部分使用下划线"_"分隔。

  • final修饰参数

    在实际应用中,我们除了可以用final修饰成员变量、成员方法、类,还可以修饰参数、若某个参数被final修饰了,则代表了该参数是不可改变的。如果在方法中我们修改了该参数,则编译器会提示你:

    Cannot assign a value to final variable 'aa'
    
  • 空白final

    空白final指的是被声明为final但又未给定初始值的域,无论什么情况,编译器都确保空白final在使用前必须被初始化。比如下面这段代码:

    public class FinalTest{
          private int i;
          private final int j;
          public FinalTest(inti,intj){
          this.i=i;
          this.j=j;
          }
    }
    

    必须在域的定义处或者每个构造器中用表达式对final进行赋值,这正是final域在使用前总是被初始化的原因所在。

深入了解final关键字

​ **类的final变量和普通变量的区别:**当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。

​ 下面看一下两个例子:

public static void main(String[] args) {
        String a = "helloworld";
        final String b="hello";
        String c = "hello";
        String x = b + "world";
        String y = c + "world";
        System.out.println(a == x);
        System.out.println(a == y);
}

输出结果为true false

大家可以先想一下这道题的输出结果。为什么第一个比较结果为true,而第二个比较结果为fasle?大家可以动动手看看编译之后的代码是什么样的,这里就不做展示了

这里面就是final变量和普通变量的区别了,当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。

​ 再看一个例子

 public static void main(String[] args) {
        String a = "helloworld";
        final String b;
        b="hello";
        String c = "hello";
        String x = b + "world";
        String y = c + "world";
        System.out.println(a == x);
        System.out.println(a == y);
    }

输出结果为 false false,神奇吧,也可以看一下编译之后的class文件,会让你幡然醒悟的(别问,我也是这样的)

被final修饰的引用变量指向的对象内容可变,直接上代码

 public static void main(String[] args) {
        final Student student=new Student();
        student.anInt++;
        System.out.println(student.getAnInt());

    }
    public static   class  Student{
        private int anInt=0;

        public int getAnInt() {
            return anInt;
        }

        public void setAnInt(int anInt) {
            this.anInt = anInt;
        }
    }

这段代码可以顺利编译通过并且有输出结果,输出结果为1。这说明引用变量被final修饰之后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值