文档章节

J2SE入门(三) String深度解析

SEOwhywhy
 SEOwhywhy
发布于 06/22 11:41
字数 1642
阅读 39
收藏 1

  String可以说是Java中使用最多最频繁、最特殊的类,因为同时也是字面常量,而字面常量包括基本类型、String类型、空类型。
  
  一. String的使用
  
  1. String的不可变性
  
  /**
  
  * The {@code String} class represents character strings. All
  
  * string literals in Java programs, such as {@code "abc"}, are
  
  * implemented as instances of this class.
  
  * <p>
  
  * Strings are constant; their values cannot be changed after they
  
  * are created. String buffers support mutable strings.
  
  * Because String objects are immutable they can be shared. For example:
  
  * ...
  
  */
  
  public final class String {
  
  private final char value[];
  
  }
  
  String对象一旦在堆中创建出来,就无法再修改。因为String对象放在char数组中,该数组由final关键字修饰,不可变。
  
  2. 定义一个字符串
  
  /**
  
  * 定义一个字符串
  
  */
  
  String str1 = "helloworld";
  
  String str2 = "helloworld";
  
  //也可以,但基本不这样写
  
  String str3 = new String("helloworld");
  
  System.out.println(str1 == str2);
  
  System.out.println(str1 == str3);
  
  //运行结果 true, false
  
  上面三句代码怎么理解呢?这里需要先引入一个概念,字符串常量池。
  
  字符串常量池是一块特殊的独立内存空间,放在Java Heap中 { 在Jdk7.0之前字符串常量池存放在PermGen中,Jdk7.0的时候移动到了Java Heap(在堆中仍然是独立的),Jdk8.0的时候去掉了PermGen,用Metaspace进行取代 } ,Java内存模型不是本章讨论的重点。
  
  str1和str2引用的字符串字面量就在字符串常量池中,而str3引用的对象在Java Heap中。
  
  怎么,还不太好理解?举个例子
  
  工作一天,到下班时间了,准备看会儿金瓶.,算了,《三国演义》,打开小说网站,在线阅读;过了半个小时,女票回家了,看《三国演义》也是她想做的事儿,我看网址发给她,好,她也开始看了,再过半个小时,我爸回来了,他也是三国迷,但是他不喜欢在线看,因此在书店买了一本看。
  
  上面提到的小说网站就是一个字符串常量池,包含了很多字符串字面量,如《三国演义》、《西游记》、《红楼梦》等,每个字符串字面量在常量池中保持独一份,无论谁进网站看《三国演义》都是同样的网址和同样的内容。
  
  我和女票就是str1和str2,我们看的都是同一个网站的《三国演义》,不仅内容一样,引用的地址也一样(字符串常量池中保留了唯一的“helloworld”),因此str1 == str2 运行结果为true
  
  而我爸就是str3,与我和女票都不一样,虽然看的内容也是《三国演义》,但是通过实体书籍来看,引用地址不一样,同时一本书籍不支持多个人同时看(字符串对象在java heap中,且每次new都会新建一个对象),因此str1 == str3 运行结果为false。
  
  一个字符串字面量总是引用String类的同一个实例,因为被String.intern()方法限定了,同样我们可以调用该方法将堆中的String对象放到字符串常量池中,这样做可以提升内存使用效率,同时可以让所用使用者共享唯一的实例。
  
  System.out.println(str1 == str3.intern());
  
  //运行结果为true
  
  那么该方法的实现逻辑是怎么样的呢,我们看一下源码
  
  /**
  
  * Returns a canonical representation for the string object.
  
  * <p>
  
  * A pool of strings, initially empty, is maintained privately by the
  
  * class {@code String}.
  
  * <p>
  
  * When the intern method is invoked, if the pool already contains a
  
  * string equal to this {@code String} object as determined by
  
  * the {@link #equals(Object)} method, then the string from the pool is
  
  * returned. Otherwise, this {@code String} object is added to the
  
  * pool and a reference to this {@code String} object is returned.
  
  * <p>
  
  * It follows that for any two strings {@code s} and {@code t},
  
  * {@code s.intern(www.yuchengyuLe.com) == t.intern()} is {@code true}
  
  * if and only if {@code s.equals(t)} is {@code true}.
  
  * <p>
  
  * All literal strings and string-valued constant expressions are
  
  * interned. String literals are defined in section 3.10.5 of the
  
  * <cite>The Java&trade; Language Specification<www.chaoyuL.com  /cite>.
  
  *
  
  * @return  a string that has the same contents as this string, but is
  
  *          guaranteed to be from a pool of unique strings.
  
  */
  
  public native String intern();
  
  我们发现这是一个native方法,看一下注释,发现str3.intern()方法大致流程是:
  
  当执行intern()时,会先判断字符串常量池中是否含有相同(通过equals方法)的字符串字面量,如果有直接返回字符串字面量;如果不含,则将该字符串对象添加到字符串常量池中,同时返回该对象在字符串常量池的引用。
  
  返回的引用需要赋值才可,否则还是会指向堆中的地址,即:
  
  String str4 = new String("helloChina");
  
  System.out.println(str4.intern(www.chenghyLpt.com) == str4);//false
  
  str4 = str4.intern(www.xingtuyLgw.com);
  
  String str5 = "helloChina";
  
  String str6 = "helloZhonghua"
  
  System.out.println(str4 == str5);//true
  
  下面我们看一下内存结构
  
  3. 再次赋值给已定义的字符串
  
  str6 = "helloHuaxia";
  
  我们开始已经说了String是由final关键字修饰,不可变,那么此时在内存中如何体现呢?
  
  4. String 对 “+” 的处理
  
  String str7 = "good good" + " study";
  
  String str8 = "good good study";
  
  system.out.println(str7 == str8);
  
  通过编译工具后得到
  
  String str7 = "good good study";
  
  String str8 = "good good study";
  
  因此我们可以发现编译器在编译期间就是进行变量合并,而不会在常量池中创建三个对象 “good good”,“ study”,"good good study"。str7 == str8 运行结果 true。
  
  但如果这样
  
  String str9 = "good good ";
  
  String str10 = str9 + "study";
  
  system.out.println(str8 == str10);//false
  
  这时运行结果为false,通过String变量 + 字符常量方式得到的结果会在堆中,不在常量池中,当然可以通过intern()方法放进常量池中,同时不仅“+”如此,调用substring(),toUpperCase(),trim()等返回的都是String在堆中的地址。
  
  5. String常用的方法
  
  //str1 == "hello,world ";
  
  //获取长度
  
  str1.length()//12;
  
  //截取位置2到5之间的字符串(包括位置2,不包括位置5,从0开始)
  
  str1.substring(2,5);//"llo"
  
  //判断是否含有字符串“ello”
  
  str1.contains("ello");//true,通过indexOf实现
  
  //获取ello在str1中的开始位置
  
  str1.indexOf("ello");//1
  
  //将字符串转化为字符串数据
  
  str1.split(",");//["hello","world"]
  
  //去掉字符串两侧空格
  
  str1.trim();//"hello,world"
  
  二. 总结
  
  本文从String的不可变性,String创建时字面量和String对象的不同,字符串字面量常量池,字符串的内存结构,常用的String相关方法的描述,若有不对之处,请批评指正,望共同进步,谢谢!

© 著作权归作者所有

SEOwhywhy
粉丝 8
博文 155
码字总数 342404
作品 0
私信 提问
common digester-入门

Commons-Digester简介 一.历史 Digester本来仅仅是Jakarta Struts中的一个工具,用于处理struts-config.xml配置文件。显然,将XML文件转换成相应的Java对象是一项很通用的功能,这个工具理应...

gzh412163
2014/06/20
104
0
Gradle入门系列(二)——groovy高级语法

groovy高级语法 一、json操作 使用groovy自带的json工具进行json操作 groovy.json.JsonSlurper:将json原数据转成实体对象 groovy.json.JsonOutput:将实体对象转成json数据 groovy是完全兼容...

GitLqr
01/05
0
0
学习JVM是如何从入门到放弃的?

只有光头才能变强 JVM在准备面试的时候就有看了,一直没时间写笔记。现在到了一家公司实习,闲的时候就写写,刷刷JVM博客,刷刷电子书。 学习JVM的目的也很简单: 能够知道JVM是什么,为我们...

Java3y
2018/07/11
375
3
【目录导航】JAVA零基础进阶之路

【JAVA零基础入门系列】(已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day6 Java字符串 Day7 Java输入与输出...

MFrank
2018/06/21
0
0
你所需要的java提升篇大总结

java基础篇深入解析大总结 java基础(一) 深入解析基本类型 java基础(二) 自增自减与贪心规则 java基础(三) 加强型for循环与Iterator java基础(四) java运算顺序的深入解析 java基础(五) Str...

sihailoveyan
2018/04/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

最简单的获取相机拍照的图片

  import android.content.Intent;import android.graphics.Bitmap;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import andr......

MrLins
52分钟前
4
0
说好不哭!数据可视化深度干货,前端开发下一个涨薪点在这里~

随着互联网在各行各业的影响不断深入,数据规模越来越大,各企业也越来越重视数据的价值。作为一家专业的数据智能公司,个推从消息推送服务起家,经过多年的持续耕耘,积累沉淀了海量数据,在...

个推
54分钟前
7
0
第三方支付-返回与回调注意事项

不管是支付宝,微信,还是其它第三方支付,第四方支付,支付机构服务商只要涉及到钱的交易都要进行如下校验,全部成功了才视为成功订单 1.http请求是否成功 2.校验商户号 3.校验订单号及状态...

Shingfi
56分钟前
4
0
简述Java内存分配和回收策略以及Minor GC 和 Major GC(Full GC)

内存分配: 1. 栈区:栈可分为Java虚拟机和本地方法栈 2. 堆区:堆被所有线程共享,在虚拟机启动时创建,是唯一的目的是存放对象实例,是gc的主要区域。通常可分为两个区块年轻代和年老代。更...

DustinChan
今天
6
0
Excel插入批注:可在批注插入文字、形状、图片

1.批注一直显示:审阅选项卡-------->勾选显示批注选项: 2.插入批注快捷键:Shift+F2 组合键 3.在批注中插入图片:鼠标右键点击批注框的小圆点【重点不可以在批注文本框内点击】----->调出批...

东方墨天
今天
6
1

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部