String 字符串基本使用

Java框架

浏览数:83

2019-6-27


一、JavaDoc解释

  1. String类表示字符串,所有Java程序中的字符串像是”abc”都是此类的实例,字符串是恒定的,不可变的,字符串的值一旦创造就不能被更改,字符串缓冲区支持可变

  2. 因为String对象是不可变的,所以能够被共用

     String str = "abc";
     // 等同于
     char[] data = {'a','b','c'};
     String str = new String(data);
  3. 一些示例说明字符串为什么不可变

        System.out.println("abc");
       String cde = "cde";
       System.out.println("abc" + cde);
       String c = "abc".substring(2,3);
       String d = cde.substring(1, 2);
  4. Java语言对string提供了特殊的支持像是 ” + “的连接操作和转换其他对象到字符串,字符串连接实现了StringBuffer 和 StringBuilder的append 方法string类型的转换也是实现了Object.toString()方法,并且被Java中所有的类继承

  5. 除非有另外说明,否则将null传递给构造函数或者方法会导致NullPointerException

二、基础属性和构造函数

介绍完JavaDoc官网对String的简单用法外,下面来介绍一下String内部有哪些属性和构造函数

基本属性

    // 该值用于字符存储
    private final char value[];

String是个字符串,字符串是一串字符的拼接,这是一个char数组,用来存储每一个字符序列

    // 缓存字符串的哈希码
    private int hash; // Default to 0

每生成一个字符串都会对应生成一个字符串的哈希编码

构造函数

String的构造函数有很多,下面对主要的构造函数进行介绍

  • String支持几类构造函数,将创建空String的构造函数称为默认的构造函数
    // 初始化一个新创建的String实例,能够代表一个空的字符序列。
  // 注意使用这个构造器不是必要条件,因为字符串是不可变的。
    public String() {
        this.value = "".value;
  }

eg:

    String s = new String();
  • 通常希望创建含有初始值的字符串。 String类提供了各种构造函数来完成这项功能。使用如下的构造函数可以创建一个被字符数组初始化的字符串
    // 分配一个新的字符串,使其能够代表包含字符类型参数的字符串序列。
  // 这个字符串的内容是一份副本随后的修改,字符数组不会影响新创建的字符串
    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
  }

eg:

    char[] chars = {'a','b','c'};
    String s = new String(chars);
  • 使用下面的构造函数可以指定字符数组的一个子区域作为初始化值。
        
        /*
        * 分配一个新的String包括新的字符数组参数,offset参数是字符数组的第一个字符,count是
    * 数组字符的指定长度,
    */
    public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count <= 0) {
            if (count < 0) {
                throw new StringIndexOutOfBoundsException(count);
            }
            if (offset <= value.length) {
                this.value = "".value;
                return;
            }
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

        /*
        * 将指定数组的指定范围复制到新的数组中,索引的范围必须介于0和original.length之间,
    * 包括original.length。
        */
    public static char[] copyOfRange(char[] original, int from, int to) {
        int newLength = to - from;
        if (newLength < 0)
            throw new IllegalArgumentException(from + " > " + to);
        char[] copy = new char[newLength];
        System.arraycopy(original, from, copy, 0,
                         Math.min(original.length - from, newLength));
        return copy;
    }

eg:

        char[] chars = {'a','b','c','d','e','f'};
        String s = new String(chars,2,3);
  • 用下面的构造函数可以构造一个String对象,该对象包括了与另一个String对象相同的字符序列。
        /*
        * 初始化一个新创建的String实例,能够表示相同参数的序列。换句话说,新创建的字符串是参数字符串
        * 的副本,除非需要original的显式副本,注意使用这个构造器不是必要条件因为字符串是不可变的。
        */
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }

eg:

    public class UseOfString {
      public static void main(String[] args) {
          char[] array = {'a','b','c','d','e'};
          String s1 = new String(array);
          String s2 = new String(s1);
          System.out.println("s1 = " + s1);
          System.out.println("s2 = " + s2);
      }
    }
  • 尽管Java的Char类型使用16位(bit)表示Unicode编码字符集,在Internet中,字符串的典型格式使用由ASCII字符集构成的8位字节数组。因为8位ASCII字符串是共同的,当给定一个字节(byte)数组时,String类提供了初始化字符串的构造函数。
    
        /*
        * 通过解码指定的字节数组构造一个新的String对象,新的String长度是字符集的一个功能,
    * 因此可能不等于字节数组的长度
    */
    public String(byte bytes[]) {
        this(bytes, 0, bytes.length);
    }

        // 通过解码指定的子数组来构造一个新的String,使用平台默认的字符集。
    public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }

eg:

        
    public class UseOfString {
      public static void main(String[] args) {
          byte[] byteArray = {65,66,67,68,69,70};
          String s1 = new String(byteArray);
          System.out.println("s1 = " + s1);
          String s2 = new String(byteArray,2,3);
          System.out.println("s2 = " + s2);
      }
    }

