首页 > 代码库 > Java面试准备之String类专项突破+源码分析

Java面试准备之String类专项突破+源码分析

String的源码中有很多Arrays的方法使用,建议先参阅Arrays的类库

基本介绍:

  String是一个比较特殊的类,有很多种建立的方法。

  如果使用传统的构造方法比如 String s = new String("字符串");这时的对象会在堆上分配,这时候比较两个字符串地址就不相等,而用""双引号包起来的内容会在常量池中做停留,这时如果有两个内容一样的地址就一样了。

  因此,使用==来比较字符串是不靠谱的。

 

  String类还实现了三个接口:Serializable, CharSequence, Comparable<String>。

  serializable只是可序列化的标记,不用去管它。

  CharSequence这个接口为String提供了三个个很重要的方法:

    charAt(int index),可以返回索引的值

    length(),返回字符串序列长度

      subSequence(int start,int end),看名字就明白了,返回一个子序列

   comparable是相当重要的一个接口了(看它的子类就知道了),作用这里搬运以下JavaDOC中的原文。

    作用:此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。

    这个接口可以实现集合或者数组的排序,自然地,字符串的排序也少不了它。

    只有一个compareTo()来实现。

类库使用:

   Java中每个类的类库中的方法实在是太多了,在此不想做一个简单的罗列,我们尽量按照设计一个类的思考方式去熟悉一些方法,再配合源码的解析,应该会理解的比较清楚。

  假设,我们是Java语言的设计者(当然不是那么正规的),现在,我们已经给String这个类实现了三个接口,那么第一件事,肯定是重写这些接口了。

  把握String本质还是char型数组的原则,

    charAt(int index)方法被重写成了一个获取数组中第index个字符的方法

    length()方法就返回了数组的长度,这时候记忆两个"length"就很容易了,String调用的是一个方法所以是length(),而这个方法中又调用了数组的一个属性length

    subSequence()方法被重写成调用了subString方法,而在subString方法中进行一系列边界检查之后,调用了一个构造方法,最后调用了Arrays.copyOfRange()方法

    compareTo是最复杂的一个,它实现了两个字符串的比较。它循环比较了第一个不同的字符,并返回他们的差值,如果都相同则返回0。这个方法对外来看就是本字符串字典顺序小于被比较的字符串,返回  一个小于0的数,反之返回大于0的数;

    
 1  public int compareTo(String anotherString) { 2         int len1 = value.length; 3         int len2 = anotherString.value.length; 4         int lim = Math.min(len1, len2); 5         char v1[] = value; 6         char v2[] = anotherString.value; 7  8         int k = 0; 9         while (k < lim) {10             char c1 = v1[k];11             char c2 = v2[k];12             if (c1 != c2) {13                 return c1 - c2;14             }15             k++;16         }17         return len1 - len2;18     }
View Code

 

  现在,我们实现了所有接口方法,该干一点Sting自己的事了

    首先是构造方法,在此不再赘述,但是大量的构造方法用到了Arrays.copy()这个静态方法。

    然后应该是判定了:

      是否为空:isEmpty()

      是否以特定字符串开头或结尾:startWith(),endWith()

      是否包含某字符串:contains(CharSequence s),注意参数,我们仍可以用String代替

      是否与某个字符串相等: equals(Object),源码中将Object转换为String之前,使用了instanceof判断此Object是不是String类型的,避免了抛出异常。

      是否与某个字符串相等(不考虑大小写):equalsIgnoreCase(),基本所有的不考虑大小写的用法都这么加一个后缀

    再然后应该是拆分,合并:

      替换:替换字符:replace(char old, char new)

         替换字符串:replace(CharSequence target, CharSequence replacement)

         替换所有字符串,但是第一个参数是一个正则表达式:replaceAll(String regex, String replacement)

         替换第一个字符串,但是第一个参数是一个正则表达式:replaceFirst(String regex, String replacement)

      分割:按照指定的正则表达式拆分字符串,返回值是一个字符串数组:split(String regex)

         返回一个子字符串:substring(int beginIndex, int endIndex)

         忽略前后的空白:trim()

      合并: 将指定字符串连接到此字符串的结尾:concat(String str)

      转换:将数组转换成字符串:copyValueOf(char[] data)

         将字符串转换成数组:toCharArray()

         大小写转换:toLowerCase(),toUpperCase()

         将各种类型转换成字符串:各种valueOf(Any b)