当前位置: 首页 > news >正文

做商城网站产品怎么分布企业品牌网站建设怎么做

做商城网站产品怎么分布,企业品牌网站建设怎么做,湖北联诺建设网站,做捐款网站这是我的第 200 期分享作者 | 王磊来源 | Java中文社群#xff08;ID#xff1a;javacn666#xff09;转载请联系授权#xff08;微信ID#xff1a;GG_Stone#xff09;生活中的尴尬无处不在#xff0c;有时候你只是想简单的装一把#xff0c;但某些“老同志”总是在不… 这是我的第 200 期分享作者 | 王磊来源 | Java中文社群IDjavacn666转载请联系授权微信IDGG_Stone生活中的尴尬无处不在有时候你只是想简单的装一把但某些“老同志”总是在不经意之间给你无情的一脚踹得你简直无法呼吸。但谁让咱年轻呢吃亏要趁早前路会更好。喝了这口温热的鸡汤咱们来聊聊是怎么回事。事情是这样的在一个不大不小的项目中小王写下了这段代码MapString, String map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3); }}; map.forEach((k, v) - {System.out.println(key:  k   value:  v); }); 本来是用它来替代下面这段代码的MapString, String map  new HashMap(); map.put(map1, value1); map.put(map2, value2); map.put(map3, value3); map.forEach((k, v) - {System.out.println(key:  k   value:  v); }); 两块代码的执行结果也是完全一样的key:map3 value:value3key:map2 value:value2key:map1 value:value1所以小王正在得意的把这段代码介绍给部门新来的妹子小甜甜看却不巧被正在经过的老张也看到了。老张本来只是想给昨天的枸杞再续上一杯 85° 的热水但说来也巧刚好撞到了一次能在小甜甜面前秀技术的一波机会于是习惯性的整理了一下自己稀疏的秀发便开启了 diss 模式。“小王啊你这个代码问题很大啊”“怎么能用双花括号初始化实例呢”此时的小王被问的一脸懵逼内心有无数个草泥马奔腾而过心想你这头老牛竟然也和我争这颗嫩草但内心却有一种不祥的预感感觉自己要输瞬间羞涩的不知该说啥只能红着小脸轻轻的“嗯”了一声。老张“使用双花括号初始化实例是会导致内存溢出的啦侬不晓得嘛”小王沉默了片刻只是凭借着以往的经验来看这“老家伙”还是有点东西的于是敷衍的“哦~”了一声仿佛自己明白了怎么回事一样其实内心仍然迷茫的一匹为了不让其他同事发现只得这般作态。于是片刻的敷衍待老张离去之后才悄悄的打开了 Google默默的搜索了一下。小王哦原来如此......双花括号初始化分析 首先我们来看使用双花括号初始化的本质是什么以我们这段代码为例MapString, String map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3); }}; 这段代码其实是创建了匿名内部类然后再进行初始化代码块。这一点我们可以使用命令 javac 将代码编译成字节码之后发现我们发现之前的一个类被编译成两个字节码.class文件如下图所示我们使用 Idea 打开 DoubleBracket$1.class 文件发现import java.util.HashMap;class DoubleBracket$1 extends HashMap {DoubleBracket$1(DoubleBracket var1) {this.this$0  var1;this.put(map1, value1);this.put(map2, value2);} } 此时我们可以确认它就是一个匿名内部类。那么问题来了匿名内部类为什么会导致内存溢出呢匿名内部类的“锅” 在 Java 语言中非静态内部类会持有外部类的引用从而导致 GC 无法回收这部分代码的引用以至于造成内存溢出。思考 1为什么要持有外部类这个就要从匿名内部类的设计说起了在 Java 语言中非静态匿名内部类的主要作用有两个。1、当匿名内部类只在外部类主类中使用时匿名内部类可以让外部不知道它的存在从而减少了代码的维护工作。2、当匿名内部类持有外部类时它就可以直接使用外部类中的变量了这样可以很方便的完成调用如下代码所示public class DoubleBracket {private static String userName  磊哥;public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {MapString, String map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3);put(userName, userName);}};} } 从上述代码可以看出在 HashMap 的方法内部可以直接使用外部类的变量 userName。思考 2它是怎么持有外部类的关于匿名内部类是如何持久外部对象的我们可以通过查看匿名内部类的字节码得知我们使用 javap -c DoubleBracket\$1.class 命令进行查看其中 $1 为以匿名类的字节码字节码的内容如下javap -c DoubleBracket\$1.class Compiled from DoubleBracket.java class com.example.DoubleBracket$1 extends java.util.HashMap {final com.example.DoubleBracket this$0;com.example.DoubleBracket$1(com.example.DoubleBracket);Code:0: aload_01: aload_12: putfield      #1                  // Field this$0:Lcom/example/DoubleBracket;5: aload_06: invokespecial #7                  // Method java/util/HashMap.init:()V9: aload_010: ldc           #13                 // String map112: ldc           #15                 // String value114: invokevirtual #17                 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;17: pop18: aload_019: ldc           #21                 // String map221: ldc           #23                 // String value223: invokevirtual #17                 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;26: pop27: return } 其中关键代码的在 putfield 这一行此行表示有一个对 DoubleBracket 的引用被存入到 this$0 中也就是说这个匿名内部类持有了外部类的引用。如果您觉得以上字节码不够直观没关系我们用下面的实际的代码来证明一下import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map;public class DoubleBracket {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {Map map  new DoubleBracket().createMap();// 获取一个类的所有字段Field field  map.getClass().getDeclaredField(this$0);// 设置允许方法私有的 private 修饰的变量field.setAccessible(true);System.out.println(field.get(map).getClass());}public Map createMap() {// 双花括号初始化Map map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3);}};return map;} } 当我们开启调试模式时可以看出 map 中持有了外部对象 DoubleBracket如下图所示以上代码的执行结果为class com.example.DoubleBracket从以上程序输出结果可以看出匿名内部类持有了外部类的引用因此我们才可以使用 $0 正常获取到外部类并输出相关的类信息。什么情况会导致内存泄漏 当我们把以下正常的代码public void createMap() {Map map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3);}};// 业务处理.... } 改为下面这个样子时可能会造成内存泄漏public Map createMap() {Map map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3);}};return map; } 为什么用了「可能」而不是「一定」会造成内存泄漏这是因为当此 map 被赋值为其他类属性时可能会导致 GC 收集时不清理此对象这时候才会导致内存泄漏。可以关注我「Java中文社群」后面会专门写一篇关于此问题的文章。如何保证内存不泄露 要想保证双花扣号不泄漏办法也很简单只需要将 map 对象声明为 static 静态类型的就可以了代码如下public static Map createMap() {Map map  new HashMap() {{put(map1, value1);put(map2, value2);put(map3, value3);}};return map; } 什么你不相信没关系我们用事实说话使用以上代码我们重新编译一份字节码查看匿名类的内容如下javap -c  DoubleBracket\$1.class Compiled from DoubleBracket.java class com.example.DoubleBracket$1 extends java.util.HashMap {com.example.DoubleBracket$1();Code:0: aload_01: invokespecial #1                  // Method java/util/HashMap.init:()V4: aload_05: ldc           #7                  // String map17: ldc           #9                  // String value19: invokevirtual #11                 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;12: pop13: aload_014: ldc           #17                 // String map216: ldc           #19                 // String value218: invokevirtual #11                 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;21: pop22: aload_023: ldc           #21                 // String map325: ldc           #23                 // String value327: invokevirtual #11                 // Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;30: pop31: return } 从这次的代码我们可以看出已经没有 putfield 关键字这一行了也就是说静态匿名类不会持有外部对象的引用了。为什么静态内部类不会持有外部类的引用原因其实很简单因为匿名内部类是静态的之后它所引用的对象或属性也必须是静态的了因此就可以直接从 JVM 的 Method Area方法区获取到引用而无需持久外部对象了。双花括号的替代方案 即使声明为静态的变量可以避免内存泄漏但依旧不建议这样使用为什么呢原因很简单项目一般都是需要团队协作的假如那位老兄在不知情的情况下把你的 static 给删掉呢这就相当于设置了一个隐形的“坑”其他不知道的人一不小心就跳进去了所以我们可以尝试一些其他的方案比如 Java8 中的 Stream API 和 Java9 中的集合工厂等。替代方案 1Stream使用 Java8 中的 Stream API 替代示例如下。原代码ListString list  new ArrayList() {{add(Java);add(Redis); }}; 替代代码ListString list  Stream.of(Java, Redis).collect(Collectors.toList()); 替代方案 2集合工厂使用集合工厂的 of 方法替代示例如下。原代码Map map  new HashMap() {{put(map1, value1);put(map2, value2); }}; 替代代码Map map  Map.of(map1, Java, map2, Redis); 显然使用 Java9 中的方案非常适合我们简单又酷炫只可惜我们还在用 Java 6...6...6... 心碎了一地。总结 本文我们讲了双花括号初始化因为会持有外部类的引用从而可以会导致内存泄漏的问题还从字节码以及反射的层面演示了这个问题。要想保证双花括号初始化不会出现内存泄漏的办法也很简单只需要被 static 修饰即可但这样做还是存在潜在的风险可能会被某人不小心删除掉于是我们另寻它道发现了可以使用 Java8 中的 Stream 或 Java9 中的集合工厂 of 方法替代“{{”。最后的话看在我努力编故事的份上点个「在看」再走呗参考 鸣谢https://www.ripjava.com/article/1291630596325408https://cloud.tencent.com/developer/article/1179625https://hacpai.com/article/1498563483898往期推荐 if快还是switch快解密switch背后的秘密HashMap 的 7 种遍历方式与性能分析「修正篇」关注公众号发送”进群“磊哥拉你进读者群。
http://www.pierceye.com/news/113781/