字节-字符串转换的扩展版本也有定义,使用该版本,你可以指定实现字节-字符串转换的字符编码方式。不过,大多数情况下,一般会选择操作平台提供的默认编码。

三、基本方法说明

1. 字符串长度

字符串的长度是指其所包含的字符的个数。

    public class UseOfString {
        public static void main(String[] args) {
           // 字符串长度
            char[] chars = {'a','b','c','d','e'};
            String s = new String(chars);
            System.out.println("s = " + s.length());
        }
    }

2. 字符串连接

  • 上面创建字符串的方式都是通过String的构造函数来创建,String也能像基本数据类型一样赋值
    String s = "abc";
    System.out.println("s = " + s);
  • 通常,Java不允许对字符串进行操作,但是使用” + “是个例外,” + ” 可以连接两个字符串,产生一个String对象,也可以使用一连串的字符串+进行运算
    public class UseOfString {
        public static void main(String[] args) {
            String age = "9";
            String s = "He " + "is " + age + "years old ";
            System.out.println(s);
        }
    }
  • 字符串连接的实际使用时当一个字符串的长度很长的时候,可以将他拆开,使用” + “将它们连接起来
        
    public static void main(String[] args) {
        String longStr = "This could have been " +
                "a very long line that would have" +
                "wrapped around. But String concatenation" +
                "prevents this";
        System.out.println(longStr);
    }
  • 字符串与其他数据类型的连接,考虑类型的转换关系
    public static void main(String[] args) {
        int age = 9;
        String s = "He is " + age + " years old";
        System.out.println(s);
     }

第一个例子的age是String类型,第二个例子中age 是int类型,但是产生的结果是一样的,这是因为字符串在使用+号进行连接的时候,会默认把int类型自动的转换为String类型再进行连接,这种转换思想具有普适性,其他数据类型也是如此

但是这种在连接的过程中转换的思想也会产生不如意的结果

        // 字符串拼接
    public static void main(String[] args) {
        String result = "The result 2 + 2 is " + 2 + 2;
        System.out.println(result);
    }

正如上面所说的,String类型和任何类型的相加都会变为String类型的结果,上面程序的运行过程会先执行”The result 2 + 2 is” 加2,得到的结果再加2 ,就会变成The result 2 + 2 is 22

3. 字符串转换

当Java在连接时将字符串转换为其他字符串形式时,它是通过调用一个由字符串(String)定义的字符串转换方法valueOf()的重载方法来完成的。valueOf()方法对所有简单的类型和类型Object重载。对于简单类型的数据,valueOf()方法返回一个字符串,对于对象,valueOf()方法调用toString()方法。

valueOf(boolean) : String

valueOf(char[]): String

valueOf(char): String

valueOf(char[],int,int): String

valueOf(double): String

valueOf(float): String

valueOf(int) : String

valueOf(long) : String

valueOf(Object) : String

每一个类都是执行toString()方法,因为它是由Object定义的方法,然而toString()的很多默认实现方法是不够的,对于大多数所创建的类,通常需要你提供自己重写过的toString()方法。

它的一般形式:

    String toString();

通过对所创建类的toString( )方法的覆盖,允许将得到的字符串完全集成到Java的程序设计环境中。例如它们可以被用于print( )和println( )语句以及连接表达式中。下面的程序中用Box类重载toString( )方法说明了这些。

    public class Box {

        double wight;
        double height;
        double length;

        public Box(double w,double h,double l){
            this.wight = w;
            this.height= h;
            this.length = l;
        }

        @Override
        public String toString() {
            return "Box{" +
                    "wight=" + wight +
                    ", height=" + height +
                    ", length=" + length +
                    '}';
        }
    }
        
    public class UseOfString {
        public static void main(String[] args) {
            Box box = new Box(12,15,20);
            String boxFix = "Box b" + box;
            System.out.println(box);
            System.out.println(boxFix);
        }
    }
    

该程序的输出:

Box{wight=12.0, height=15.0, length=20.0}
Box b = Box{wight=12.0, height=15.0, length=20.0}

正如你所看到的,当Box对象在连接表达式中使用或出现println()表达式的时候,Box的toString()方法能够自动被调用

4. 字符截取

String类提供了很多字符串截取的方法,下面来逐一介绍一下,尽快字符串中的字符不能像字符数组一样能够被索引,许多字符串方法利用下标或偏移对字符进行操作

  • charAt()

方法用于从字符串(String)中截取一个字符。可以通过charAt()方法直接引用单个字符

        char charAt(int where);

这里,where指的是字符串索引的位置,它是非负的,charAt()方法返回指定字符。

    String str = "chars";
    char c = str.charAt(1);
    System.out.println(c);          
  • getChars

