前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于final关键字的两个面试题

关于final关键字的两个面试题

作者头像
半月无霜
发布2023-03-03 14:32:19
2760
发布2023-03-03 14:32:19
举报
文章被收录于专栏:半月无霜半月无霜

关于final关键字的两个面试题

一、介绍

final关键字常用,但真的了解它吗。我做一下记录,仅供参考

  • 简述final的作用
  • 为什么局部内部类和匿名内部类只能访问局部的final变量

二、简述final的作用

final是一个修饰符,表示最终的,不可被修改

  • 修饰类:表示类不可被继承,所以抽象类不能使用final关键字
  • 修饰方法:表示方法不能被重写,但是可以进行重载
  • 修饰变量:表示赋值后就不能修改该变量的值

修饰变量时,有几种情况

修饰成员变量时

代码语言:javascript
复制
public class Demo {

    // 声明时直接赋值
    final int a = 1;

    // 在代码块中进行赋值
    final int b;
    {
        b = 2;
    }

    // 在构造函数中进行赋值
    final int c;
    public Demo(int c) {
        this.c = c;
    }
}

修饰局部变量时

代码语言:javascript
复制
public class Demo0 {

    public static void main(String[] args) {
		final int a = 1;// 一旦赋值无法改变
        final int b;// 在声明时,可以不赋值
        b = 2;// 在使用前一定要进行赋值
        System.out.println(a + b);
    }
}

修饰静态变量时

代码语言:javascript
复制
public class Demo {

    // 直接赋值
    static final int a = 1;
    
    // 在静态代码块中赋值
    static final int b;
    static {
        b = 2;
    }
    
}

修饰基本数据类型和引用类型时

代码语言:javascript
复制
public class Demo {

    public static void main(String[] args) {
        final int a = 1;
        a = 2;// 不可修改
        
        final Person person = new Person("半月", 18);
        person.setName("半月无霜");// 可以进行修改,final声明的只是person这个局部变量
        person = new Person("半月无霜", 22);// 不允许修改
    }
}

@Data
@AllArgsConstructor
class Person {
    String name;
    int age;
}

三、局部内部类和匿名内部类

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

这的确是一个好问题,我们一起来看看

先简单写出局部内部类和匿名内部类,发现他们使用外部的变量时,外部变量都要用final修饰,不然idea直接爆红了。

image-20220305184215565
image-20220305184215565
image-20220305190654868
image-20220305190654868

Variable used in lambda expression should be final or effectively final 简单翻译一下:在lambda表达式中使用变量应该是final或者有效的final 还有局部内部类,也有这样的问题 Variable ‘number1’ is accessed from within inner class, needs to be final or effectively final 在内部类中访问number1,需要final或者有效的final

它提到了final,要进行修饰这些变量

代码语言:javascript
复制
package com.banmoon.algorithm.order;

public class Demo {

    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.test1(10);
        demo.test2(10);
    }

    public void test1(int number1){
        int number2 = 1;
        number1 = number1 + number2;
        number2 = 10;
        final int finalNumber = number1;
        final int finalNumber1 = number2;
        new Thread(() -> {
            System.out.println(finalNumber);
            System.out.println(finalNumber1);
        }).start();
    }

    public void test2(int number1){
        int number2 = 1;
        number1 = number1 + number2;
        number2 = 10;
        int finalNumber = number1;
        int finalNumber1 = number2;
        class InnerClass {
            public void print(){
                System.out.println(finalNumber);
                System.out.println(finalNumber1);
            }
        }
    }
}

为什么不能直接使用呢,原因也很简单。

因为,在进行编译java文件时,上面提到了内部类会生成独立的class文件。

那么问题随之而来,匿名内部类和局部内部类想要使用外部的变量该怎么办,编译时候它是怎么做的?它直接将外部的变量复制了一份在内部类中。

好的那么,问题又来了。外部类中有一份,内部类中也有一份,数据不一致该怎么办。干脆一刀切算了,直接使用final关键字吧。

像上面示例的27和28行,虽然它没有final修饰,但也可以编译通过,这两个变量已经不会再做更改了。不过在使用内部类的时候,还是得小心,最好还是加上final

四、最后想说的话

我是半月,祝你幸福!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于final关键字的两个面试题
    • 一、介绍
      • 二、简述final的作用
        • 三、局部内部类和匿名内部类
          • 四、最后想说的话
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档