Java Review (十八、面向对象----对象与垃圾回收),java面试指南

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

}

public void finalize () {

System.out.println (" 系统正在清理 GcTest 对象的资源 . . . ") ;

}

}

编译、运行上面程序 , 看不到任何输出,可见直到系统退出 , 系统都不曾调用 GcTest 对象的 finalize()方法 。 但如果将程序修改成如下形式 :

GcTest.java

public class GcTest {

public static void main(String[] args) {

for (int i = 0 ; i < 4 ; i++) {

new GcTest();

// 下面两行代码的作用 完全相同,强制系统进行垃圾回收

//System.gc() ;

Runtime.getRuntime() . gc();

}

}

public void finalize () {

System.out.println (" 系统正在清理 GcTest 对象的资源 . . . ") ;

}

}

上面程序与前一个程序相比,增加了强制系统进行垃圾回收代码 。 编译上面程序,使用如下命令来运行此程序 :

java -verbose:gc GcTest

图三:垃圾回收的运行提示信息

在这里插入图片描述

运行 Java 命令时指定 -verbose :gc 选项,可以看到每次垃坡回收后的提示信息,如图三所示 。

从图三 中可以看出,每次调用了 Runtime.getRuntime(). gc()代码后 , 系统垃圾回收机制 还是"有所动作"的,可以看出垃圾回收之前、回收之后的内存占用对 比 。

虽然图三显示了程序强制垃圾回收的效果,但仍然要认识到这种强制只是建议系统立即进行垃坡回收 , 系统完全有可能并不立即进行垃圾回收,垃圾回收机制也不会对程序的建议完全置之不理 : 垃圾回收机制会在收到通知后,尽快进行垃圾回收 。

finalize 方法

=============================================================================

在垃圾回收机制回收某个对象所占用的内存之前,通常要求程序调用适当的方法来清理资源 , 在没有明确指定清理资源的情况下, Java 提供了默认机制来清理该对象的资源,这个机制就是 finalize()方法 。

该方法是定义在 Object 类里的实例方法,方法原型为 :

protected void finalize() throws Throwable

当 finalize()方法返回后,对象消失,垃圾回收机制开始执行 。方法原型中的 throws Throwable 表示它可以抛出任何类型的异常 。

任何 Java 类都可以重写 Object 类的 finalizeO方法,在该方法中清理该对象占用的资源 。 如果程序终止之前始终没有进行垃圾回收,则不会调用失去引用对象的 finalize()方法来清理资源 。

垃圾回收机制何时调用对象的 finalizeO方法是完全透明的,只有当程序认为需要更多的额外内存时,垃圾回收机制才会进行垃坡回收 。 因此,完全有可能出现这样一种情形:某个失去引用的对象只占用了少量内存,而且系统没有产生严重的内存需求,因此垃圾回收机制并没有试图回收该对象所占用的资源,所以该对象的自finalize()方法也不会得到调用。

finalize()方法具有如下 4 个特点 :

  • 永远不要主动调用某个对象的 finalize()方法,该方法应交给垃圾回收机制调用 。

  • finalize()方法何时被调用,是否被调用具有不确定性 ,不要把自finalize()方法当成一定会被执行的方法 。

  • 当 JVM 执行可恢复对象的 finalize()方法时,可能使该对象或系统中其他对象重新变成可达状态。

  • 当执行 finalize()方法时出现异常时,垃圾回收机制不会报告异常,程序继续执行 。

下面程序演示了如何在 finalize()方法里复活自身,并可通过该程序看出垃圾回收的不确定性。

FinalizeTest.java

public class FinalizeTest {

private static FinalizeTest ft = null;

public void info() {

System.out.println( "测试资源清理的 finalize 方法 " );

}

public static void main(String[] args) throws Exception{

// 创建 FinalizeTest 对象立即进入可恢复状态

new FinalizeTest() ;

// 通知系统进行资源回收

System.gc(); //①

// 强制垃圾回收机制调用可恢复对象的 finalize ()方法

// Runtime.getRuntime() . runFinalization() ; //②

System.runFinalization(); //③

ft.info();

}

public void finalize() {

// 让 ft 引用到试图回收的可恢复对象,即可恢复对象重新变成可达

ft = this;

}

}