如果想一次截取多个字符,可以使用getChars()方法,它有如下一般形式

        void    getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

它的一般用法如下

    public static void main(String[] args) {
        String s = "This is a demo of the getChars method.";
        int start = 10;
        int end = 14;
        char[] buf = new char[end-start];
                
        s.getChars(start,end,buf,0);
        System.out.println(buf);
    }

这里的srcBegin指定了字符串开始的下标,srcEnd指定了字符串结束的下标。因此字符串包含了从srcBegin到srcEnd – 1的字符。dst数组是需要进行存储的数组。dstBegin定义存储数组的起始位置。

  • getBytes()

有一种称为getBytes()的方法,它是实现将字符存放于字节数组的getChars()替代,它使用平台提供的默认字符到字节的转换。下面是它的最简单的形式:

        byte[] getBytes();

它的一般用法如下

        // 演示getBytes()用法
    public static void main(String[] args) {
        String s = "ABCDE";
        byte[] bytes = s.getBytes();
        for(byte b : bytes){
            System.out.print(" b = " + b);
        }
        System.out.println();
    }

输出如下:

b = 65 b = 66 b = 67 b = 68 b = 69

输出的结果是一个个的字节类型。

  • toCharArray()

如果想将字符串对象中的字符转换为一个数组,那么可以使用toCharArray()方法。对应整个字符串,它返回一个字符数组,一般形式为:

    char[] toCharArray();

使用getChars()也能得到相同的结果。

5. 字符串比较

String类包括了几个用于比较字符串或字符串内字符串的比较方法

  • equals(Object anObject) 和 equalsIgnoreCase(String anotherString)
    • equals(Object anObject)方法用于比较两个字符串的值是否相同
    • equalsIgnoreCase(String anotherString)方法用于比较两个字符串的值是否相同,不区分大小写,也就是说a – z 与 A – Z的比较是相同的。
    // 演示字符串的比较方法
    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = "Hello";
        String s3 = "HELLO";
        String s4 = "WORLD";
        String s5 = "world";

        System.out.println("s1.equals(s2) = " + s1.equals(s2));
        System.out.println("s1.equals(s3) = " + s1.equals(s3));
        System.out.println("s1.equalsIgnoreCase(s2) = " + s1.equalsIgnoreCase(s2));
        System.out.println("(s1 + s5).equals(s3 + s4) = " +
                (s1 + s5).equalsIgnoreCase(s3 + s4));
    }
  • regionMatches

regionMatches()方法将一个字符串中指定的区间和另一字符串指定的区间进行比较,它的重载形式允许在比较时忽略大小写

regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
regionMatches(int toffset, String other, int ooffset, int len)

以第二个方法为例:

        // 演示regionMatches()用法
    public static void main(String[] args) {
        String s1 = "He is a good boy";
        String s2 = "He is not a good boy";
        System.out.println(s1.regionMatches(6,s2,10,s1.length()-6));
    }

此示例使用了第二个方法,参数分别表示为 toffset(需要比较字符串的起始位置),other(被比较的字符串),ooffset(被比较字符串的起始位置),len(长度)

  • startsWith() 和 endWith()

字符串定义两个例程,startWith()方法判断一个给定的字符串是否从指定位置开始,endWith()方法判断一个给定的字符串是否从指定位置结束

    public static void main(String[] args) {
        String s = "FooBar";
        System.out.println(s.startsWith("Foo"));
        System.out.println(s.endsWith("Bar"));
    }

还有另外一种形式,是从指定位置处开始索引

        startsWith(String prefix, int toffset)
  • equals() 与 == 比较

理解equals 方法和 == 方法是非常重要的,如何上面解释的一样,equals比较的是字符串中的字符,而==是比较两个对象的引用是否相同,也就是比较两个对象引用看他的是否引用相同的实例。如下面程序

    public static void main(String[] args) {
        String s1 = "Hello";
        String s2 = new String(s1);
        System.out.println("s1.equals(s2) = " + s1.equals(s2));
        System.out.println("s1 == s2 : " + s1 == s2);
    }
  • CompareTo

通常,仅仅知道两个字符串是否相同往往是不够的,对于排序应用来说,还需要知道一个字符与另一个字符之间的关系,是大于,小于还是等于,一个字符串小于另一个指的是它在字典中先出现。而一个字符串大于另外一个指的是在字典中后出现。

        int compareTo(String str);

下面是一个对字符串数组进行排序的例子程序,程序在冒泡排序中使用compareTo()确定排序的顺序:

public class UseOfString {

    static String[] arr = {
            "Now", "is", "the", "time", "for", "all", "good", "men",
            "to", "come", "to", "the", "aid", "of", "their", "country"
    };

