Java基础类String学习分析(string java基本数据类型)

  本篇文章为你整理了Java基础类String学习分析(string java基本数据类型)的详细内容,包含有java中string类的常用方法 string java基本数据类型 java中的string的运用 java string类的常用方法 Java基础类String学习分析,希望能帮助你了解 Java基础类String学习分析。

  目录1 String不可变性2 不可变的好处3 String+和StringBuilder效率差异4 String, StringBuffer and StringBuilder5 String与JVM内存管理6 String api方法

  1 String不可变性

  String类被声明为 final,因此它不可被继承。

  内部使用char数组存储数据,该数组被声明为final,这意味着value数组初始化之后就不能再指向其它数组。

  String内部没有改变value数组的方法

  String类中所有修改String值的方法,如果内容没有改变,则返回原来的String对象引用,如果改变了,创建了一个全新的String对象,包含修改后的字符串内容,最初的String对象没有任何改变。(目的:节约存储空间、避免额外的开销)

  

//String的类声明以及value字段代码:

 

  public final class String

   implements java.io.Serializable, Comparable String , CharSequence {

   private final char value[]; //字符数组存储String的内容

   /** Cache the hash code for the string */

   private int hash; // Default to 0

  

 

  不可变的验证分析:

  

public class Immutable {

 

   public static String upcase(String s) {

   return s.toUpperCase();

   public static void main(String[] args) {

   String q = "howdy";

   System.out.println(q); // howdy

   String qq = upcase(q);

   System.out.println(qq); // HOWDY

   System.out.println(q); // howdy

  } /* 输出:

   howdy

   HOWDY

   howdy

   *///:~

  

 

  当把q传给upcase0方法时,实际传递的是引用的一个拷贝。

  upcase0方法中,传入引用s,只有upcase0运行的时候,局部引用s才存在。一旦upcase0运行结束,s就消失。upcaseO的返回值是最终结果的引用。

  综上,upcase()返回的引用已经指向了一个新的对象,而原本的q则还在原地。

  延伸结论:

  String对象作为方法的参数时,都会复制一份引用,参数传递是引用的拷贝

  2 不可变的好处

  1. 可以缓存 hash 值
 

  String的hash值经常被使用,例如String用做HashMap的key。不可变的特性可以使得hash值也不可变,因此只需要进行一次计算。

  2. String Pool 的需要
 

  如果一个String对象已经被创建过了,那么就会从 String Pool 中取得引用。只有String是不可变的,才可能使用 String Pool。

  3. 线程安全
 

  String不可变性天生具备线程安全,可以在多个线程中安全地使用。

  3 String+和StringBuilder效率差异

  String使用“+”表示字符串拼接

  先说结论:

  
“+”操作,javac编译器会自动优化为StringBuilder.append() 调用。

  StringBuilder要比“+”操作高效

  涉及循环追加的,手动创建StringBuilder对象操作比“+”操作编译器优化,更高效

  
编译并查看字节码:javap -verbose StringBuilderTest.class
 

  执行过程:
 

  调用了2次append()方法,最后调用StringBuilder.toString()返回最终结果

  为什么StringBuilder要比+高效?

  +操作,按照:每次追加都创建新的String对象,把字符加入value数组中。这里产生一次对象创建操作,以及对应的垃圾回收

  StringBuilder的底层数组value也是用到了char[],但它没有声明为final,故它可变,所以追加内容时不用创建新的数组,而是直接修改value

  StringBuilder比+省去String对象创建以及垃圾回收的开销,因此效率更高。

  源码追溯:

  

 //StringBuilder.append()

 

   @Override

   public StringBuilder append(char c) {

   super.append(c);

   return this;

   // 父类 AbstractStringBuilder.append()

   @Override

   public AbstractStringBuilder append(char c) {

   ensureCapacityInternal(count + 1);

   value[count++] = c;

   return this;

   //AbstractStringBuilder value 字段

   abstract class AbstractStringBuilder implements Appendable, CharSequence {

   //The value is used for character storage.

   char[] value; // 没有声明为final,因此value可变

  

 

  手动实现StringBuilder对象操作比编译器自行优化,更高效:

  通过字节码分析可知(我这里省去了,可以自己实现验证):循环部分的代码更简短、更简单,而且它只生成了一个StringBuilder对象。

  显式地创建StringBuilder还允许你预先为其指定大小。如果你已经知道最终的字符串大概有多长,那预先指定StringBuilder的大小可以避免多次重新分配缓冲。

  

当你为一个类编写toString方法时,如果字符串操作比较简单,那就可以信赖编译

 

  器,它会为你合理地构造最终的字符串结果。但是,如果你要在toString0方法中使用循环,那

  么最好自己创建一个StringBuilder对象来实现。

  

 

  4 String, StringBuffer and StringBuilder

  可变性

  String 不可变

  StringBuffer和StringBuilder可变

  线程安全

  String不可变,因此是线程安全的

  StringBuilder 不是线程安全的

  StringBuffer 是线程安全的,内部使用synchronized进行同步

  效率

  如果要操作少量的数据用String

  单线程环境且字符串缓冲区涉及大量数据 StringBuilder

  多线程环境且字符串缓冲区涉及大量数据 StringBuffer

  5 String与JVM内存管理

  一、引入字符串常量池

  Javac编译后,字节码文件中有一块区域:常量池,存储了包括类中声明的字符串常量值等字面量

  运行时,JVM开辟实际内存空间:字符串常量值写入了字符串常量池,属于方法区的一部分。

  案例1:

  

String s1 = "win";

 

  String s2 = "win";

  System.out.println(s1==s2);

  //输出结果:true

  //引用 s1 s2 的值等于win在字符串常量池的地址值

  

 

  结论:
 

  引用 s1 s2 的值等于win在字符串常量池的地址值

  分析字节码的执行过程:
 

  案例2:

  

public class StringPool {

 

   public static void main(String[] args) {

   String s3 = new String("win");

   String s4 = new String("win");

   System.out.println(s3==s4);//false

  

 

  结论:
 

  通过new操作符创建的字符串对象不指向字符串池中的任何对象。
 

  字节码分析:
 

  综上:

  

public class StringPool {

 

   public static void main(String[] args) {

   String s1 = "win";

   String s2 = "win";

   String s3 = new String("win");

   String s4 = new String("win");

   System.out.println(s1==s2);//true

   System.out.println(s1==s3);//false

   System.out.println(s3==s4);//false

  

 

  6 String api方法

  从这个表中可以看出,当需要改变字符串的内容时,String类的方法都会返回一个新的String对象。同时,如果内容没有发生改变,String的方法只是返回指向原对象的引用而已。这可以节约存储空间以及避免额外的开销。
 

  
 

  以上就是Java基础类String学习分析(string java基本数据类型)的详细内容,想要了解更多 Java基础类String学习分析的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: