在上一篇文章中,小编为您详细介绍了关于《android app自动化测试工具有哪些?Android 手机自动化测试工具有哪几种》相关知识。本篇中小编将再为您讲解标题Java中的强引用软引用?Java对象的初始化顺序。
java有④种引用
对于Java中的垃圾回收机制来说,对象是否被回收的标准在于该对象是否被引用。因此,引用也是JVM进行内存管理的①个重要概念。众所周知,java中是JVM负责内存的分配和回收,这是它的优点(使用方便,程序不用再像使用c那样担心内存),但同时也是它的缺点(不够灵活)。为了解决内存操作不灵活这个问题,可以采用软引用等方法。
在JDK①.②以前的版本中,当①个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及状态,程序才能使用它。这就像在日常生活中,从商店购买了某样物品后,如果有用,就①直保留它,否则就把它扔到垃圾箱,由清洁工人收走。①般说来,如果物品已经被扔到垃圾箱,想再 把它捡回来使用就不可能了。
但有时候情况并不这么简单,你可能会遇到类似鸡肋①样的物品,食之无味,弃之可惜。这种物品现在已经无用了,保留它会占空间,但是立刻扔掉它也不划算,因为也许将来还会派用场。对于这样的可有可无的物品,①种折衷的处理办法是:如果家里空间足够,就先把它保留在家里,如果家里空间不够,即使把家里所有的垃圾清除,还是无法容纳那些必不可少的生活用品,那么再扔掉这些可有可无的物品。
从JDK①.②版本开始,把对象的引用分为④种级别,从而使程序能更加灵活的控制对象的生命周期。这④种级别由高到低依次为:强引用、软引用、弱引用和虚引用。
①.强引用
以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果①个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空 间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
②.软引用(SoftReference)
如果①个对象只具有软引用,那就类似于可有可物的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。
软引用可以和①个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,JAVA虚拟机就会把这个软引用加入到与之关联的引用队列中。
③.弱引用(WeakReference)
如果①个对象只具有弱引用,那就类似于可有可物的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它 所管辖的内存区域的过程中,①旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是①个优先级很低的线程, 因此不①定会很快发现那些只具有弱引用的对象。
弱引用可以和①个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
④.虚引用(PhantomReference)
\"虚引用\"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果①个对象仅持有虚引用,那么它就和没有任何引用①样,在任何时候都可能被垃圾回收。
虚引用主要用来跟踪对象被垃圾回收的活动。虚引用与软引用和弱引用的①个区别在于:虚引用必须和引用队列(ReferenceQueue)联合使用。当垃 圾回收器准备回收①个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是 否已经加入了虚引用,来了解
被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。
特别注意,在世纪程序设计中①般很少使用弱引用与虚引用,使用软用的情况较多,这是因为软引用可以加速JVM对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生。
以下是软引用的代码:
import java.lang.ref.SoftReference; public class Test { public static void main(String[] args){ System.out.println(\"开始\"); A a = new A(); SoftReference sr = new SoftReference(a); a = null; if(sr!=null){ a = sr.get(); } else{ a = new A(); sr = new SoftReference(a); } System.out.println(\"结束\"); } } class A{ int[] a ; public A(){ a = new int[①⓪⓪⓪⓪⓪⓪⓪⓪]; } }
看这个例子就清楚了。记得收藏起来,忘记了可以拿出来看看。
例子里总共测试了静态代码块,普通代码块,静态成员变量,普通成员 变量,构造器。分别在基类和派生类里各有①套。
例子里每部分开头的数字,由大到小代表实际执行顺序。
/** * 控制台打印 */class Log{ public static String baseFieldInit(){System.out.println(\"Base Normal Field\");return \"\";} public static String baseStaticFieldInit(){System.out.println(\"Base Static Field\");return \"\";} public static String fieldInit(){System.out.println(\"Normal Field\");return \"\";} public static String staticFieldInit(){System.out.println(\"Static Field\");return \"\";}}/** *基类 */class Base { /*①*/ static {System.out.println(\"Base Static Block ①\");} /*①*/ private static String staticValue=Log.baseStaticFieldInit(); /*①*/ static {System.out.println(\"Base Static Block ②\");} /*③*/ {System.out.println(\"Base Normal Block ①\");} /*③*/ private String value=Log.baseFieldInit(); /*③*/ {System.out.println(\"Base Normal Block ②\");} /*④*/ Base(){System.out.println(\"Base Constructor\");}}/** *派生类 */public class Derived extends Base{ /*②*/ static {System.out.println(\"Static Block ①\");} /*②*/ private static String staticValue=Log.staticFieldInit(); /*②*/ static {System.out.println(\"Static Block ②\");} /*⑤*/ {System.out.println(\"Normal Block ①\");} /*⑤*/ private String value=Log.fieldInit(); /*⑤*/ {System.out.println(\"Normal Block ②\");} /*⑥*/ Derived(){System.out.println(\"Derived Constructor\");} /** * MAIN 主线程 */ public static void main(String[] args){ Derived d=new Derived(); }}
实验输出结果:
Base Static Block ①Base Static FieldBase Static Block ②Static Block ①Static FieldStatic Block ②Base Normal Block ①Base Normal FieldBase Normal Block ②Base ConstructorNormal Block ①Normal FieldNormal Block ②Derived Constructor
结果证明:
对象在class文件加载完毕,以及为各成员在方法区开辟好内存空间之后,就开始所谓“初始化”的步骤:
①. 基类静态代码块,基类静态成员字段 (并列优先级,按代码中出现先后顺序执行)(只有第①次加载类时执行)
②. 派生类静态代码块,派生类静态成员字段 (并列优先级,按代码中出现先后顺序执行)(只有第①次加载类时执行)
③. 基类普通代码块,基类普通成员字段 (并列优先级,按代码中出现先后顺序执行)
④. 基类构造函数
⑤. 派生类普通代码块,派生类普通成员字段 (并列优先级,按代码中出现先后顺序执行)
⑥. 派生类构造函数
注意,第① · ②步的静态过程,只在这个类第①次被加载的时候才运行。如果创建两个对象,
Derived d①=new Derived();Derived d②=new Derived();第②次创建d②就只执行③ · ④ · ⑤ · ⑥步。\", \"extras\": \"\", \"created_time\": ①④⑦⓪②⓪①⑧⑥⑨ · \"type\": \"answer
编后语:关于《Java中的强引用软引用?Java对象的初始化顺序》关于知识就介绍到这里,希望本站内容能让您有所收获,如有疑问可跟帖留言,值班小编第一时间回复。 下一篇内容是有关《就我一个发现图是一加手机么?魅族Pro 6 Plus和一加3T谁好》,感兴趣的同学可以点击进去看看。
小鹿湾阅读 惠尔仕健康伙伴 阿淘券 南湖人大 铛铛赚 惠加油卡 oppo通 萤石互联 588qp棋牌官网版 兔牙棋牌3最新版 领跑娱乐棋牌官方版 A6娱乐 唯一棋牌官方版 679棋牌 588qp棋牌旧版本 燕晋麻将 蓝月娱乐棋牌官方版 889棋牌官方版 口袋棋牌2933 虎牙棋牌官网版 太阳棋牌旧版 291娱乐棋牌官网版 济南震东棋牌最新版 盛世棋牌娱乐棋牌 虎牙棋牌手机版 889棋牌4.0版本 88棋牌最新官网版 88棋牌2021最新版 291娱乐棋牌最新版 济南震东棋牌 济南震东棋牌正版官方版 济南震东棋牌旧版本 291娱乐棋牌官方版 口袋棋牌8399 口袋棋牌2020官网版 迷鹿棋牌老版本 东晓小学教师端 大悦盆底 CN酵素网 雀雀计步器 好工网劳务版 AR指南针 布朗新风系统 乐百家工具 moru相机 走考网校 天天省钱喵 体育指导员 易工店铺 影文艺 语音文字转换器