final

简介: final

1.简述final作用?

2.为什么局部内部类和匿名内部类只能访问局部final变量?

1.简述final作用?


final:最终的

修饰类: 表示类不可被继承

修饰方法: 表示方法不可被子类覆盖,但是可以重载

修饰变量:表示变量一旦被赋值就不可以更改它的值。

(1) 修饰成员变量

  • 如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初始值.
  • 如果final修饰的是成员变量,可以在非静态初始化块、声明该变量或者构造器中执行初始值。

(2) 修饰局部变量

系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。因此使用final修饰局部变量时,即可以在定义时指定默认值(后面的代码不能对变量再赋值),也可以不指定默认值,而在后面的代码中对final变量赋初值 (仅一次)

public class FinalVar {
      static final int a=0;//再声明的时候就需要赋值,或者静态代码块赋值
      final int b=0;//再声明的时候就需要赋值,或者代码块中赋值,或者构造器赋值
      public static void main(String[] args) {
      final int localA;//局部变量只声明没有初始化,不会报错,与final无关
      localA=0;//在使用之前一定要赋值,但是不允许第二次赋值
      }
}

(3) 修饰基本类型数据和引用类型数据

  • 如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改
  • 如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是引用的值是可变的.
public class FinalReferenceTest {
  public static void main(String[] args) {
    final int[] iArr= {1,2,3,4};
    iArr[2]=-3;//合法
    //iArr=null;//非法,对iArr不能重新赋值
    final Person p=new Person(25);
    p.setAge(24);//合法
    //p=null;//非法
  }
}
class Person {
  int age;
    Person(int age){
      this.age=age;
    }
    public int getAge() {
      return age;
    }
    public void setAge(int s_age) {
      age=s_age;
    }
}

2.为什么局部内部类和匿名内部类只能访问局部final变量


public class Test {
  public static void main(String[] args) {
    // TODO Auto-generated method stub
  }
  public void test(final int b) {
    final int a=10;
    //匿名内部类
    new Thread() {
      public void run() {
        System.out.println(a);
        System.out.println(b);
      }
    }.start();
  }
}
class OutClass{
  private int age=12;
  public void outPrint(final int x) {
    class InClass{
      public void InPrint() {
        System.out.println(x);
        System.out.println(age);
      }
    }
    new InClass().InPrint();
  }
}

首先需要知道的一点是:内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。

这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(只有没有人再引用它时,才会死亡)。这里就出现了一个矛盾: 内部类对象访问了一个不存在的变量。为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的“copy”。这样就好像延长了局部变量的生命周期

将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的,也就是如果我们在内部类中修改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?

就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协。使得局部变量与内部类内建立的拷贝保持一致。

目录
相关文章
|
编解码 Ubuntu 编译器
Qt开发笔记之编码x264码流并封装mp4(四):mp4v2库的介绍和windows平台编译
Qt开发笔记之编码x264码流并封装mp4(四):mp4v2库的介绍和windows平台编译
Qt开发笔记之编码x264码流并封装mp4(四):mp4v2库的介绍和windows平台编译
|
1月前
|
Java API 开发工具
百宝箱开放平台 ✖️ Java SDK
百宝箱提供Java SDK,支持开发者集成其开放能力。需先发布应用,准备Java 8+及Maven环境,通过添加依赖安装SDK,并初始化客户端调用对话型或生成型智能体,实现会话管理、消息查询与文件上传等功能。
1262 0
百宝箱开放平台 ✖️ Java SDK
|
7月前
|
机器学习/深度学习 人工智能 自然语言处理
人工智能技术的探讨
人工智能的概念,人工智能的发展,人工智能的各种学派,人工智能的应用领域
347 4
【编程基础知识】正数负数的二进制位运算(左移 右移 无符号右移)
正数和负数需转换成二进制后进行移位运算。左移低位补0,不影响符号位;右移符号位跟随移动,最高位还原为原符号位;无符号右移高位补0,适用于负数处理。
855 0
|
数据采集 机器学习/深度学习 数据挖掘
揭秘DataFrame缺失值处理的神秘面纱:从填充到删除,再到插值,你的数据能否起死回生?
【8月更文挑战第22天】在数据分析中,处理DataFrame内的缺失值至关重要。本文通过一个关于公司员工基本信息的例子,展示了三种常见方法:填充、删除和插值。首先构建了一个含有缺失值的DataFrame,然后使用均值填充年龄缺失值;接着演示了删除含缺失值的行;最后采用线性插值填补。此外,对于复杂情形,还可利用机器学习预测填充。合理处理缺失值能有效提升数据质量,为后续分析奠定坚实基础。
338 2
微服务注册中心技术选型:5种主流注册中心,哪个最香?
讲解5种常用的注册中心,对比其流程和原理,无论是面试还是技术选型,都非常有帮助。 对于注册中心,在写这篇文章前,我其实只对ETCD有比较深入的了解,但是对于Zookeeper和其它的注册中心了解甚少,甚至都没有考虑过ETCD和Zookeeper是否适合作为注册中心。 经过近2周的学习,原来注册中心除了ETCD和Zookeeper,常用的还有Eureka、Nacos、Consul,下面我们就对这些常用的注册中心,初探它们的异同,便于后续技术选型。 全文接近 8千字,有点长,建议先收藏,再慢慢看,下面是文章目录:
|
新零售 Cloud Native 安全
光云科技快麦ERP正式入选阿里云原生合作伙伴计划,赋能企业“新基建”
阿里云在云原生领域的投入广泛而深入,在容器、服务网格和 Serverless 等领域均有丰富的技术和产品体系,目前阿里云已经拥有国内最丰富的云原生产品家族、最全面的云原生开源贡献、最大规模的云原生应用实践、最大的云原生客户群体。
1411 89
光云科技快麦ERP正式入选阿里云原生合作伙伴计划,赋能企业“新基建”
|
机器学习/深度学习 JavaScript 前端开发
Jupyter Notebook好用在哪?
Jupyter Notebook好用在哪?
389 0
阿里云效平台java代码扫描问题的修复
关于在阿里云效平台进行java代码扫描后 遇到问题的解释以及如何修复。
阿里云效平台java代码扫描问题的修复