Java对象实习

Java将出现在源代码中的字符串竞争者存储在池中。 换句话说,当您有如下代码时:

String a = "I am a string";
String b = "I am a string";

变量ab将具有相同的值。 不只是两个相等的字符串,而是完全相同的字符串。 用Java单词a == b是正确的。 但是,这仅适用于字符串以及较小的整数和长值。 其他对象不会被插入,因此,如果您创建两个具有完全相同值的对象,它们通常是不相同的。 它们可能并且可能相等,但对象不同。 有时候这可能很麻烦。 可能是当您从某个持久性存储中获取某个对象时。 如果您碰巧多次获取同一对象,则可能希望获取同一对象而不是两个副本。 换句话说,我也可以说您只希望在持久性中的单个对象的内存中拥有一个副本。 一些持久层可以为您完成此任务。 例如,JPA实现遵循此模式。 在其他情况下,您可能需要自己执行缓存。

在这个示例中,我将描述一个简单的内部池实现,也可以在stackoverflow主题上进行查看。 在本文中,我还将解释导致此处(以及此处)描述的解决方案的细节和注意事项。 本文包含的矿石信息比原始讨论要多。

对象池

实习需要一个对象池。 当您有一个对象并且想要实习该对象时,您实际上是在对象池中查看以查看是否已经有一个对象等于手头的对象。 如果有一个,我们将使用已经存在的一个。 如果没有对象等于实际对象,则将实际对象放入池中,然后使用该对象。

在实施过程中,我们必须面对两个主要问题:

  • 垃圾收集
  • 多线程环境

如果不再需要某个对象,则必须将其从池中删除。 删除可以由应用程序完成,但这将是完全过时且古老的方法。 Java优于C ++的主要优势之一是垃圾回收。 我们可以让GC收集这些对象。 为此,我们不应该在对象池中强烈引用池中的对象。

参考

如果您知道什么是软引用,弱引用和幻像引用,请跳至下一部分。

您可能会注意到,我并不是简单地说“参考”,而是说“强参考”。 如果您了解到在没有对对象的引用时GC会收集对象,则它不是绝对正确的。 事实上,这是GC处理不可触摸对象所需的强大参考。 为了更精确,强引用应该可以与其他强引用一起从局部变量,静态字段和类似的普遍位置传播。 换句话说:(强)引用从一个死亡对象指向另一个死亡对象的点不计算在内,它们将一起被删除并收集。

因此,如果这些都是强引用,那么您可能不会想到这么强的引用。 你是对的。 有一个名为java.lang.ref.Reference的类,还有另外三个扩展它的类。 这些类是:

  1. PhantomReference
  2. WeakReference
  3. SoftReference

在同一包中。 如果阅读文档,您可能会怀疑我们所需要的只是薄弱的一环。 幻影在池中使用毫无疑问,因为幻影引用不能用于访问对象。 软引用太过分了。 如果没有对该对象的强引用,那么将其保留在池中就没有意义。 如果它再次来自某个来源,我们将再次实习。 这肯定是一个不同的实例,但是没有人注意到它,因为没有引用前一个实例。

弱引用是可以用于访问对象但不会改变GC行为的引用。

WeakHashMap

弱引用不是我们必须直接使用的类。 有一个名为WeakHashMap的类,该类使用软引用来引用关键对象。 这实际上是我们所需要的。 当我们实习一个对象并想查看它是否已经在池中时,我们搜索所有对象以查看是否有任何对象等于实际对象。 地图就是实现此搜索功能的东西。 在弱引用中持有密钥只会让GC在没人需要时收集密钥对象。

到目前为止我们可以搜索,这很好。 使用地图,我们还必须获得一些价值。 在这种情况下,我们只想获取相同的对象,因此必须在不存在该对象的情况下将其放入地图中。 但是,将对象本身放置在那里会破坏我们获得的结果,即我们仅保留对同一对象的弱引用作为键。 我们必须创建并弱引用该对象作为键。