上面程序中定义了 一个 FinalizeTest 类,重写了该类的 finalizeO方法,在该方法中把需要清理的可恢复对象重新赋给 a 引用变量,从而让该可恢复对象重新变成可达状态。

上面程序中的 main()方法创建了 一个 FinalizeTest 类的匿名对象,因为创建后没有把这个对象赋给任何引用变量,所以该对象立即进入可恢复状态 。 进入可恢复状态后:

  • 系统调用①号字代码通知系统进行垃圾回收

  • ②号代码强制系统立即调用可恢复对象的 finalize()方法,再次调用位对象的 info()方法 。编译、运行上面程序 , 看到 info()方法被正常执行 。

  • 如果删除①行代码,取消强制垃圾回收 。 再次编译、运行上面程序,将会看到如图四所示的结果 。

图四:调用info()方法时引发空指针异常

在这里插入图片描述

从图四所示的运行结果可以看 出,如果取消①号代码,程序并没有通知系统开始执行垃圾回收(而且程序内存也没有紧张 ) ,因此系统通常不会立即进行垃圾回收,也就不会调用 FinalizeTest对象的 fmalize()方法,这样 FinalizeTest 的ft类变量将依然保持为 null,这样就导致了空指针异常 。

上面程序中②号代码和③号代码都用于强制垃圾回收机制调用可恢复对象的 finalize()方法,如果程序仅执行 System.gc(); 代码,而不执行②号或③号代码一一由于 JVM垃圾回收机制的不确定性,JVM往往并不立即调用可恢复对象的 finalize()方法,这样 FinalizeTest 的ft类变量可能依然为 null ,可能依然会导致空指针异常。

对象的软、弱和虚引用

============================================================================

对大部分对象而言 ,程序里会有一个引用变量引用该对象,这是最常见的引用方式 。 除此之外,还有软引用、弱引用、虚引用。

在这里插入图片描述

1. 强引用 (StrongReference)


强引用就是指在程序代码之中普遍存在的,类似 "Object obj = new Object()” 这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。

2. 软引用 (SoftReference)


软引用是用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中进行第二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2之后,提供了 SoftReference类来实现软引用。

3. 弱引用 (WeakReference)


弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,被弱引用 关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当 前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK 1.2之后,提供WeakReference类来实现弱引用。

4. 虚引用 (PhantomReference)


虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚 引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实 例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一 个系统通知。在JDK 1.2之后,提供了 PhantomRcfcrcncc类来实现虚引用。

上面三个引用类都包含了 一个 get()方法,用于获取被它们所引用的对象 。

引用队列由 java. lang.ref.ReferenceQueue 类表示,它用于保存被回收后对象的引用 。 当联合使用软引用、弱引用和引用队列时,系统在回收被引用的对象之后,将把被回收对象对应的引用添加到关联的引用队列中。与软引用和弱引用不同的是,虚引用在对象被释放之前,将把它对应的虚引用添加到它关联的引用队列中,这使得可以在对象被回收之前采取行动 。

软引用和弱引用可以单独使用,但虚引用不能单独使用,单独使用虚引用没有太大的意义。虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用关联的引用队列中是否已经包含了该虚引用,从而了解虚引用所引用的对象是否即将被回收 。

下面程序示范了弱引用所引用的对象被系统垃圾回收过程 :

ReferenceTest.java

public class ReferenceTest {

public static void main(String[] args) throws Exception {

//创建一个字符串对象

String str = new String( "疯狂Java讲义 " ) ;

//创建一个弱引用,让此弱引用引用到 " 疯狂 Java 讲义 " 字符串

WeakReference wr = new WeakReference(str) ; //①

//切断 str 引用和 "疯狂 Java 讲义 " 字符串之间的引用

str = null; // ②

//取出弱引用所引用的对象

System.out.println(wr.get()); //③

//强制垃圾回收

System.gc ();

System.runFinalization ();

//再次取出弱引用所引用的对象

System.out.println(wr.get()); //④

}

}

