面试官:小伙子来说一说Java中final关键字,以及它和finally、finalize()有什么区别?

简介: 面试官:“小伙子,用过final关键字吗?”我:“必须用过呀”面试官:“好,那来说一说你对这个关键字的理解吧,再说一说它与finally、finalize()的区别”我:“好嘞!

写在开头

面试官:“小伙子,用过final关键字吗?”
我:“必须用过呀”
面试官:“好,那来说一说你对这个关键字的理解吧,再说一说它与finally、finalize()的区别”
我:“好嘞!”

final中文释义:最终的,最后的;在Java中作为关键字的一种,被用来修饰变量、方法、类,final 语义是不可改变的。

final修饰变量

当final修饰变量时有如下几点需要注意:

1、final 修饰表示常量、一旦创建不可改变;
2、final 修饰的局部变量必须在声明时给定初值;
3、final 修饰的成员变量必须在声明时给定初值或者在构造方法内设置初始值,只能读取,不可修改;
4、被 final 修饰的成员变量必须要初始化,赋初值后不能再重新赋值(可以调用对象方法修改属性值)。
   对基本类型来说是其值不可变;对引用变量来说其引用不可变,即不能再指向其他的对象;

【代码示例】

public class Test {
   
   
    private String name;
    public final int age = 18;
    //和static一同修饰时,被当做常量
    private static final int HIGH = 180;

    public String getName() {
   
   
        return name;
    }
    public void setName(String name) {
   
   
        this.name = name;
    }
    public int getWeight(){
   
   
        final int weight;
        //修饰局部变量时,不能再赋值,需要在声明时给定初始值!
        return weight;
    }
    public static void main(String[] args) {
   
   
       final Test test = new Test();
       // 给一个被final修饰的引用类型重新赋值,编译器会报错,提示取消final修饰
       //test = new Test();
        // 但给这个引用类型进行属性赋值是可以的!
        test.setName("JavaBuild");
        //final修饰的成员变量,给定初始值后不可再修改,但可以调用
        if(test.age == 18){
   
   
            System.out.println("永远18岁");
        }
    }
}

final修饰方法

当final修饰方法时需要注意:

1、final修饰的方法:只能使用,不能被子类重写,但能够类内重载;

【代码示例】

public class Test extends Animal{
   
   
    //方法的重写不被允许
    public void run(){
   
       
    }
}
class Animal {
   
   
    public final void run(){
   
   
        System.out.println("我会跑");
    }
    //方法的重载,被允许
    public final void run(String dog){
   
   
        System.out.println("我会跑");
    }
}

image.png

final修饰类

当final修饰方法时需要注意:

1final修饰的类不能被继承,没有子类;
2final 类中的方法默认是 final 的,比如String类;

【代码示例】

public class Test extends Animal{
   
   

}
 final class Animal {
   
   
    public final void run(){
   
   
        System.out.println("我会跑");
    }
}

image.png

final、finally、finalize()三者的区别?

final

见上文

finally

finally 异常处理的一部分,它只能用在 try/catch 语句中,表示希望 finally 语句块中的代码最后一定被执行(存在一些情况导致 finally 语句块不会被执行,如 jvm 结束)
不被执行的情况:

  • 直接返回未执行到 try-finally 语句块
  • 抛出异常未执行到 try-finally 语句块
  • 系统退出未执行到 finally 语句块

【代码示例】

public static String test() {
   
   
    String str = null;
    int i = 0;
    if (i == 0) {
   
   
        return str;//直接返回未执行到finally语句块
    }
    try {
   
   
        System.out.println("try...");
        return str;
    } finally {
   
   
        System.out.println("finally...");
    }
}

public static String test2() {
   
   
    String str = null;
    int i = 0;
    i = i / 0;//抛出异常未执行到finally语句块
    try {
   
   
        System.out.println("try...");
        return str;
    } finally {
   
   
        System.out.println("finally...");
    }
}

public static String test3() {
   
   
    String str = null;
    try {
   
   
        System.out.println("try...");
        System.exit(0);//系统退出未执行到finally语句块
        return str;
    } finally {
   
   
        System.out.println("finally...");
    }
}

finalize()

finalize() 是在 java.lang.Object 里定义的,Object 的 finalize() 方法什么都不做,对象被回收时 finalize() 方法会被调用。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要清理工作,在垃圾收集器删除对象之前被调用的。
一般情况下,此方法由JVM调用。特殊情况下,可重写 finalize() 方法,当对象被回收的时候释放一些资源,须调用 super.finalize() 。

目录
相关文章
|
22天前
|
Java
【Java集合类面试二十八】、说一说TreeSet和HashSet的区别
HashSet基于哈希表实现,无序且可以有一个null元素;TreeSet基于红黑树实现,支持排序,不允许null元素。
|
22天前
|
Java
【Java集合类面试二十三】、List和Set有什么区别?
List和Set的主要区别在于List是一个有序且允许元素重复的集合,而Set是一个无序且元素不重复的集合。
|
22天前
|
存储 Java 索引
【Java集合类面试二十四】、ArrayList和LinkedList有什么区别?
ArrayList基于动态数组实现,支持快速随机访问;LinkedList基于双向链表实现,插入和删除操作更高效,但占用更多内存。
|
22天前
|
Java
【Java集合类面试二十二】、Map和Set有什么区别?
该CSDN博客文章讨论了Map和Set的区别,但提供的内容摘要并未直接解释这两种集合类型的差异。通常,Map是一种键值对集合,提供通过键快速检索值的能力,而Set是一个不允许重复元素的集合。
【多线程面试题十】、说一说notify()、notifyAll()的区别
notify()唤醒单个等待对象锁的线程,而notifyAll()唤醒所有等待该对象锁的线程,使它们进入就绪队列竞争锁。
|
22天前
|
安全 Java
【Java集合类面试十六】、HashMap与ConcurrentHashMap有什么区别?
HashMap是非线程安全的,而ConcurrentHashMap通过减少锁粒度来提高并发性能,检索操作无需锁,从而提供更好的线程安全性和性能。
|
22天前
|
算法 Java
【多线程面试题十八】、说一说Java中乐观锁和悲观锁的区别
这篇文章讨论了Java中的乐观锁和悲观锁的区别,其中悲观锁假设最坏情况并在访问数据时上锁,如通过`synchronized`或`Lock`接口实现;而乐观锁则在更新数据时检查是否被其他线程修改,适用于多读场景,并常通过CAS操作实现,如Java并发包`java.util.concurrent`中的类。
|
22天前
|
Java
【多线程面试题十三】、说一说synchronized与Lock的区别
这篇文章讨论了Java中`synchronized`和`Lock`接口在多线程编程中的区别,包括它们在实现、使用、锁的释放、超时设置、锁状态查询以及锁的属性等方面的不同点。
【多线程面试题九】、说一说sleep()和wait()的区别
sleep()和wait()的主要区别在于sleep()是Thread类的静态方法,可以在任何地方使用且不会释放锁;而wait()是Object类的方法,只能在同步方法或同步代码块中使用,并会释放锁直到相应线程通过notify()/notifyAll()重新获取锁。
【多线程面试题 三】、 run()和start()有什么区别?
run()方法定义线程执行的任务,而start()方法启动线程,使得run()在新的线程中异步执行;直接调用run()方法只会同步执行run()中的代码,不会创建新线程。