相关文章:

  • 门户网站建设汇报如果在网上接网站建设项目
  • 网站开发文档是什么概念注册个体户
  • 双井做网站的公司app开发和网站开发价格
  • 电梯企业网站制作中山网站建设电话
  • 做网站推广哪些跨境电商平台企业
  • 域名注册网站推荐方案模板
  • 亚运村网站建设北京工商注册官网
  • sql2005做网站书店网站建设人员分配
  • 工商局网站怎么做股东实名认证石家庄网站建设公司怎么样
  • 做公众号的模版的网站国内网站做国外服务器
  • 做国际网站的上海高端网站公司wordpress 4.9.6 下载
  • 学校集约网站建设最牛餐饮营销手段
  • wordpress影视站网站太花哨
  • 青岛 机械 中企动力提供网站建设小说网站怎么做空间小
  • 通江县网站建设做网站到八方资源网怎么样
  • 国家网站建设ssh架构jsp网站开发
  • 浦东新区手机网站设计网络营销做得好的产品
  • 浙江市建设网站市场监督管理局电话举报电话
  • 企业网站的建设的功能定位菏泽百度推广公司电话
  • linux系统怎么做网站女生去住建局好不好
  • 自己搭建环境建设网站网站开发温州
  • 下沙做网站软件erp系统的主要功能
  • 郑州网站建设专家最新手机排行榜2021
  • 宠物店网站建设策划书重庆网站建设 红旗河沟
  • 一般网站自己可以做播放器吗最简单的一个网站开发
  • 网站的开发商务网站安全方案设计
  • 如何建立网站教材漳诈网站建设
  • 开家网站设计公司广州网站建设app开发
  • 建站服务公司网站源码成都游戏外包公司排名
  • 呼伦贝尔网站建设呼伦贝尔astro wordpress