弱水池

在那之后的解释是代码。 它只是说如果有一个对象等于实际对象,那么get(actualObject)应该返回它。 如果没有,则get(actualObject)将返回null。 方法put(newObject)将一个新对象放入池中,如果有一个等于新对象的对象,它将用新对象覆盖旧对象的位置。

public class WeakPool<T> {private final WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();public T get(T object){final T res;WeakReference<T> ref = pool.get(object);if (ref != null) {res = ref.get();}else{res = null;}return res;}public void put(T object){pool.put(object, new WeakReference<T>(object));}
}

实习生池

解决该问题的最终方法是一个内部池,该池很容易使用已有的WeakPool来实现。 InternPool内部有一个弱池,并且intern(T object)只有一个同步方法。

public class InternPool<T> {private final WeakPool<T> pool = new WeakPool<T>();public synchronized T intern(T object) {T res = pool.get(object);if (res == null) {pool.put(object);res = object;}return res;}
}

该方法尝试从池中获取对象,如果该对象不存在,则将其放在那里,然后将其返回。 如果已经有一个匹配的对象,那么它将返回池中已经存在的对象。

多线程

该方法必须同步以确保新对象的检查和插入是原子的。 如果没有同步,则可能发生两个线程检查池中两个相等的实例,两个线程都发现其中没有匹配的对象,然后将其版本插入池中。 其中一个,后来放置其对象的对象将是赢家,它会覆盖已存在的对象,但较宽松的人也认为它拥有真正的单个对象。 同步解决了这个问题。

与垃圾收集器赛车

即使使用该池的java应用程序的不同线程不会在同时使用该池时遇到麻烦,但是如果对垃圾收集器线程有任何干扰,我们仍然应该查看它。

调用弱引用get方法时,引用可能返回null。 当垃圾回收器回收了关键对象,但是弱轮询实现中的弱哈希映射仍然没有删除条目时,就会发生这种情况。 即使弱映射实现每次查询映射时都检查密钥的存在,它也可能发生。 垃圾收集器可以在通话之间踢get()弱哈希映射,并号召get()来返回的弱引用。 哈希映射返回对对象的引用,该对象在返回时就已经存在,但是由于该引用是弱引用,因此将其删除,直到我们的Java应用程序执行到下一条语句为止。

在这种情况下, WeakPool实现将返回null。 没问题。 InternPool也不InternPool困扰。

如果查看前面提到的stackoverflow主题中的其他代码,则可以看到一个代码:

