全面解析java final关键字

 更新时间:2021年01月21日 11:21:34   作者:Spear_J  
这篇文章主要介绍了java final关键字的使用,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下

根据上下文环境,Java 的关键字 final 的含义有些微的不同,但通常它指的是“这是不能被改变的”。防止改变有两个原因:设计或效率。因为这两个原因相差很远,所以有可能误用关键字 final。

以下几节讨论了可能使用 final 的三个地方:数据、方法和类。

1)final 数据

对于编译时常量这种情况,编译器可以把常量带入计算中,可以减少了一些运行时的负担。在 Java 中,这类常量必须是基本类型,而且用关键字 final 修饰。你必须在定义常量的时候进行赋值。

带有恒定初始值的 final static 基本变量(即编译时常量)命名全部使用大写,单词之间用下划线分隔。

一个被 static 和 final 同时修饰的属性只会占用一段不能改变的存储空间。

当用 final 修饰对象引用而非基本类型时,

  • 对于基本类型,final 使数值恒定不变。
  • 对于对象引用,final 使引用恒定不变。

一旦引用被初始化指向了某个对象,它就不能改为指向其他对象。但是,对象本身是可以修改的,Java 没有提供将任意对象设为常量的方法。(你可以自己编写类达到使对象恒定不变的效果)这一限制同样适用数组,数组也是对象。

示例:

import java.util.*;

class Value {
  int i;
  Value(int i) {
    this.i = i;
  }
}

/**
 * @author Limh
 */
public class FinalData {
  private static Random rand = new Random(47);
  private String id;

  public FinalData(String id) {
    this.id = id;
  }
  private final int valueOne = 9;
  private static final int VALUE_TWO = 99;
  public static final int VALUE_THREE = 39;
  private final int i4 = rand.nextInt(20);
  static final int INT_5 = rand.nextInt(20);
  private Value v1 = new Value(11);
  private final Value v2 = new Value(22);
  private static final Value VAL_3 = new Value(33);
  private final int[] a = {1, 2, 3, 4, 5, 6};

  @Override
  public String toString() {
    return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
  }

  public static void main(String[] args) {
    FinalData fd1 = new FinalData("fd1");
    //v2=new Value(22);
    fd1.v2.i++;
    fd1.v1 = new Value(9);
    //a.length = 6
    for (int i = 0; i < fd1.a.length; i++) {
      fd1.a[i]++;
    }
    System.out.println(fd1);
    System.out.println("Creating new FinalData");
    FinalData fd2 = new FinalData("fd2");
    System.out.println(fd1);
    System.out.println(fd2);
  }
}

输出:

fd1: i4 = 15, INT_5 = 18
Creating new FinalData
fd1: i4 = 15, INT_5 = 18
fd2: i4 = 13, INT_5 = 18

因为第一个变量和第二个变量都是带有编译时值的 final 基本类型,它们都可用作编译时常量,没有多大区别。第三个变量是一种更加典型的常量定义的方式:public 意味着可以在包外访问,static 强调只有一个,final 说明是一个常量。

正如你在 main() 中所见,v2 是 final 的并不意味着你不能修改它的值。因为它是引用,所以只是说明它不能指向一个新的对象。

2)空白final

空白 final 指的是没有初始化值的 final 属性。

编译器确保空白 final 在使用前必须被初始化。这样既能使一个类的每个对象的 final 属性值不同,也能保持它的不变性。

你必须在定义时或在每个构造器中执行 final 变量的赋值操作。这保证了 final 属性在使用前已经被初始化过。

3)final参数

在参数列表中,将参数声明为 final 意味着在方法中不能改变参数指向的对象或基本变量:

class Gizmo {
  public void spin() {

  }
}

/**
 * @author Limh
 */
public class FinalArguments {
  void with(final Gizmo g) {
    //-g = new Gizmo(); 
    // Illegal -- g is final
  }

  void without(Gizmo g) {
    g = new Gizmo(); // OK -- g is not final
    g.spin();
  }

