Java核心技术面试精讲
杨晓峰
前Oracle首席工程师
立即订阅
43250 人已学习
课程目录
已完结 43 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 以面试题为切入点,有效提升你的Java内功
免费
模块一 Java基础 (14讲)
第1讲 | 谈谈你对Java平台的理解?
第2讲 | Exception和Error有什么区别?
第3讲 | 谈谈final、finally、 finalize有什么不同?
第4讲 | 强引用、软引用、弱引用、幻象引用有什么区别?
第5讲 | String、StringBuffer、StringBuilder有什么区别?
第6讲 | 动态代理是基于什么原理?
第7讲 | int和Integer有什么区别?
第8讲 | 对比Vector、ArrayList、LinkedList有何区别?
第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同?
第10讲 | 如何保证集合是线程安全的? ConcurrentHashMap如何实现高效地线程安全?
第11讲 | Java提供了哪些IO方式? NIO如何实现多路复用?
第12讲 | Java有几种文件拷贝方式?哪一种最高效?
第13讲 | 谈谈接口和抽象类有什么区别?
第14讲 | 谈谈你知道的设计模式?
模块二 Java进阶 (16讲)
第15讲 | synchronized和ReentrantLock有什么区别呢?
第16讲 | synchronized底层如何实现?什么是锁的升级、降级?
第17讲 | 一个线程两次调用start()方法会出现什么情况?
第18讲 | 什么情况下Java程序会产生死锁?如何定位、修复?
第19讲 | Java并发包提供了哪些并发工具类?
第20讲 | 并发包中的ConcurrentLinkedQueue和LinkedBlockingQueue有什么区别?
第21讲 | Java并发类库提供的线程池有哪几种? 分别有什么特点?
第22讲 | AtomicInteger底层实现原理是什么?如何在自己的产品代码中应用CAS操作?
第23讲 | 请介绍类加载过程,什么是双亲委派模型?
第24讲 | 有哪些方法可以在运行时动态生成一个Java类?
第25讲 | 谈谈JVM内存区域的划分,哪些区域可能发生OutOfMemoryError?
第26讲 | 如何监控和诊断JVM堆内和堆外内存使用?
第27讲 | Java常见的垃圾收集器有哪些?
第28讲 | 谈谈你的GC调优思路?
第29讲 | Java内存模型中的happen-before是什么?
第30讲 | Java程序运行在Docker等容器环境有哪些新问题?
模块三 Java安全基础 (2讲)
第31讲 | 你了解Java应用开发中的注入攻击吗?
第32讲 | 如何写出安全的Java代码?
模块四 Java性能基础 (3讲)
第33讲 | 后台服务出现明显“变慢”,谈谈你的诊断思路?
第34讲 | 有人说“Lambda能让Java程序慢30倍”,你怎么看?
第35讲 | JVM优化Java代码时都做了什么?
模块5 Java应用开发扩展 (4讲)
第36讲 | 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
第37讲 | 谈谈Spring Bean的生命周期和作用域?
第38讲 | 对比Java标准NIO类库,你知道Netty是如何实现更高性能的吗?
第39讲 | 谈谈常用的分布式ID的设计方案?Snowflake是否受冬令时切换影响?
周末福利 (2讲)
周末福利 | 谈谈我对Java学习和面试的看法
周末福利 | 一份Java工程师必读书单
结束语 (1讲)
结束语 | 技术没有终点
Java核心技术面试精讲
登录|注册

第3讲 | 谈谈final、finally、 finalize有什么不同?

杨晓峰 2018-05-10
Java 语言有很多看起来很相似,但是用途却完全不同的语言要素,这些内容往往容易成为面试官考察你知识掌握程度的切入点。
今天,我要问你的是一个经典的 Java 基础题目,谈谈 final、finally、 finalize 有什么不同?

典型回答

final 可以用来修饰类、方法、变量,分别有不同的意义,final 修饰的 class 代表不可以继承扩展,final 的变量是不可以修改的,而 final 的方法也是不可以重写的(override)。
finally 则是 Java 保证重点代码一定要被执行的一种机制。我们可以使用 try-finally 或者 try-catch-finally 来进行类似关闭 JDBC 连接、保证 unlock 锁等动作。
finalize 是基础类 java.lang.Object 的一个方法,它的设计目的是保证对象在被垃圾收集前完成特定资源的回收。finalize 机制现在已经不推荐使用,并且在 JDK 9 开始被标记为 deprecated。

考点分析

