String在java中是一个很特殊的类,但很多人对他的了解都很局限。快来跟我了解一下String吧。

String的创建方式

public class Test {public static void main(String[] args) {//通过new创建出来String s1 = new String("123");//直接指定一个常量String s2 = "123";}
}

很多人就会想这傻子都知道,你是把我们当傻子吧。

此言差矣,我当然是不敢这样想啊。

但小伙伴们,你们知道这两种创建方式有什么区别吗?
我相信学过Java的小伙伴应该会了解个大概,不就是一个创建在常量池,一个创建在堆区嘛,简单。

可是到底是什么样子的呢?

首先我们要先了解String类中的一个native方法

    public native String intern();

他到底干了什么呢?

我们先看一眼源代码里是怎么说的

大致意思也就是如果池子里有的话就直接返回池子中的字符串。没有的话就在池子中创建后,再返回。

但是池子中的字符串是什么样子呢?
我们都知道字符串在早期Java版本中本身是一个字符数组,在较新的Java版本是一个字节数组。无论如何他就是一个数组。

//String中的成员变量
private final byte[] value;
private final byte coder;
private int hash;

了解了这些,这篇文章就要开始了。

我们先将一开始创建字符串的代码进行反编译。
把代码拿下来方便大家看。

public class Test {public static void main(String[] args) {//通过new创建出来String s1 = new String("123");//直接指定一个常量String s2 = "123";}
}

先对Java进行编译

javac Test.java

对生成的字节码文件反编译

javap -v Test

注意这里的参数 -v是为了显示常量池中的东西。
我这里先删掉不必要的代码。

public class test3
Constant pool:
//常量池#2 = Class              #16            // java/lang/String#3 = String             #17            // 123
//这个#4是指String的clinit方法#4 = Methodref          #2.#18         // java/lang/String."<init>":#16 = Utf8               java/lang/String#17 = Utf8               123
{public test3();public static void main(java.lang.String[]);Code:stack=3, locals=4, args_size=10: new           #2                  // class java/lang/String3: dup4: ldc           #3                  // String 1236: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V9: astore_110: ldc           #3                  // String 12312: astore_213: ldc           #3                  // String 12315: astore_316: return
}

我们可以看到

ldc #3

这句话出现了三次,第一次是在new之后出现的,那这个#3字符串到底是个什么东西呢。

我们来看一下String的构造方法

//String的构造方法将传入字符传的成员变量赋给了当前字符串public String(String original) {this.value = original.value;this.coder = original.coder;this.hash = original.hash;this.hashIsZero = original.hashIsZero;}

这个original到底是什么呢?
我们并没有创建这个字符串对象啊,我们只是传入了一个字符串常量 “123”
我猜想这个就是Java自己创建的字符串对象,也就是#3这个字符串

那接下来一切就特别明了了。

当我们第一次使用某个字符串常量时Java会帮我们创建一个字符串对象在常量池中。

当我们使用字面值的方式创建String时

String s2 = "123";

s2指向的是常量池中的String对象

但使用new的方式创建呢?

public class test3 {public static void main(String[] args) {String s1 = new String("123");String s2 = new String("123");String s3 = "123";String s4 = "123";System.out.println();}
}

我们在idea中进行调试

我们发现s1的value和s2的value是一样的,但是他们的地址确实不一样的
这就说明s1和s2指向的位置不一样,但他们的成员变量value却指向同一个地方。

s3的value属性也是这个地方。

总结:创建字符串时,使用没有使用过的字符串常量会先在常量池创建一个字符串对象。
之后如果使用字面值创建同样的字符串的话,会直接指向常量池中的字符串对象。
使用new 的方式创建会在堆上创建一个字符串,他的value属性指向与常量池中字符串的value属性指向同一个位置。

快来了解String的秘密吧相关推荐

  1. 如何更快地将string转换成int/long