      public static void main(String[] args) {
          for(int i = 0;i < arr.length;i++){
              for(int j = i + 1;j < arr.length;j++){
                  if(arr[i].compareTo(arr[j]) > 0){
                      String a = arr[j];
                      arr[j] = arr[i];
                      arr[i] = a;
                  }
              }
              System.out.println(arr[i]);
          }
      }
  }

6. 搜索字符串

String类提供了两个搜索字符串的方法,一个是从第一个字符处开始搜索,另外一个是从最后一个字符处向前搜索。它们的一般形式如下:

    /*
  * 返回第一次出现指定字符处的索引,如果一个字符出现在了一个字符序列中,
    * 那么第一次出现指定字符的索引将被返回。
    */
    indexOf(int ch): 

    /*
    * 从某个起始位置开始,返回出现指定字符的位置
    */
    indexOf(int ch, int fromIndex):

    /*
    * 搜索出现指定字符串的位置
    */
    indexOf(String str):

    /*
    * 从指定位置开始,搜索出现指定字符串的位置
    */
    indexOf(String str, int fromIndex): 

    // lastIndexOf和indexOf的用法很相似
    lastIndexOf(int ch)
    lastIndexOf(int ch, int fromIndex)
    lastIndexOf(String str)
    lastIndexOf(String str, int fromIndex)

一般用法如下

    public static void main(String[] args) {
        String str = "Java is the best Language";
        int charIndex = str.indexOf('a');
        int strIndex = str.indexOf("best");
        System.out.println("strIndex = " + charIndex);
        System.out.println("strIndex = " + strIndex);
    }

注意: indexOf(int ch) 这个方法的参数 ch 可以是数字,也可以是字符类型(char),在搜索指定字符的时候,会将字符转换成为Unicode编码再进行搜索

7. 修改字符串

  • substring()

因为字符串的不可变性,在每当想对字符串进行操作的时候,都需要采用将它复制到StringBuffer或者使用下面方法中的一种,这些方法都将完成一个字符串的拷贝

有两种形式:substring(int beginIndex) 和 substring(int beginIndex, int endIndex)

用法如下

    public static void main(String[] args) {
        String str = "The quick brown fox jumps over the lazy dogs";
        // 从位置为3的地方开始截取字符串
        String s = str.substring(3);
        System.out.println("s = " + s);

        // 从位置为3的地方截取字符串,截止到length() - 1 处。
        s = str.substring(3,str.length()-1);
        System.out.println("s = " + s);
    }

输出:

s = quick brown fox jumps over the lazy dogs
s = quick brown fox jumps over the lazy dog

  • concat()

使用concat()可以连接两个字符串,一般形式如下:

    String concat(String str);

这个方法创建创建一个新的对象,该对象包含调用字符串。而str内容跟在调用字符串的后面。concat()方法与”+”运算符执行相同的功能。

    public static void main(String[] args) {
        String str1 = "Hello";
        String str2 = "World";
        System.out.println("str1.concat(str2) = " + str1.concat(str2));
    }

通过使用concat能够达到和 + 号相同的效果

  • replace()

replace()方法用另外一个字符代替调用字符串中的一个字符的所有值。它的一般形式

    replace(char oldChar, char newChar)

这里的oldChar 是要被替换的字符串,而newChar 是要替换的字符串

例如

    // 替换'u' - > 'o'
    String s = "Hellu".replace('u','o');
  • trim()

trim方法返回一个调用字符串的拷贝,该字符串将位于调用字符串前面和后面的空格删除后的剩余部分

下面是一个例子:

    String s = "    Hello World".trim();

8. 利用valueOf()方法实现数据转换

valueOf()方法将数据的内部格式转换为可读的形式,它是一种静态方法,对于所有内置的类型,在字符串中被重载。以便每一种类型都能被转换成为字符串,valueOf()方法还被类型Object重载,所以创建的任何形式类的对象也可被用做一个参数,下面是它的几种形式:

    valueOf(boolean b)
    valueOf(char c)
    valueOf(char[] data)
    valueOf(char[] data, int offset, int count)
    valueOf(double d)
    valueOf(float f)
    valueOf(int i)
    valueOf(long l)
    valueOf(Object obj)

使用静态方法也是effective Java 中所推崇的一种转换方式。

9. 改变字符串内字符大小写

toLowerCase() 方法将字符串内所有字符从大写转换为小写,而toUpperCase()方法将字符处内所有字符从小写转换为大写。下面是这些方法的一般形式

String toUpperCase()
String toLowerCase()

下面是具体的示例

public class UseOfString {

    public static void main(String[] args) {
        String s = "This is a test";
        System.out.println("Original : " + s);
        String upper = s.toUpperCase();
        String lower = s.toLowerCase();
        System.out.println("Uppercase : " + upper);
        System.out.println("Lowercase : " + lower);
    }
}

程序输出:

Original : This is a test
Uppercase : THIS IS A TEST
Lowercase : this is a test

作者:c旋儿