这是一个非常经典的 Java 基础问题,我上面的回答主要是从语法和使用实践角度出发的,其实还有很多方面可以深入探讨,面试官还可以考察你对性能、并发、对象生命周期或垃圾收集基本过程等方面的理解。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Java核心技术面试精讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(88)

  • sharp
    这三个就是卡巴斯基和巴基斯坦的关系,有个基巴关系。。。
    2018-06-12
    3
    523
  • zjh
    一直不懂为什么这三个经常拿来一起比较,本身就一点关系都没有啊,难道仅仅是长的像。我觉得final倒是可以和volatile一起比较下
    2018-05-11
    3
    159
  • 云学
    请问这篇文章中涉及的知识点是java中最重要的吗?我感觉有点剑走偏锋,这种知识了解就好了,应该有很多知识比这更重要的吧,虽说面试中可能会问,但不能以面试为中心,而要把实际应用中最有用的真正核心的东西分享出来,把它讲透彻,不追求面面俱到,也不想成为语言专家,我期望通过这个专栏可以获得java中最核心最实用特性的本质认识,希望有一种醍醐灌顶的感觉,在阅读java开源框架代码时不再困惑。我有多年的c++开发背景,希望通过这个专栏对java也有提纲契领的本质认识。
    2018-06-12
    1
    139
  • WolvesLeader
    能不能帮我分析一哈,匿名内部累,访问局部变量时,局部变量为啥要用final来修饰吗?

    作者回复: 这个因为Java inner class实际会copy一份,不是去直接使用局部变量,final可以防止出现数据一致性问题

    2018-05-10
    2
    131
  • 石头狮子
    列几个 fianlly 不会被执行的情况:
    1. try-cach 异常退出。
    try{
    system.exit(1)
    }finally{
    print(abc)
    }

    2. 无限循环
    try{
      while(ture){
        print(abc)
      }
    }finally{
    print(abc)
    }

    3. 线程被杀死
    当执行 try,finally 的线程被杀死时。finally 也无法执行。


    总结
    1,不要在 finally 中使用 return 语句。
    2,finally 总是执行,除非程序或者线程被中断。
    2018-05-10
    115
  • ★神峰★
    你们都看懂了吗?我怎么什么都不知道😂
    2018-05-12
    98
  • Monday
    前提本节听了4遍,看了不下3遍,所花的时间大于4小时,写点心得与疑问。
    一道如此“简单”的面试题,能够引申出性能、安全、GC的问题,再扩展出一些我以前没接触过或知之甚少的知识点,如Cleaner、try-catch-resources、编写immutable对象、幻象引用等等。
    还有一些读起来很简单的语句,消化起来却很吃力,如:你无法保证finalize什么时候执行,执行是否符合预期。使用不当会影响性能,导致程序死锁,挂起等。又如:final class可以有效的避免API使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。
    疑问如下:
    1、本文中自己不熟悉的知识点,需要每一种都花时间去死扣吗?
    2、finalize使用不当会影响性能,导致程序死锁,挂起等,可否举几个通俗易懂的案例?
    3、final class可以有效的避免API使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。可否举知名案例证实若某类不设计为final class会导致更改其原有功能,进而影响平台安全?
    2018-09-26
    2
    49
  • 皮卡皮卡丘
    “将 State 定义为 static,就是为了避免普通的内部类隐含着对外部对象的强引用,因为那样会使外部对象无法进入幻象可达的状态。”这个该怎么理解呢?

    作者回复: 内部类如果不是static,它本身对外面那个类有引用关系,这一点其实从构造阶段就能看出来,你可以写段代码试试;有强引用就是strong reachable状态

    2018-05-10
    35
  • 有渔@蔡
    1.你说那异常被生吞,是指没写e.print...语句吧?另外我有个疑惑:super.clear()为什么写在exception里,理论上super方法写第一行,或finally里。2.在一个对象的生命周期里,其finalize方法应该只会被调用1次。3.强软弱虚引用大家都知道,这虚幻引用相比较有什么特别的吗?请再深入点。4.final是不是都在编译后确定位置?比如final List这样的,内存布局是怎样的?谢谢
    2018-05-10
    32
  • Loong
    final、finally、finalize

    1. final
    修饰类:不可被继承
    修饰方法:不可重写
    修饰变量:不可修改,只能约束引用不可以被再次赋值。匿名内部类访问局部变量时需要使用 final,因为 Innerclass 实际会 copy 一份局部变量,final 可以防止出现数据一致性问题

    2. finally:Java 保证重点代码一定要被执行的机制,try - finally,除非在 finally 前执行了 System.exit(1)、try 中死循环、线程被杀死

    3. finalize:基础类 Object 的一个方法,保证对象在被垃圾收集前完成特定的资源回收。由于 finalize 执行时间不确定且可能造成程序死锁、拖慢垃圾收集等问题,Java 9 中将改方法废弃
    优化:使用 Cleaner 配合幻想引用
    2018-12-03
    17
  • 🎵Children乏
    用final修饰的class,这可以有效避免 API 使用者更改基础功能,某种程度上,这是保证平台安全的必要手段。这个地方真的很需要个例子去帮助理解。比如大家都知道String类是被final修饰不可被继承,但假如没有被final修饰,很好奇会出现什么样不安全的后果。

    作者回复: 谢谢反馈

    2018-05-14
    17
  • Hesher
    见过一些写法是将对象手动赋值为null来让GC更快的回收,不过能起多少作用就不知道了。关于JVM中那几种引用了解不多,平时可以怎么使用呢?
    2018-05-10
    13
  • 小哥。
    copy-on-write 原则,学习了
    2018-05-10
    13
  • Pantheon
    杨老师,关于final不能修改我想请教下,代码如下,class util {
        public final Integer info = 123;
    }

    @Test
    public void test() throws NoSuchFieldException, IllegalAccessException {
        util util = new util();
        Field field = util.getClass().getDeclaredField("info");
        field.setAccessible(true);
        field.set(util,789);
        System.out.println(field.get(util));
        System.out.println(util.info);
    }
    这里final修饰的被改了,如果不加accessible这句会报错,刚刚试了几个,似乎是基本数据类型改不了,封装类型都能改,请杨老师解答下我的疑惑,感谢。

    作者回复: setAccessible是“流氓”,不问题出在定义为基本数据类型,会被当作constant,可以反编译看看

    2018-05-10
    12
  • Julian
    第3讲 | 谈谈final、finally、 finalize有什么不同的学习总结:
    一、final:适合用来在语义方面标识当前的方法、变量、类不可以更改,适合封装一些代码,让用的人知道这些不要随意更改。final标识的变量不等于不可变,对于变量而言这个变量只是不能够在赋值,但是可以做任何增删改查操作。所以从这方面来讲,final在高并发下面的数据一致性起来积极作用,对性能比较好。要想写一个不可变的对象,首先需要对象的类和成员都是private和final;其次对象的赋值不要直接赋值,而是采用深拷贝;然后对象不要随意实现setter方法;在获取当前对象内容或者状态时候要遵守copy-on-write 原则,创建私有的 copy。

    二、深拷贝与浅拷贝;其实这两个概念的区别就是当在给一个变量赋值时候是否直接使用这个值的内存地址;例如,基础类型都是值传递,所以浅拷贝过来的对象赋值后不会影响之前被拷贝的对象。但是对于引用类型的变量,在拷贝的时候就要考虑了,如果你要使新的对象的赋值不会影响之前被拷贝的对象,就要用深拷贝,否则就是copy的内存地址而已。一个类实现拷贝的功能很简单,有两种方式;要么实现Clone~接口,然后在clone方法里面进行拷贝;要是实现序列化,先把对象写到输入流里面,然后在读出来对象,这样就是一个新的对象了。

    三、finally:就是在一些资源处理关闭时候用到,对于try cath 最好即用即关;

    四、finalize:就是java虚拟机在实现gc时候调用的方法,理论上是进行内存回收等操作的地方。但是实际上这个方法调用时机并不固定,可能在处理不当导致程序异常。并且finalize源码实现使用了try cath 但是并没有抛出异常,而是生吞。所以你要是在这里面处理逻辑,你都不知道程序到底哪里出了问题。得出结论就是要放弃这个方法的实现。
    2018-12-12
    10
  • ls
    Java中有说:finalize 有一种用途:在 Java 中调用非 Java 代码,在非 Java 代码中若调用了C的 malloc 来分配内存,如果不调用 C 的free 函数,会导致内存泄露。所以需要在 finalize 中调用它。

    面试中会有问:为什么 String 会设计成不可变?想听听老师的解释

    作者回复: 是的,很多资源都是需要使用本地方式获取和释放

    2018-05-13
    9
  • 公号-代码荣耀
    1定义不可变对象类,当构造函数传入可变对象引用时、当getter函数返回可变对象引用时,容易掉坑。
    2 在不可变对象类的构造函数中,如果传入值包括了可变对象,则clone先。
    3 从不可变对象类的getter函数返回前,如果返回值为可变对象,则clone先。
    4 Java默认的clone方法执行浅拷贝,对于数组、对象引用只是拷贝地址。浅拷贝在业务实现中可能是一个坑,需要多加注意。
    5 如果步骤2、3中的浅拷贝无法满足不可变对象要求,请实现“深拷贝”。
    2018-05-10
    7
  • feifei
    JDK 自身使用的 Cleaner 机制仍然是有缺陷的,你有什么更好的建议吗?

    1,临时对象,使用完毕后,赋值为null,可以加快对象的回收
    2,公用资源对象,比如数据库连接,使用连接池
    3,native调用资源的释放,比如一个进程初始化调用一次,退出调用一次,这类场景可以考虑使用cleaner
    4,对尽量try-finally中完成资源的释放,即使用完毕就释放,最小化的使用,下次使用在申请。
    5,可以使用钩子进行程序的正常退出清理操作。

    此为我个人的一点小心得,欢迎老师指正,谢谢
    2018-06-30
    6
  • Do
    final修饰变量参数的时候,其实理解为内存地址的绑定,这样理解是不是更直观,基本类型指向栈中,引用类型指向堆中。老师后期文章能不能说下java堆栈的区别,还有变量局部变量的生命周期,最好能附上图,加深理解。

    作者回复: 会有

    2018-05-12
    6
  • echo_陈
    回答上面一个人的问题。
    被final修饰的变量不可变。如果初始化不赋值,后续赋值,就是从null变成你的赋值,违反不可变
    2018-05-10
    6
收起评论
88
返回
顶部