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

“青岛今晚12时封城”湖北seo公司

“青岛今晚12时封城”,湖北seo公司,沈阳建设公司网站,wordpress版本下载面试回答 创建的对象数 应该是1个或者2个。 首先要清楚什么是对象? Java 是一种面向对象的语言,而 Java 对象在 JVM 中的存储也是有一定的结构的,在 HotSpot 虚拟机中,存储的形式就是 oop-klass model,即 Java 对象模型…

面试回答

创建的对象数 应该是1个或者2个。

首先要清楚什么是对象?

Java 是一种面向对象的语言,而 Java 对象在 JVM 中的存储也是有一定的结构的,在 HotSpot 虚拟机中,存储的形式就是 oop-klass model,即 Java 对象模型。我们在 Java 代码中,使用 new 创建一个对象的时候,JVM 会创建一个 instanceOopDesc 对象,这个对象中包含了两部分信息,对象头以及元数据。对象头中有一些运行时数据,其中就包括和多线程相关的锁的信息。元数据其实维护的是指针,指向的是对象所属的类的 instanceKlass。

这才叫对象。其他的,一概都不叫对象。

那么不管怎么样,一次 new 的过程,都会在堆上创建一个对象,那么就是起码有一个对象了。至于另外一个对象,到底有没有要看具体情况了。

另外这一对象就是常量池中的字符串常量,这个字符串其实是类编译阶段就进到 Class 常量池的,那么当这个类第一次被 ClassLoader 加载的时候,会从 Class 常量池进入到运行时常量池。

在运行时常量池中,也并不是会立刻被解析成对象,而是会先以 JVM_CONSTANT_UnresolveString_info 的形式驻留在常量池。在后面,该引用第一次被 LDC 指令执行到的时候,就尝试在堆上创建字符串对象,并将对象的引用驻留在字符串常量池中。

通过看上面的过程,你也能发现,这个过程的触发条件是我们没办法决定的,问题的题干中也没有提到。有可能执行这段代码的时候是第一次 LDC 指令执行,也许在前面就执行过了。

所以,如果是第一次执行,那么就是会同时创建两个对象。一个字符串常量引用指向的对象,一个我们 new 出来的对象。

如果不是第一次执行,那么就只会创建我们自己 new 出来的对象。

至于有人说什么在字符串池内还有在栈上还有一个引用对象,你听听这说法,引用就是引用。别往对象上面扯。

知识扩展

字面量和运行时常量池

JVM 为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。为了减少在 JVM 中创建的字符串的数量,字符串维护了一个字符串常量池。

在 JVM 运行时区域的方法区中,有一块区域是运行时常量池,主要用来存储编译器生成的各种字面量符号引用

intern

编译器生成的各种字面量符号引用是运行时常量池中比较重要的一部分来源,但是并不是全部。那么还有一种情况,可以在运行期间运行时常量池中添加常量。那就是 Stringintern 方法。

当一个 String实例调用 intern()方法时,Java 查找常量池中是否有相同 Unicode 的字符串常量,如果有,则返回其的引用,如果没有,则在常量池增加一个 Unicode 等于 str 的字符串并返回它的引用。

intern() 有两个作用,第一个是将字符串字面量放入常量池(如果池没有的话),第二个是返回这个常量的引用。

intern 的正确用法

不知道,你有没有发现,在 String s = new String("Tango").intern();中,其实 intern是多余的?

因为就算不用 intern, Tango 作为一个字面量也会被加载到 Class 文件的常量池,进而加入到运行时常量池中,为啥还要多此一举呢?到底什么场景下才需要使用 intern呢?

在解释这个之前,我们先来看下代码:

      String s1="Tango";String s2="Chi";String s3=s1+s2;String s4="Tango"+"Chi";

在经过反编译后,得到代码如下:

        String s1 = "Tango";String s2 = "Chi";String s3 = (new StringBuilder()).append(s1).append(s2).toString();String s4 = "TangoChi";

可以发现,同样是字符串拼接,s3和s4在经过编译器编译后的实现方式并不一样。s3被转化成 StringBuilderappend,而 s4 被直接拼接成新的字符串。

