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

网线水晶头接法图解东莞seo网络营销

网线水晶头接法图解,东莞seo网络营销,开发第一个app应用程序,微信公众号平台入口官网如何证明 new String 创建了 N 个对象#xff1f; 我想所有 Java 程序员都曾被这个 new String 的问题困扰过#xff0c;这是一道高频的 Java 面试题#xff0c;但可惜的是网上众说纷纭#xff0c;竟然找不到标准的答案。有人说创建了 1 个对象#xff0c;也有人说创建了…如何证明 new String 创建了 N 个对象 我想所有 Java 程序员都曾被这个 new String 的问题困扰过这是一道高频的 Java 面试题但可惜的是网上众说纷纭竟然找不到标准的答案。有人说创建了 1 个对象也有人说创建了 2 个对象还有人说可能创建了 1 个或 2 个对象但谁都没有拿出干掉对方的证据这就让我们这帮吃瓜群众们陷入了两难之中不知道到底该信谁得。 但是今天老王就斗胆和大家聊聊这个话题顺便再拿出点证据。 以目前的情况来看关于 new String(xxx) 创建对象个数的答案有 3 种 有人说创建了 1 个对象有人说创建了 2 个对象有人说创建了 1 个或 2 个对象。 而出现多个答案的关键争议点在「字符串常量池」上有的说 new 字符串的方式会在常量池创建一个字符串对象有人说 new 字符串的时候并不会去字符串常量池创建对象而是在调用 intern() 方法时才会去字符串常量池检测并创建字符串。 那我们就先来说说这个「字符串常量池」。 字符串常量池 字符串的分配和其他的对象分配一样需要耗费高昂的时间和空间为代价如果需要大量频繁的创建字符串会极大程度地影响程序的性能因此 JVM 为了提高性能和减少内存开销引入了字符串常量池Constant Pool Table的概念。 字符串常量池相当于给字符串开辟一个常量池空间类似于缓存区对于直接赋值的字符串String s“xxx”来说在每次创建字符串时优先使用已经存在字符串常量池的字符串如果字符串常量池没有相关的字符串会先在字符串常量池中创建该字符串然后将引用地址返回变量如下图所示 ![字符串常量池示意图.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvOTI3OTEvMTU4NzAzNzc4ODY5NC00YThhMWE1Zi03YWNhLTQ1ZDAtYjQyYS0wODRlODA5YTQ3ZmYucG5n?x-oss-processimage/format,png#alignleftdisplayinlineheight301margin[object Object]name字符串常量池示意图.pngoriginHeight301originWidth464size23923statusdonestylenonewidth464) 以上说法可以通过如下代码进行证明 public class StringExample {public static void main(String[] args) {String s1 Java;String s2 Java;System.out.println(s1 s2);} }以上程序的执行结果为true说明变量 s1 和变量 s2 指向的是同一个地址。 在这里我们顺便说一下字符串常量池的再不同 JDK 版本的变化。 常量池的内存布局 从JDK 1.7 之后把永生代换成的元空间把字符串常量池从方法区移到了 Java 堆上。 JDK 1.7 内存布局如下图所示 ![JDK 1.7 内存布局.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvOTI3OTEvMTU4NzAzOTE0NzYzNi1lNzEzZjMwNy0yMTQ2LTQ1OWItOTJmNi1jMDE5OTNhZDMwNmMucG5n?x-oss-processimage/format,png#alignleftdisplayinlineheight311margin[object Object]nameJDK 1.7 内存布局.pngoriginHeight311originWidth631size38867statusdonestylenonewidth631) JDK 1.8 内存布局如下图所示 ![JDK 1.8 内存布局.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvOTI3OTEvMTU4NzAzOTU5Njc5NC1kMDBhNzI1MC0xMTA4LTQ2NzgtYmI1MC0yYWVmNmQwNDAyZmEucG5n?x-oss-processimage/format,png#alignleftdisplayinlineheight464margin[object Object]nameJDK 1.8 内存布局.pngoriginHeight464originWidth538size44373statusdonestylenonewidth538) JDK 1.8 与 JDK 1.7 最大的区别是 JDK 1.8 将永久代取消并设立了元空间。官方给的说明是由于永久代内存经常不够用或发生内存泄露会爆出 java.lang.OutOfMemoryError: PermGen 的异常所以把将永久区废弃而改用元空间了改为了使用本地内存空间官网解释详情http://openjdk.java.net/jeps/122 答案解密 认为 new 方式创建了 1 个对象的人认为new String 只是在堆上创建了一个对象只有在使用 intern() 时才去常量池中查找并创建字符串。 认为 new 方式创建了 2 个对象的人认为new String 会在堆上创建一个对象并且在字符串常量池中也创建一个字符串。 认为 new 方式有可能创建 1 个或 2 个对象的人认为new String 会先去常量池中判断有没有此字符串如果有则只在堆上创建一个字符串并且指向常量池中的字符串如果常量池中没有此字符串则会创建 2 个对象先在常量池中新建此字符串然后把此引用返回给堆上的对象如下图所示 ![new 字符串常量池.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvOTI3OTEvMTU4NzA0MTU3MzcyNy01YjA2ODMzZS01NmYzLTQyZmItYWZiYy0xNzM1ZjQ4ZDZkZmMucG5n?x-oss-processimage/format,png#alignleftdisplayinlineheight321margin[object Object]namenew 字符串常量池.pngoriginHeight321originWidth527size27796statusdonestylenonewidth527) 老王认为正确的答案创建 1 个或者 2 个对象。 技术论证 解铃还须系铃人回到问题的那个争议点上new String 到底会不会在常量池中创建字符呢我们通过反编译下面这段代码就可以得出正确的结论代码如下 public class StringExample {public static void main(String[] args) {String s1 new String(javaer-wang);String s2 wang-javaer;String s3 wang-javaer;} }首先我们使用 javac StringExample.java 编译代码然后我们再使用 javap -v StringExample 查看编译的结果相关信息如下 Classfile /Users/admin/github/blog-example/blog-example/src/main/java/com/example/StringExample.classLast modified 2020年4月16日; size 401 bytesSHA-256 checksum 89833a7365ef2930ac1bc3d7b88dcc5162da4b98996eaac397940d8997c94d8eCompiled from StringExample.java public class com.example.StringExampleminor version: 0major version: 58flags: (0x0021) ACC_PUBLIC, ACC_SUPERthis_class: #16 // com/example/StringExamplesuper_class: #2 // java/lang/Objectinterfaces: 0, fields: 0, methods: 2, attributes: 1 Constant pool:#1 Methodref #2.#3 // java/lang/Object.init:()V#2 Class #4 // java/lang/Object#3 NameAndType #5:#6 // init:()V#4 Utf8 java/lang/Object#5 Utf8 init#6 Utf8 ()V#7 Class #8 // java/lang/String#8 Utf8 java/lang/String#9 String #10 // javaer-wang#10 Utf8 javaer-wang#11 Methodref #7.#12 // java/lang/String.init:(Ljava/lang/String;)V#12 NameAndType #5:#13 // init:(Ljava/lang/String;)V#13 Utf8 (Ljava/lang/String;)V#14 String #15 // wang-javaer#15 Utf8 wang-javaer#16 Class #17 // com/example/StringExample#17 Utf8 com/example/StringExample#18 Utf8 Code#19 Utf8 LineNumberTable#20 Utf8 main#21 Utf8 ([Ljava/lang/String;)V#22 Utf8 SourceFile#23 Utf8 StringExample.java {public com.example.StringExample();descriptor: ()Vflags: (0x0001) ACC_PUBLICCode:stack1, locals1, args_size10: aload_01: invokespecial #1 // Method java/lang/Object.init:()V4: returnLineNumberTable:line 3: 0public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: (0x0009) ACC_PUBLIC, ACC_STATICCode:stack3, locals4, args_size10: new #7 // class java/lang/String3: dup4: ldc #9 // String javaer-wang6: invokespecial #11 // Method java/lang/String.init:(Ljava/lang/String;)V9: astore_110: ldc #14 // String wang-javaer12: astore_213: ldc #14 // String wang-javaer15: astore_316: returnLineNumberTable:line 5: 0line 6: 10line 7: 13line 8: 16 } SourceFile: StringExample.java备注以上代码的运行也编译环境为 jdk1.8.0_101。 其中 Constant pool 表示字符串常量池我们在字符串编译期的字符串常量池中找到了我们 String s1 new String(javaer-wang);  定义的“javaer-wang”字符在信息 #10 Utf8 javaer-wang 可以看出也就是在编译期 new 方式创建的字符串就会被放入到编译期的字符串常量池中也就是说 new String  的方式会首先去判断字符串常量池如果没有就会新建字符串那么就会创建 2 个对象如果已经存在就只会在堆中创建一个对象指向字符串常量池中的字符串。 那么问题来了以下这段代码的执行结果为 true 还是 false String s1 new String(javaer-wang); String s2 new String(javaer-wang); System.out.println(s1 s2);既然 new String 会在常量池中创建字符串那么执行的结果就应该是 true 了。其实并不是这里对比的变量 s1 和 s2 堆上地址因为堆上的地址是不同的所以结果一定是 false如下图所示 ![字符串引用.png](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlLzAvMjAyMC9wbmcvOTI3OTEvMTU4NzA0MzUwNDAyMS00MzFkYTMyZS0xYjE0LTQ1NmEtOGZmNy0zZGJmYzM3Yjg2NTIucG5n?x-oss-processimage/format,png#alignleftdisplayinlineheight394margin[object Object]name字符串引用.pngoriginHeight394originWidth593size41183statusdonestylenonewidth593) 从图中可以看出 s1 和 s2 的引用一定是相同的而 s3 和 s4 的引用是不同的对应的程序代码如下 public static void main(String[] args) {String s1 Java;String s2 Java;String s3 new String(Java);String s4 new String(Java);System.out.println(s1 s2);System.out.println(s3 s4); }程序执行的结果也符合预期 true false 扩展知识 我们知道 String 是 final 修饰的也就是说一定被赋值就不能被修改了。但编译器除了有字符串常量池的优化之外还会对编译期可以确认的字符串进行优化例如以下代码 public static void main(String[] args) {String s1 abc;String s2 ab c;String s3 a b c;System.out.println(s1 s2);System.out.println(s1 s3); }按照 String 不能被修改的思想来看s2 应该会在字符串常量池创建两个字符串“ab”和“c”s3 会创建三个字符串他们的引用对比结果也一定是 false但其实不是他们的结果都是 true这是编译器优化的功劳。 同样我们使用 javac StringExample.java 先编译代码再使用 javap -c StringExample 命令查看编译的代码如下 警告: 文件 ./StringExample.class 不包含类 StringExample Compiled from StringExample.java public class com.example.StringExample {public com.example.StringExample();Code:0: aload_01: invokespecial #1 // Method java/lang/Object.init:()V4: returnpublic static void main(java.lang.String[]);Code:0: ldc #7 // String abc2: astore_13: ldc #7 // String abc5: astore_26: ldc #7 // String abc8: astore_39: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;12: aload_113: aload_214: if_acmpne 2117: iconst_118: goto 2221: iconst_022: invokevirtual #15 // Method java/io/PrintStream.println:(Z)V25: getstatic #9 // Field java/lang/System.out:Ljava/io/PrintStream;28: aload_129: aload_330: if_acmpne 3733: iconst_134: goto 3837: iconst_038: invokevirtual #15 // Method java/io/PrintStream.println:(Z)V41: return }从 Code 3、6 可以看出字符串都被编译器优化成了字符串“abc”了。 总结 本文我们通过 javap -v XXX 的方式查看编译的代码发现 new String 首次会在字符串常量池中创建此字符串那也就是说通过 new 创建字符串的方式可能会创建 1 个或 2 个对象如果常量池中已经存在此字符串只会在堆上创建一个变量并指向字符串常量池中的值如果字符串常量池中没有相关的字符会先创建字符串在返回此字符串的引用给堆空间的变量。我们还将了字符串常量池在 JDK 1.7 和 JDK 1.8 的变化以及编译器对确定字符串的优化希望能帮你正在的理解字符串的比较。 最后的话 原创不易本篇近 3000 的文字描述以及大量精美的图片耗费了作者大概 5 个多小时的时间写作是一件很酷并且能帮助他人的事作者希望一直能坚持下去。如果觉得有用请随手点击一个赞吧谢谢。
http://www.sadfv.cn/news/227582/