上面程序先创建了 一个"疯狂 Java 讲义"宇符串对象,并让 5位引用变量引用它,执行①行粗体字代码时,系统创建了 一个弱引用对象,并让该对象和 str引用同一个对象 。 当程序执行到②行代码时,程序切断了str和 "疯狂 Java 讲义 "字符串对象之间 的引用关系 。 此时系统内存如图 6.10 所示 。

仅被弱引用引用的字符串对象

在这里插入图片描述

当程序执行到③号代码时 ,由于本程序不会导致内存紧张 ,此时程序通常还不会回收弱引用wr 所引用的对象,因此在③号代码处可以看到输出 "疯狂 Java 讲义"字符串 。执行到③号代码之后,程序调用了 System.gc(); 和 System.runFinalization(); 通知系统进行垃圾回收,如果系统立即进行垃圾回收,那么就会将弱引用 WT 所引用的对象回收 。 接下来在④号字代码处将看到输出 nul l 。

下面程序与上面程序基本相似,只是使用了虚引用来引用字符串对象,虚引用无法获取它引用的对象。下面程序还将虚引用和引用队列结合使用,可以看到被虚引用所引用的对象被垃圾回收后,虚引用将被添加到引用队列中 。

PhantomReferenceTest.java

public class PhantomReferenceTest {

public static void main(String[] args) throws Exception{

//创建一个字符串对象

String str = new String("疯狂 Java 讲义 " ) ;

//创建一个引用队列

ReferenceQueue rq = new ReferenceQueue();

// 创建一个虚引用,让此虚引用引用到"疯狂 Java 讲义"字符串

PhantomReference pr = new PhantomReference (str , rq);

// 切断 str 引用和 " 疯狂 Java 讲义 " 字符串之间的引用

str = null;

// 取出虚 引用所引用的对象,并不能通过虚引用获取被引用的对象,所以此处输出 null

System. out .println(pr . get()) ; // ①

// 强制垃圾回收

System . gc () ;

System . runFinalization();

//垃圾回收之后 ,虚引用将被放入引用队列中

// 取出引用 队列中最先进入队列的引用与 pr 进行比较

System. out.println(rq.poll()==pr); // ②

}

}

因为系统无法通过虚引用来获得被引用的对象,所以执行①处的输出语句时,程序将输出 null (即使此时并未强制进行垃圾回收)。当程序强制垃圾回收后,只有虚引用引用的字符串对象将会被垃圾回收,当被引用的对象被回收后,对应的虚引用将被添加到关联的 引用队列中,因而将在②代码处看到输出 true 。

使用这些引用类可以避免在程序执行期间将对象留在内存中。如果以软引用、弱引用或虚引用的方式引用对象,垃圾回收器就能够随意地释放对象 。如果希望尽可能减小程序在其生命周期中所占用的内存大小时,这些引用类就很有用处。

必须指出:要使用这些特殊的引用类,就不能保留对对象的强引用:如果保留了对对象的强引用,就会浪费这些引用类所提供的任何好处 。

由于垃圾回收的不确定性,当程序希望从软、弱引用中取出被引用对象时,可能这个被引用对象己经被释放了。如果程序需要使用那个被引用的对象,则必须重新创建该对象 。 这个过程可以采用两种方式完成,下面代码显示了其中一种方式。

总结

一般像这样的大企业都有好几轮面试,所以自己一定要花点时间去收集整理一下公司的背景,公司的企业文化,俗话说「知己知彼百战不殆」,不要盲目的去面试,还有很多人关心怎么去跟HR谈薪资。

这边给大家一个建议,如果你的理想薪资是30K,你完全可以跟HR谈33~35K,而不是一下子就把自己的底牌暴露了出来,不过肯定不能说的这么直接,比如原来你的公司是25K,你可以跟HR讲原来的薪资是多少,你们这边能给到我的是多少?你说我这边希望可以有一个20%涨薪。

最后再说几句关于招聘平台的,总之,简历投递给公司之前,请确认下这家公司到底咋样,先去百度了解下,别被坑了,每个平台都有一些居心不良的广告党等着你上钩,千万别上当!!!

Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
,每个平台都有一些居心不良的广告党等着你上钩,千万别上当!!!

Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书。
[外链图片转存中…(img-9w3SRNOk-1713477178418)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-zcxgTV6n-1713477178419)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 8
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值