Java中final关键字的使用与注意总结

 更新时间:2020年08月19日 16:30:30   作者:IBLiplus  
这篇文章主要给大家介绍了关于Java中final关键字的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

在java中可以将实例域定义为final。在构建对象是必须初始化这样的值。必须确保在每个构造器执行之后,这个域的值被设置,并且在后面的操作中不再对其修改。使用final声明变量之后,这个值就不能修改,一般final类型的变量都被声明为静态变量,而且是公有类型的,它在内存中被放在一个特有的公共区域。

也就是说,在Java语法中规定,final修饰的成员变量必须有程序员显式地指定初始值。

定义格式为: public  static  final  double pi = 3.1415926;

final修饰符大多应用于基本类型域,或不可变类的域(如果类中的每个方法都不会改变其对象,这种类成为不可变类。比如说Java中的String类就是一个不可变类。)

如果定义了两个相同的变量,都是final类型的,这两个相同的变量名有着不同的值,其实在内存中是开辟了两个内存空间,之前定义的变量的值会被后来定义的变量的值覆盖掉。原理是变量名指向后来定义的变量值的内存空间,之前定义的变量值会被Java虚拟机根据某种特定的算法在特定的时间处理掉。

在下面的代码中详细的介绍了final类型的变量如何进行定义和初始化:

public class FinalVariableText {
 //定义成员变量是指定默认值,合法
 final int a = 6;
 //下面变量将在构造器或初始化块中分配初始值
 final String str;
 final int c ;
 final static double d;
 //既没有指定默认值,也没有在初始化块、构造器中指定初始值
 //下面定义的ch实例变量是不合法的
 //final char ch;
 
 {
 //在初始化块中只懂初始值,合法
 str ="hello" ;
 //定义a实例变量已经有初始值了,不能为a重新赋值。下面的语句是不正确的
 //a = 9;
 }
 
 //静态初始化块
 static {
 // d是静态成员变量,必须在静态初始化块中为其指定初始值
 d = 5.6;
 
 }
 //构造器,可对 没有设置初始值的成员变量设置初始值
 //构造器必须与类名相同,这一点注意!
 public FinalVariableText(){
 //如果在初始化块中对str赋初值,在构造器中在为str重新赋值,是不合法的,程序会抛出错误。
 c = 5;
 }
 
 public void changeFinal() {
 //普通方法不能为final修饰的成员变量赋值
 //d = 1.3;
 //也不能在普通方法中为没有设置初始值的final类型的变量赋初值
 //ch = 'ch';
 
 }
 
 public static void main(String[] args) {
  
 FinalVariableText ff = new FinalVariableText();
 System.out.println(ff.a);
 System.out.println(ff.c);
 System.out.println(ff.str);
 System.out.println(ff.d); 
 }

结果:
6
5
hello
5.6

注意:

如果打算在构造器、初始化块中对final类型的成员变量进行初始化,则不要在初始化之前访问成员变量的值,否则会引发程序报错。

final也存在局部变量的情况

系统不会对局部变量进行初始化,局部变量必须由程序员显式的进行初始化,因此使用final修饰局部变量的时候,既可以在定义是设定默认值,也可以不指定默认值。如果在定义是没有进行设定默认值,则可以在后面的代码中对该final变量赋初值,但只能一次,不可以重复赋值。当然如果在定义变量的时候就已经指定默认值,在后面的代码中就没有必要也不允许对该变量在进行赋值操作。

 public void text(final int a) {
 //不能对fianl修饰的形参进行赋值操作
 //a = 5; 该语句是不合法的
 }
 public static void main(String[] args) {
  //定义final局部变量时,指定初始值,则该变量再无法进行赋值了
 final String str = "str";
 //下面的语句会报错,不合法
 //str = "Java";
 //定义final变量没有指定默认值,则可以被赋值一次
 final int d;
 d = 5;
 //再对d进行新的赋值,不合法
 // d = 8;
 
 }

Final修饰基本类型变量和引用类型的变量的区别

Final修饰基本类型变量上面已经讲述的很清楚了,那引用类型的变量会有什么不同呢?对于引用类型的变量而言,它仅仅是保存了一个引用关系,final只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。下面通过代码来验证一下:

class Person1{
 