相关文章:

  • 上传户型图生成效果图长沙网站快速优化排名
  • 做阿里云网站的公司吗所见即所得的网页编辑器
  • 不会代码怎么做外贸网站WordPress做分类信息平台
  • 福建得兴建设工程网站什么网站可以买世界杯
  • 邯郸做淘宝网站怎样申请做c c 网站
  • 做网站推广好做吗威海优化推广
  • 建设网站个人简介范文网站的展现形式
  • 才做的网站怎么搜不到wordpress 的论坛模板
  • 电子商务网站建设 精品课程南京市建设执业资格中心网站
  • 漳州微网站建设公司哪家好山东住房和城乡建设厅网站登陆
  • 服务器上怎做网站网上快速学做网站
  • 网络营销是什么的基础选择题做seo哪些网站会好点
  • 网站打开404错误怎么解决松江 企业网站建设
  • 正规网站建设商家建立个人网站的目的
  • 免费搭建自己的官网镇江网站建设优化
  • 中建建设银行网站跨境电商主要平台有哪些
  • 做网站比较专业的有哪些公司安阳市建设工程招标投标协会网站
  • 重庆网站建设快速建站河南专业网站建设开发团队
  • 电脑QQ浮动窗口怎做电脑网站网站商城的建设
  • 企业网站首页设计欣赏株洲制作网站
  • 宝安网站制作培训施工企业信用评价
  • 天猫网站设计创建一个网站流程图
  • 网站制作网络推广价格seo任务平台
  • 广州市建设交易中心网站北京最新公告
  • 外贸soho建站多少钱网址大全免费下载安装
  • 触屏网站开发北京市工程信息网
  • 企业品牌营销型网站建设ppt模板哪里可以免费下载
  • 好的做外贸的网站郑州高档网站建设
  • 小说网站开发需求企业营销策略分析论文
  • 苏州官网设计优化网站推广教程整站