博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 语言设计中的部分共享策略
阅读量:4934 次
发布时间:2019-06-11

本文共 2787 字,大约阅读时间需要 9 分钟。

Java 语言的设计者认为共享带来的效率远远高于提取、拼接字符串所带来的低效率。    ——Core Java

 

  在之前的学习和使用过程中,遇到过字符串常量池的概念,对于整形,在其源码中也有缓存数组的概念。其实这些类似概念,都是JVM对获取常用的字符串、整形对象这一操作所做的优化。

下面我们来分析下创建字符串的两种方式 

1         String s1 = "hello"; 2         String s2 = "hello"; 3         String s3 = new String("hello"); 4      // equals比较字符串字符值是否相等,均为 true  5         System.out.println(s1.equals(s2)); 6         System.out.println(s2.equals(s3)); 7         System.out.println(s1.equals(s3)); 8       9         System.out.println(s1==s2); // true10         System.out.println(s1==s3); // false11         System.out.println(s2==s3); // false

对于第一种方式

  用字面值的方式创建一个字符串时,JVM首先会去字符串常量池中查找是否存在"hello"这个对象,如果不存在,则在字符串常量池中创建"hello"这个对象,然后将池中"hello"这个对象的引用地址返回给"hello"对象的引用s1,这样s1会指向字符串常量池中"hello"这个字符串对象;如果存在,则不创建任何对象,直接将池中"hello"这个对象的地址返回,赋给引用s2。因为s1、s2都是指向同一个字符串池中的"hello"对象,所以“==”比较结果true。

对于第二种方式

  采用new关键字新建一个字符串对象时,JVM会首先在字符串池中查找有没有"hello"这个字符串对象,如果有,则不在池中再去创建"hello"这个对象了,直接在堆中创建一个"hello"字符串对象,然后将堆中的这个"hello"对象的地址返回赋给引用s3,这样,s3就指向了堆中创建的这个"hello"字符串对象;如果没有,则首先在字符串池中创建一个"hello"字符串对象,然后再在堆中创建一个"hello"字符串对象,然后将堆中这个"hello"字符串对象的地址返回赋给s3引用,这样,s3指向了堆中创建的这个"hello"字符串对象。所以在进行“==”比较的时候,s1 和 s2 都是指向常量池中的字符串对象。s3 是指向堆中字符串对象。结果肯定为false。

考虑下面的整形恒等判断的代码

1         Integer a = Integer.valueOf(3);2         Integer b = Integer.valueOf(3);3 4         Integer c = Integer.valueOf(323);5         Integer d = Integer.valueOf(323);6 7         System.out.println(a==b);8         System.out.println(c==d);

输出结果为

1 ```2 true3 false4 ```
为什么会有这样的输出结果呢?
点击查看Integer.valueOf()方法的源码,发现:
@HotSpotIntrinsicCandidate    public static Integer valueOf(int i) {        if (i >= IntegerCache.low && i <= IntegerCache.high)            return IntegerCache.cache[i + (-IntegerCache.low)];        return new Integer(i);    }
  其方法注释的意思是:返回表示指定 Integer 的实例。如果不需要新的 integer 实例,则通常应优先使用此方法,而不是使用构造函数 integer(int),因为通过缓存频繁请求值,此方法可能会显著提高空间和时间性能。此方法将始终缓存范围为-128到127(含)的值,并可能缓存此范围之外的其他值。
 
  再去看看IntegerCache类的源码,发现在这个静态内部类声明了一个Integer cache[],对于-128~127的整形,也就是占用1个字节的整形来说,如果用Integer.valueOf()方法进行初始化,就会从这个缓存数组中取值,因为JVM对这种操作进行了优化,,所以可以用一个缓存数组进行速度上的提升。
再看看下面一段代码:
1         Integer e  = 42;2         Integer f = 42;3 4         Integer g  = 423;5         Integer h = 423;6         7         System.out.println(e==f); // true8         System.out.println(g==h); // false
 
让我们来分析一下产生如此结果之原因,对于 e, f 他们的代码等同于
    Integer e  = 42; // Integer d = Integer.valueOf(42);        Integer f = 42;  // Integer d = Integer.valueOf(42);
所以 e==f 返回true;对于 g 和 h
1         Integer g  = 423; 2         Integer h = 423;
由于423超过了-128~127(含)的范围,所以不会再去使用缓存数组中的整形值,而是使用了:
1         Integer g = new Integer(423);2         Integer h = new Integer(423);

  都是使用了 new 关键字进行整形的创建,g 和 h指向的是堆中两个不同的地址,他们进行恒等判断结果当然就是false。IntegerCache 类的 cache[] 数组和数组字符串常量池有异曲同工之妙。

 

 

 

 

转载于:https://www.cnblogs.com/dogeLife/p/11154475.html

你可能感兴趣的文章
3.每周总结
查看>>
应用提交 App Store 上架被拒绝
查看>>
Android实现异步处理 -- HTTP请求
查看>>
数据清空js清空div里的数据问题
查看>>
Fortran中的指针使用
查看>>
移动终端app测试点总结
查看>>
14-6-27&28自学内容小结
查看>>
JSP
查看>>
---
查看>>
(第一组_GNS3)自反ACl
查看>>
hdu--1258--Sum It Up(Map水过)
查看>>
Spring @DeclareParents 的扩展应用实例
查看>>
VS2012更新Update1后帮助查看器无法打开
查看>>
【Weiss】【第03章】练习3.9:大整数运算包
查看>>
Android 文件的读取和写入
查看>>
机器学习-加权采样算法简介
查看>>
高校表白APP-冲刺第四天
查看>>
outlook 设置163邮箱
查看>>
mysql优化——show processlist命令详解
查看>>
Solr服务器搭建
查看>>