 private int age;
 //有一个参数的构造函数
 public Person1(int age) {
 this.age = age; 
 }
 public int getAge() {
 return age;
 }
 public void setAge(int age) {
 this.age = age;
 }
}
 
public class FinalReferenceText {
 
 public static void main(String[] args) {
  
  final int [] arr = {5,6,12,9};
  System.out.println(Arrays.toString(arr));
  Arrays.sort(arr);
  System.out.println(Arrays.toString(arr));
  arr[2] = -8;
  System.out.println(Arrays.toString(arr));
  //下面对arr重新赋值,非法
  //arr = null;
  //final 修饰Person变量,p是一个引用变量
  final Person1 p = new Person1(45);
  //改变Person对象的实例变量,合法
  p.setAge(55);
  System.out.println(p.getAge());
  //下面对p重新赋值,非法
  //p = null;
 }
 
}

结果:
[5, 6, 12, 9]
[5, 6, 9, 12]
[5, 6, -8, 12]
55

final方法

Final修饰的方法不可被重写,如果处于某种原因,不希望子类重写父类的某个方法,则可以使用final关键字修饰该方法。

如果父类中的方法的是公有的,则子类中不能有一个一样方法名,一样参数的方法,但如果父类中的方法是私有的,那么子类中完全可以写一个一样的方法。

对于private类型的方法,由于其只能在当前类中可见,其子类无法访问到该方法,所以子类无法重写该方法,那么,如果子类中存在一个与父类private方法有相同方法名,一样的参数列表,相同的返回值的方法,也不是方法的重写,只是重新定义了一个新的方法。因此,final修饰一个private方法,依然可以在其子类中定义和父类private类型一样的方法,不会有程序错误。

public class PrivateFinalText{
 
 //如果将访问修饰符改成public,则其子类中的方法定义在程序编译时会报错
 private final void text();
 
}
 
class Sub extends PrivateFinalText{
 //下面的方法完全没有问题
 public void text();
}

以上是我目前对Java中final关键字的总结,稍后会有补充!!!

总结

到此这篇关于Java中final关键字的文章就介绍到这了,更多相关Java的final关键字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中的几种读取properties配置文件的方式

    Java中的几种读取properties配置文件的方式

    这篇文章主要介绍了Java中的几种读取properties配置文件的方式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • java使用任务架构执行任务调度示例

    java使用任务架构执行任务调度示例

    在Java 5.0之前启动一个任务是通过调用Thread类的start()方法来实现的,5.0里提供了一个新的任务执行架构使你可以轻松地调度和控制任务的执行,并且可以建立一个类似数据库连接池的线程池来执行任务,下面看一个示例
    2014-01-01
  • 自定义注解实现Spring容器注入Bean方式(类似于mybatis的@MapperScans)

    自定义注解实现Spring容器注入Bean方式(类似于mybatis的@MapperScans)

    本文介绍了如何通过自定义注解@MyService和@MyServiceScans在SpringBoot项目中自动将指定包下的类注入Spring容器,详细解释了创建自定义注解、定义包扫描器ClassPathBeanDefinitionScanner的作用与实现
    2024-09-09
  • Springboot 多租户SaaS搭建方案

    Springboot 多租户SaaS搭建方案

    这篇文章主要介绍了Springboot 多租户SaaS方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • Struts 2中的constant配置详解

    Struts 2中的constant配置详解

    通过对这些属性的配置,可以改变Struts 2 框架的一些默认行为,这些配置可以在struts.xml文件中完成,也可以在struts.properties文件中完成
    2016-09-09
  • Java通用Mapper UUID简单示例

    Java通用Mapper UUID简单示例

    今天小编就为大家分享一篇关于Java通用Mapper UUID简单示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • Spring Web MVC和Hibernate的集成配置详解

    Spring Web MVC和Hibernate的集成配置详解

    这篇文章主要介绍了Spring Web MVC和Hibernate的集成配置详解,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • java IP地址网段计算的示例代码

    java IP地址网段计算的示例代码

    这篇文章主要介绍了java IP地址网段计算的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • IDEA运行SSM项目的超详细图解教程

    IDEA运行SSM项目的超详细图解教程

    SSM项目部署其实很简单,下面这篇文章主要给大家介绍了关于IDEA运行SSM项目的超详细图解教程,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • Java异常处理机制深入理解

    Java异常处理机制深入理解

    如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器
    2022-01-01

最新评论