如果你感兴趣,你还能发现,String s3 = s1 + s2;经过编译之后,常量池中是有两个字符串常量的分别是 TangoChi(其实 TangoChiString s1="Tango";String s2="Chi";定义出来的),拼接结果 TangoChi并不在常量池中。

如果代码只有 String s4 = "Tango" + "Chi";,那么常量池中将只有 TangoChi 而没有 TangoChi

究其原因,是因为常量池要保存的是已确定的字面量值。也就是说,对于字符串的拼接,纯字面量和字面量的拼接,会把拼接结果作为常量保持到字符串池。

如果在字符串拼接中,有一个参数是非字面量,而是一个变量的话,整个拼接操作会被编译成 StringBuilder.append,这种情况编译器是无法知道其确定值的。只有在运行期才确定。

那么,有了这个特性了,intern就有了用武之地了。那就是很多时候,我们在程序中得到的字符串只有在运行期才能确定的,在编译期是无法确定的,那么也就没办法在编译期被加入到常量池中。

这时候,对于那种可能经常使用的字符串,使用 intern进行定义,每次 JVM 运行到这段代码的时候,就会直接把常量池该字面值的引用返回,这样就可以减少大量字符串对象的创建了。

如一深入解析 String#intern 文中举的一个例子:

    static  final int Max = 1000 * 100000;static final String[] arr = new String[Max];public static void main(String[] args) {Integer [] DB_DATA=new Integer[10];Random random=new Random(10*10000);for (int i = 0; i < DB_DATA.length;i++) {DB_DATA[i]=random.nextInt();}long t=System.currentTimeMillis();for (int i = 0; i < Max; i++) {arr[i]=new String(String.valueOf(DB_DATA[i%DB_DATA.length])).intern();}System.out.println(System.currentTimeMillis()-t+"ms");System.gc();}

在以上代码中,我们明确的知道,会有很多重复的相同的字符串产生,但是这些字符串的值都是只有在运行期才能确定的。所以,只能我们通过 intern显示的将其加入常量池,这样可以减少很多字符串的重复创建。

http://www.yayakq.cn/news/610636/

相关文章:

  • 定制网站开发接私活域名备案 个人 网站基本信息查询
  • wordpress多站点可视化网站建设的职称
  • 正能量晚上看的网站2021青岛营销型网站设计公司
  • 西安哪个公司可以做网站本科自考什么机构比较正规
  • 做网站你们用什么浏览器北京工装装修公司
  • tp5企业网站开发视频wordpress文章图片灯箱
  • 淘客做网站怎么备案深圳市建设工程交易服务中心宝安分中心
  • 网站建设综合实训心得体会西安有什么好玩的好吃的
  • 大连网站建站四库一平台建造师业绩查询
  • 有哪些档案网站可以自己做网站服务器不
  • 北京网站设计提供商虚拟主机怎么做网站
  • 想创办一个本地的人才招聘网站_如何做市场调查问卷黄金网站app免费视频下载
  • 石家庄网站建设求职简历烤漆 东莞网站建设
  • 做网站推广怎么做wordpress管理面板
  • 自学网站开发难吗企业网站分为哪三种类型
  • 长沙网站定制建设凡科快图网站
  • 想学网站搭建与推广烟台网站制作策划
  • 全国医院网站建设opencart做视频网站
  • 网站描述怎么设置网站模版 之星
  • 宝安西乡网站建设开发企业app公司
  • 湖南城乡建设厅官方网站新建网站百度搜不到
  • 新手学做网站12天婴二级域名怎么做网站备案
  • 网上做调查赚钱的网站微网站工程案例展示
  • 无锡中小企业网站制作网站做推广要备案吗
  • 钓鱼网站下载appwordpress设置文章图片
  • 做网站要什么颜色模式网站设置点赞
  • 重庆未来科技网站建设服务器iis做网站
  • 平果县免费网站哪家好wordpress搜索查询插件
  • 郑州网站建设 智巢logo图案素材免费网站
  • 网站开发重要性西安做网站公司报价