  //void f(final int i) { i++; } // Can't change
  // You can only read from a final primitive
  int g(final int i) {
    return i + 1;
  }

  public static void main(String[] args) {
    FinalArguments bf = new FinalArguments();
    bf.without(null);
    bf.with(null);
  }
}

4) final方法

使用 final 方法的原因有两个。

给方法上锁,防止子类通过覆写改变方法。这是出于继承的考虑,确保方法的行为不会因继承而改变。
只有在为了明确禁止覆写方法时才使用 final。

5) final和private

类中所有的 private 方法都隐式地指定为 final。因为不能访问 private 方法,所以不能覆写它。

6)final类

当说一个类是 final (final 关键字在类定义之前),就意味着它不能被继承。之所以这么做,是因为类的设计就是永远不需要改动,或者是出于安全考虑不希望它有子类。

由于 final 类禁止继承,类中所有的方法都被隐式地指定为 final,所以没有办法覆写它们。你可以在 final 类中的方法加上 final 修饰符,但不会增加任何意义。

以上就是全面解析java final关键字的详细内容,更多关于java final关键字的资料请关注脚本之家其它相关文章!

相关文章

  • Jenkins自动化打包为war包

    Jenkins自动化打包为war包

    这篇文章主要介绍了Jenkins自动化打包为war包,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 一文带你学会Spring JDBC的使用

    一文带你学会Spring JDBC的使用

    JDBC 就是 数据库开发 操作的 代名词,因为只要是现代商业项目的开发那么一定是离不开 数据库 的,不管你搞的是什么,只要是想使用动态的开发结构,那么一定就是 JDBC ,那么下面来教教大家传统JDBC的使用
    2022-09-09
  • 详解SpringBoot如何自定义一个Starter

    详解SpringBoot如何自定义一个Starter

    小伙伴们曾经可能都经历过整天写着CURD的业务,都没写过一些组件相关的东西,这篇文章记录一下SpringBoot如何自定义一个Starter。原理和理论就不用多说了,可以在网上找到很多关于该方面的资料,这里主要分享如何自定义
    2022-11-11
  • SpringBoot配置@Configuration注解和@bean注解

    SpringBoot配置@Configuration注解和@bean注解

    这篇文章主要介绍了SpringBoot配置@Configuration注解和@bean注解,文章围绕主题相关内容展开详细介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-04-04
  • JAVA中StackOverflowError错误的解决

    JAVA中StackOverflowError错误的解决

    这篇文章主要介绍了JAVA中StackOverflowError错误的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • java反射之获取类的信息方法(推荐)

    java反射之获取类的信息方法(推荐)

    下面小编就为大家带来一篇java反射之获取类的信息方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • SpringBoot添加License的多种方式

    SpringBoot添加License的多种方式

    License指的是版权许可证,当我们开发完系统后,如果不想让用户一直白嫖使用,比如说按时间续费,License的作用就有了。我们可以给系统指定License的有效期,控制系统的可用时间。
    2021-06-06
  • Mybatis中@Param注解的作用说明

    Mybatis中@Param注解的作用说明

    这篇文章主要介绍了Mybatis中@Param注解的作用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Spring AbstractRoutingDatasource 动态数据源的实例讲解

    Spring AbstractRoutingDatasource 动态数据源的实例讲解

    本文介绍如何使用 Spring AbstractRoutingDatasource 基于上下文动态切换数据源,因此我们会让查找数据源逻辑独立于数据访问之外
    2021-07-07
  • Java根据身份证号计算年龄,15位身份证号码转18位原理与操作示例

    Java根据身份证号计算年龄,15位身份证号码转18位原理与操作示例

    这篇文章主要介绍了Java根据身份证号计算年龄,15位身份证号码转18位原理与操作,结合实例形式详细分析了构成身份证号码的各个位的含义,15位身份证号码转18位的方法及Java根据身份证号计算年龄相关操作技巧,需要的朋友可以参考下
    2019-10-10

最新评论