public class InternPool<T> {private WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();public synchronized T intern(T object) {T res = null;// (The loop is needed to deal with race// conditions where the GC runs while we are// accessing the 'pool' map or the 'ref' object.)do {WeakReference<T> ref = pool.get(object);if (ref == null) {ref = new WeakReference<T>(object);pool.put(object, ref);res = object;} else {res = ref.get();}} while (res == null);return res;}
}

在此代码中,作者创建了一个无限循环来处理这种情况。 不太吸引人,但是有效。 该循环不可能无限期地执行。 可能不超过两次。 构造很难理解,很复杂。 士气:单一责任原则。 专注于简单的事情,将您的应用程序分解为简单的组件。

结论

即使Java仅对String进行实习,并且某些装箱原始类型的对象也可能进行实习,有时也希望进行实习。 在这种情况下,实习不是自动的,应用程序必须明确执行它。 通过将复制粘贴粘贴到代码库中,可以使用此处列出的两个简单类来实现此目的,或者可以:

<dependency><groupId>com.javax0</groupId><artifactId>intern</artifactId><version>1.0.0</version>
</dependency>

从Maven中央插件导入库作为依赖项。 该库是最小的,仅包含这两个类,可在Apache许可下使用。 该库的源代码在GitHub上 。

参考: Java Deep博客上来自我们JCG合作伙伴 Peter Verhas的Java Object Interning。

翻译自: https://www.javacodegeeks.com/2014/03/java-object-interning.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GT sport赛道详解 - Dragon Trail | 龙之径

参考&#xff1a;GT sport所有赛道简介 今天的心情变化挺大&#xff0c;从绝望放弃到豁然开朗。 前言&#xff1a;GT sport有个排位赛&#xff0c;是每位sim赛车手提升自己等级的唯一途径&#xff0c;其中一个排位赛就是龙之径II&#xff08;逆时针跑&#xff09;&#xff0c;我…

优秀网页设计:带给你灵感的联系页面设计

在设计网站的时候&#xff0c;我们需要考虑到各个方面&#xff0c;从页眉到脚&#xff0c;从着陆页&#xff08;landing page&#xff09;到关于页&#xff08;about us page&#xff09;&#xff0c;还有联系页面&#xff08;contact page&#xff09;都要考虑。联系页面是网站…

LeetCode 494. Target Sum

作为一个超级小白&#xff0c;最近开始寻找互联网公司的就业机会&#xff0c;可是无奈代码关难过。于是最近开始刷LeetCode上的习题。 这道题其实可以转换为典型的动态规划01背包问题。它的描述如下&#xff1a; You are given a list of non-negative integers, a1, a2, ..., …

前端项目难点及解决方法_预埋件施工重点难点的解决方法

点击箭头处“蓝色字”&#xff0c;关注我们哦&#xff01;&#xff01;关于施工重难点的问题&#xff0c;可根据主体结构施工情况&#xff0c;想从根本上解决几大重难点&#xff0c;必须严格按照设计图纸及规范要求放线定位&#xff0c;将预埋件施工精度控制合格率&#xff0c;…

小学计算机课5年级第一课,人教版(2015)小学信息技术 五年级下册 第1课 录制声音真轻松 教案...

人教版(2015)小学信息技术 五年级下册 第1课 录制声音真轻松 教案第1课录制声音真轻松教学目标知识与技能:1、了解Audacity软件的界面。2、能够掌握声音录制和编辑的方法。3、了解声音文件的基本格式及转换方法。过程与方法:? ? ? ?兴趣是最好的老师,是最强大的动力,本节课…

MySQL 基础语句

1 USE qy97;/*使用数据库*/2 CREATE TABLE book (bid INT PRIMARY KEY AUTO_INCREMENT,bname VARCHAR(50),price DOUBLE);/*创建表格*/3 DESC book;/*查看表格的格式*/4 ALTER TABLE book MODIFY price INT;/*修改列的类型 MODIFY*/5 ALTER TABLE book CHANGE bname bnames V…

视差滚动(Parallax Scrolling)技术在网页中应用的精美案例

视差滚动&#xff08;Parallax Scrolling&#xff09;是一种独特的网页内容表现形式&#xff0c;其基本原理是让多层背景以不同的速度移动&#xff0c;形成立体的运动效果&#xff0c;带来出色的视觉体验。作为今年网页设计的热点趋势&#xff0c;越来越多的网站应用了这项技术…

用Java可外部化

在理解Externalizable接口之前&#xff0c;您需要了解序列化。您可以在java中的序列化上阅读有关序列化的更多信息。 Java提供一种称为序列化的机制&#xff0c;以按字节顺序或字节顺序持久化Java对象&#xff0c;其中包括对象的数据以及有关对象的类型和存储在对象中的数据类…

批量删除html网页,批量删除.html · panghuamama/Clearly Local - Gitee.com

&#xfeff;批量删除$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.html; };…

apache camel 相关配置_使用apache camel从表中选择数据-问答-阿里云开发者社区-阿里云...

我希望能够使用Camel连续轮询数据库以从表中选择数据。我已经在我的Spring Boot应用程序中配置了Camel。这是我正在使用的配置build.gradle&#xff1a;implementation org.apache.camel:camel-jdbc-starter:2.24.0implementation org.apache.camel:camel-sql-starter:2.24.0Ro…

一些喜欢的诗词句子

原文链接&#xff1a;一些喜欢的诗词句子其一一些喜欢的诗词句子其二 清纳兰性德《酒泉子谢却荼蘼》 谢却荼蘼&#xff0c;一片月明如水。 篆香消&#xff0c;犹未睡&#xff0c;早鸦啼。 嫩寒无赖罗衣薄&#xff0c;休傍阑干角。 最愁人&#xff0c;灯欲落&#xff0c;燕还飞。…

[Swift]LeetCode1020. 飞地的数量 | Number of Enclaves

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号&#xff1a;山青咏芝&#xff08;shanqingyongzhi&#xff09;➤博客园地址&#xff1a;山青咏芝&#xff08;https://www.cnblogs.com/strengthen/&#xff09;➤GitHub地址&a…

推荐30个新鲜出炉的精美 jQuery 效果

jQuery 是最流行和使用最广泛的 JavaScript 框架&#xff0c;它简化了HTML文档遍历&#xff0c;事件处理&#xff0c;动画以及Ajax交互&#xff0c;帮助Web开发人员更快速的实现各种精美的界面效果。jQuery 的易扩展性吸引了来自全球的开发者来共同编写 jQuery 插件&#xff0c…

Java常见陷阱

总览 Java是一种极简主义的语言&#xff0c;具有比其他语言故意更少的功能&#xff0c;尽管如此&#xff0c;Java仍然具有产生奇怪效果的边缘情况&#xff0c;甚至具有令人惊讶的效果的一些常见情况也会使您轻而易举。 如果您习惯于阅读另一种语言&#xff0c;则可以轻松地以错…

python高阶函数介绍_python高级特性和高阶函数及使用详解

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里技术人对外发布原创技术内容的最大平台&…

会计专业计算机技能大赛,会计技能大赛策划

会计技能大赛策划一&#xff0e;活动背景会计是一个基于理论和实践相结合的学科&#xff0c;对于经管学院&#xff0c;会计专业是一个新创建的专业&#xff0c;缺少相应的会计实践。作为会计专业的学生&#xff0c;在不断学习理论的同时&#xff0c;我们更应该加强实践操作能力…

MySQL中查询获取每个班级成绩前三名的学生信息

CREATE TABLE t_testscore( pk_id INT PRIMARY KEY, c_name VARCHAR(50) , c_score INT, c_class INT )DEFAULT CHARSETutf8;INSERT INTO t_testscore VALUES (1, 张三6, 66, 1),(2, 张三5, 65, 1),(3, 张三4, 64, 1), (4, 张三3, 63, 1),(5, 张三2, 62, 1);INSERT…

vue自定义指令clickoutside扩展--多个元素的并集作为inside

都是个人理解&#xff0c;如果发现错误&#xff0c;恳请大家批评指正&#xff0c;谢谢。还有我说的会比较啰嗦&#xff0c;因为是以自身菜鸡水平的视角来记录学习理解的过程&#xff0c;见谅。 1.前言 产品使用vueelement作为前端框架。在功能开发过程中&#xff0c;难免遇到使…

35个让人惊讶的 CSS3 动画效果演示

本文收集了35个惊人的 CSS3 动画演示&#xff0c;它们将证明 CSS3 Transform 和 Transition 属性的强大能力。CSS 是网页设计非常重要的一部分&#xff0c;随着越来越多的浏览器对 CSS3 支持的不断完善&#xff0c;设计师和开发者们有了更多的选择。如今&#xff0c;用纯 CSS 就…

可选类型API

Java 8引入了Optional类。 简而言之&#xff0c;不是返回null&#xff0c;而是检查null&#xff0c;而是返回Optional实例&#xff0c;该实例可以设置或不设置值。 这样&#xff0c;您就不会因NullPointerException而失败。 我不会讨论Optional类型是否会完全消除NPE&#xff…