zoukankan      html  css  js  c++  java
  • java String部分源码解析

    String类型的成员变量

    /** String的属性值 */  
        private final char value[];
    
        /** The offset is the first index of the storage that is used. */
        /**数组被使用的开始位置**/
        private final int offset;
    
        /** The count is the number of characters in the String. */
        /**String中元素的个数**/
        private final int count;
    
        /** Cache the hash code for the string */
       /**String类型的hash值**/
        private int hash; // Default to 0
    
        /** use serialVersionUID from JDK 1.0.2 for interoperability */
        private static final long serialVersionUID = -6849794470754667710L;

       有上面的成员变量可以知道String类的值是final类型的,不能被改变的,所以只要一个值改变就会生成一个新的String类型对象,存储String数据也不一定从数组的第0个元素开始的,而是从offset所指的元素开始。

    如下面的代码是生成了一个新的对象,最后的到的是一个新的值为“bbaa”的新的String的值。

         String a = new String("bb");
         String b = new String("aa");
         String c =  a + b;    

      也可以说String类型的对象是长度不可变的,String拼接字符串每次都要生成一个新的对象,所以拼接字符串的效率肯定没有可变长度的StringBuffer和StringBuilder快。

    然而下面这种情况却是很快的拼接两个字符串的:

        String a = "aa" + "bb";

      原因是:java对它字符串拼接进行了小小的优化,他是直接把“aa”和“bb”直接拼接成了“aabb”,然后把值赋给了a,只需生成一次String对象,比上面那种方式减少了2次生成String,效率明显要高很多。


    下面我们来看看String的几个常见的构造方法

    1、无参数的构造方法:

    public String() {
        this.offset = 0;
        this.count = 0;
        this.value = new char[0];
        }

    2、传入一个Sring类型对象的构造方法

    public String(String original) {
        int size = original.count;
        char[] originalValue = original.value;
        char[] v;
          if (originalValue.length > size) {
             // The array representing the String is bigger than the new
             // String itself.  Perhaps this constructor is being called
             // in order to trim the baggage, so make a copy of the array.
                int off = original.offset;
                v = Arrays.copyOfRange(originalValue, off, off+size);
         } else {
             // The array representing the String is the same
             // size as the String, so no point in making a copy.
            v = originalValue;
         }
        this.offset = 0;
        this.count = size;
        this.value = v;
        }

     3、传入一个字符数组的构造函数

    public String(char value[]) {
        int size = value.length;
        this.offset = 0;
        this.count = size;
        this.value = Arrays.copyOf(value, size);
        }

    4、传入一个字符串数字,和开始元素,元素个数的构造函数

    public String(char value[], int offset, int count) {
            if (offset < 0) {
                throw new StringIndexOutOfBoundsException(offset);
            }
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            // Note: offset or count might be near -1>>>1.
            if (offset > value.length - count) {
                throw new StringIndexOutOfBoundsException(offset + count);
            }
            this.offset = 0;
            this.count = count;
            this.value = Arrays.copyOfRange(value, offset, offset+count);
        }

       由上面的几个常见的构造函数可以看出,我们在生成一个String对象的时候必须对该对象的offset、count、value三个属性进行赋值,这样我们才能获得一个完成的String类型。


    常见函数:

    1、判断两个字符串是否相等的函数(Equal):其实就是首先判断比较的实例是否是String类型数据,不是则返回False,是则比较他们每一个字符元素是否相同,如果都相同则返回True,否则返回False

    public boolean equals(Object anObject) {
     if (this == anObject) {
         return true;
     }
     if (anObject instanceof String) {
         String anotherString = (String)anObject;
         int n = count;
         if (n == anotherString.count) {
      char v1[] = value;
      char v2[] = anotherString.value;
      int i = offset;
      int j = anotherString.offset;
      while (n-- != 0) {
          if (v1[i++] != v2[j++])
       return false;
      }
      return true;
         }
     }
     return false;
        }

     2、比较两个字符串大小的函数(compareTo):输入是两个字符串,返回的0代表两个字符串值相同,返回小于0则是第一个字符串的值小于第二个字符串的值,大于0则表示第一个字符串的值大于第二个字符串的值。

      比较的过程主要如下:从两个字符串的第一个元素开始比较,实际比较的是两个char的ACII码,加入有不同的值,就返回第一个不同值的差值,否则返回0

    public int compareTo(String anotherString) {
     int len1 = count;
     int len2 = anotherString.count;
     int n = Math.min(len1, len2);
     char v1[] = value;
     char v2[] = anotherString.value;
     int i = offset;
     int j = anotherString.offset;
    
     if (i == j) {
         int k = i;
         int lim = n + i;
         while (k < lim) {
      char c1 = v1[k];
      char c2 = v2[k];
      if (c1 != c2) {
          return c1 - c2;
      }
      k++;
         }
     } else {
         while (n-- != 0) {
      char c1 = v1[i++];
      char c2 = v2[j++];
      if (c1 != c2) {
          return c1 - c2;
      }
         }
     }
     return len1 - len2;
        }
    View Code

     3、判断一个字符串是否以prefix字符串开头,toffset是相同的长度

    public boolean startsWith(String prefix, int toffset) {
     char ta[] = value;
     int to = offset + toffset;
     char pa[] = prefix.value;
     int po = prefix.offset;
     int pc = prefix.count;
     // Note: toffset might be near -1>>>1.
     if ((toffset < 0) || (toffset > count - pc)) {
         return false;
     }
     while (--pc >= 0) {
         if (ta[to++] != pa[po++]) {
             return false;
         }
     }
     return true;
        }
    
     public int hashCode() {
     int h = hash;
     if (h == 0) {
         int off = offset;
         char val[] = value;
         int len = count;
    
                for (int i = 0; i < len; i++) {
                    h = 31*h + val[off++];
                }
                hash = h;
            }
            return h;
        }

     4、连接两个字符串(concat)

    public String concat(String str) {
     int otherLen = str.length();
     if (otherLen == 0) {
         return this;
     }
     char buf[] = new char[count + otherLen];
     getChars(0, count, buf, 0);
     str.getChars(0, otherLen, buf, count);
     return new String(0, count + otherLen, buf);
        }

     连接字符串的几种方式

    1、最直接,直接用+连接

         String a = new String("bb");
         String b = new String("aa");
         String c =  a + b;

     2、使用concat(String)方法

          String a = new String("bb");
          String b = new String("aa"); 
          String d = a.concat(b);

    3、使用StringBuilder

     String a = new String("bb");
     String b = new String("aa");
         
    StringBuffer buffer = new StringBuffer().append(a).append(b);

       第一二中用得比较多,但效率比较差,使用StringBuilder拼接的效率较高。

  • 相关阅读:
    【转】final 关键字
    【转】安装Fiddler2+JsonViewer插件
    【转】SAP SD定价技术分析
    【转】SAP PP 顾问面试考试试题及资料
    【转】Hibernate数据过滤
    【转】与计划有关的生产数据
    【转】销售凭证类别
    将MyEclipse中的项目导入到Eclipse中报错的解决放法,将项目打war包部署服务器
    查看Android下生成的.db数据库
    删除快速启动栏的快捷方式 pplive
  • 原文地址:https://www.cnblogs.com/0201zcr/p/4621339.html
Copyright © 2011-2022 走看看