Java学习(2) String介绍

一、字符串的不可变性

1) Java 的字符串类被final修饰,表示该类不能被继承;

2)java 值存储为 final char[] value,变量也不可被修改;

3)每次变更字符串,其实是在内存中新创建一个对象,将变量指向该应用;

二、JDK6和JDK7中substring的区别

1)在jdk 6 中,String类包含三个成员变量:char value[], int offset,int count。他们分别用来存储真正的字符数组,数组的第一个位置索引以及字符串中包含的字符个数。假如字符串足够长,截取后仅用offset到count的数组,其余数组不可被回收。

2)在JDK中是创建一个新的数组,然后截取复制,原数组会被释放掉;

三、replaceFrist、replaceAll、replace的区别

1) replace 是基于字符串的完全替换;srt.replace("old","new");

2)   replaceFrist、replaceAll 是基于正则表达式的替换,

      replaceFrist 只替换第一个

      replaceAll 替换所有

注意:执行了替换操作后,源字符串的内容是没有发生改变的。

四、String 对+的重载

1) 变量 = 字符串 + 字符串;

       这时候其实就是一个完整的字符串对象,java编译器会自动识别处理;

2) 使用String s1 = "yves";    String s2 = s1 + "he";

       

//源码
public static void main(String[] args) {
    String s1 = "yves";
    String s2 = s1 + "he";
}
//反编译后
public static void main(String[] args) {
    String s1 = "yves";
    String s2 = (new StringBuilder(String.valueOf(s1))).append("he").toString();
}

// 由此可知,是使用StringBuilder的append方法和toString方法

 

五、字符串拼接的方式和区别

1) 使用 + 运算符   : 效率低,速度慢,耗内存

2)   concat  底层使用数组扩容,复制。

3)  List 底层也是基于数组对象的复制扩容;

4) StringBuffer  速度慢,线程安全

5) StringBuilder 速度快,线程不安全

六、switch对String的支持

1)以前只支持整型,byte,short,int,char     JDK1.7 后开始支持字符串

七、字符串池

1)" " 引号创建的字符串在字符串池中

2) new,new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则,将使得堆中的字符串永远是池中的子集,导致浪费池的空间)!

另外,对字符串进行赋值时,如果右操作数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回引用;如String s=str1+ "blog";

八、常量池,Class常量池和运行时常量池

1)全局字符串池(string pool也有叫做string literal pool)

              全局字符串池里的内容是在类加载完成,经过验证,准备阶段之后在堆中生成字符串对象实例,然后将该字符串对象实例的引用值存到string pool中(记住:string pool中存的是引用值而不是具体的实例对象,具体的实例对象是在堆中开辟的一块空间存放的。)。 在HotSpot VM里实现的string pool功能的是一个StringTable类,它是一个哈希表,里面存的是驻留字符串(也就是我们常说的用双引号括起来的)的引用(而不是驻留字符串实例本身),也就是说在堆中的某些字符串实例被这个StringTable引用之后就等同被赋予了”驻留字符串”的身份。这个StringTable在每个HotSpot VM的实例只有一份,被所有的类共享。

2) Class 常量池

          我们都知道,class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有一项信息就是常量池(constant pool table),用于存放编译器生成的各种字面量(Literal)和符号引用(Symbolic References)。 字面量就是我们所说的常量概念,如文本字符串、被声明为final的常量值等。 符号引用是一组符号来描述所引用的目标,符号可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可(它与直接引用区分一下,直接引用一般是指向方法区的本地指针,相对偏移量或是一个能间接定位到目标的句柄)。一般包括下面三类常量:

          类和接口的全限定名
          字段的名称和描述符
           方法的名称和描述符

3) 运行时常量池

           jvm在执行某个类的时候,必须经过加载、连接、初始化,而连接又包括验证、准备、解析三个阶段。而当类加载到内存中后,jvm就会将class常量池中的内容存放到运行时常量池中,由此可知,运行时常量池也是每个类都有一个。在上面我也说了,class常量池中存的是字面量和符号引用,也就是说他们存的并不是对象的实例,而是对象的符号引用值。而经过解析(resolve)之后,也就是把符号引用替换为直接引用,解析的过程会去查询全局字符串池,也就是我们上面所说的StringTable,以保证运行时常量池所引用的字符串与全局字符串池中所引用的是一致的。

总结:

         1.全局常量池在每个VM中只有一份,存放的是字符串常量的引用值。
         2.class常量池是在编译的时候每个class都有的,在编译阶段,存放的是常量的符号引用。
         3.运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值转存到运行时常量池中,也就是说,每个class都有一个运行时常量池,类在解析之后,将符号引用替换成直接引用,与全局常量池中的引用值保持一致。

九、String 的 intern

jdk1.6中字符串常量池存放在永久代中:

   当使用intern()方法时,查询字符串常量池是否存在当前字符串,若不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。

jdk1.7中字符串常量池存放在堆中:

    当使用intern()方法时,先查询字符串常量池是否存在当前字符串,若字符串常量池中不存在则再从堆中查询,然后存储并返回相关引用;

若都不存在则将当前字符串复制到字符串常量池中,并返回字符串常量池中的引用。

从上面叙述中,可以得出其中的区别:

  jdk1.6中只能查询或创建在字符串常量池;

  jdk1.7中会先查询字符串常量池,若没有又会到堆中再去查询并存储堆的引用,然后返回。

 

十、String.valueOf 和 Integer.toString的区别

String.valueOf 如果为NULL ,返回的是null字符串,否则是调用object.toString方法;

 

 

 

 

下一篇:java学习(3)--关键字

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值