    作者 | Kirito的技术分享 来源 | https://mp.weixin.qq.com/s/5qQg3ef8yjVG089iqoNTaw 你好鸭,Kirito 今天又来分享性能优化的骚操作了. ...

  2. StringBuilder、StringBuffer、String区别

    相信大家对 String 和 StringBuffer 的区别也已经很了解了,但是估计还是会有很多同志对这两个类的工作原理有些不清楚的地方,今天重新把这个概念给大家复习一下,顺便牵出 J2SE5.0 ...

  3. 2.Java中String,StringBuilder以及StringBuffer的关系与区别

    String     StringBuffer     StringBuilder String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量 ...

  4. String,StringBuffer与StringBuilder的区别??

    2019独角兽企业重金招聘Python工程师标准>>> String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全 ...

  5. Java String,StringBuilder和StringBuffer的区别 StringBuilder StringBuffer String

    可以证明,字符串操作是计算机程序设计中最常见的行为. String:不可变的对象,对String对象进行改变的时候其实都等同于生成了一个新的String对象,然后将引用指向新的String对象,原St ...

  6. String , StringBuffer 和 StringBuilder 区别

    转载:http://www.blogjava.net/chenpengyi/archive/2006/05/04/44492.html 相信大家对 String 和 StringBuffer 的区别也 ...

  7. String, StringBuffer, StringBuilder(转载)

    http://blog.csdn.net/rmn190/article/details/1492013 String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuil ...

  8. 是 String , StringBuffer 还是 StringBuilder ?

    相信大家对 String 和 StringBuffer 的区别也已经很了解了,但是估计还是会有很多同志对这两个类的工作原理有些不清楚的地方,今天我在这里重新把这个概念给大家复习一下,顺便牵出 J2SE ...

  9. 浅谈 Java 字符串(String, StringBuffer, StringBuilder)

    我们先要记住三者的特征: String 字符串常量 StringBuffer 字符串变量(线程安全) StringBuilder 字符串变量(非线程安全) 一.定义 查看 API 会发现,String ...

最新文章

  1. python基础-分支判断语句(4)
  2. Firebug 1.7正式版发布,支持Firefox 4
  3. JQuery Mobile 手机显示页面偏小
  4. Swoole源代码学习记录(十五)——Timer模块分析
  5. apache站点优化——长连接
  6. [推荐] 世界上最健康的作息时间表
  7. php结合jquery异步上传图片(ajaxSubmit)
  8. zabbix5.2安装-linux
  9. php多个请求只执行一次,php使用redis的blPop/brPop,一台服务器多个并发,也只能一次一次执行?...
  10. 在位运算中_Java常见的运算符(下)
  11. 【java】java 扩展可回调的Future
  12. 数据库事务的一致性和原子性浅析
  13. 打造自己的Android源码学习环境之一:序
  14. Bodymovin插件的使用
  15. C++实现身份证校验和归属地查询
  16. nandflash地址的物理地址,逻辑地址,spare地址等理解
  17. PHP后端跨域HEADER头的设置
  18. 10月份语音合成任务安排: 商业化的普通话合成 (质量, 速度, 准确度, 韵律)
  19. B2B2C多商户商城源码/分销商城/多用户商城系统/商家入驻商城系统
  20. acer计算机的无线功能键,Acer笔记本Fn组合键功能说明

热门文章

  1. RXA-Thanos是一个SpringCloud 分布式事务解决方案
  2. vue svg阴阳图水波图
  3. 脱机 磁盘处于脱机状态_如何阻止您的网站脱机
  4. 1705. 吃苹果的最大数目(贪心算法)
  5. 超详细Linux搭建Java开发环境
  6. 词云可视化:四行Python代码轻松上手到精通
  7. 树莓派26/100 - Pico控制RGB三色灯
  8. 【记录】关于Intel wireless-ac-9461错误代码56或10
  9. “钢刀刑警”露面,南部孔氏涉黑集团案更多细节被曝光
  10. 最小比例生成树 小澳的葫芦