Java基础—String类

一、String类

1.概述
1)字符串解读
String s1 = "abc"; s1是一个类类型变量,"abc"是一个对象。只要在""里的,都是对象。字符串最大的特点在于,一旦初始化,就不可以改变。字符串,既是对象,又是常量。

示例:
String s1 = "abc";
s1 = "kk";
System.out.println(s1);

输出结果为:kk
变化的不是"abc"这个对象,而是s1这个引用;重新赋值后,s1指向了"kk"这个对象。

2)字符串创建方式的区别

高能:
String s1 = new "abc";
String s2 = new String("abc");
s1和s2的区别在于,s1有一个对象,s2有两个对象。s2中,new是一个对象,"abc"是一个对象。

小扩展
字符串在内存中有常量池,该常量池是一个数组,用于存储'a','b','c'这样的字符;字符串由字符组成,如果常量池中有'a','b','c','d','e','f'这些字符,下次创建String s3 = "abf";的时候,虚拟机会到常量池中找到这三个字符,拼接起来。

3)String类的equals()方法
String类复写了Object类中的equals()方法,该方法用于判断字符串是否相同。

示例:
String s1 = new "abc";
String s2 = new String("abc");
System.out.println(s1.equals(s2));

输出:true

4)String的“==”操作符比较

示例代码:

class StringCompare {
    public void main(String[] args) {
        String s1 = "abc";
        String s2 = new String("abc");
        String s3 = "abc";
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
    }
}

输出结果为:

false
true

字符串储存在常量池当中,当s1创建的时候,"abc"对象已经在内存中存在了;那么,当s3创建的时候,如果常量池中已经有"abc"字符串的字符,就不会再创建对象,而直接让s3指向"abc"这个对象。
2.String类中的方法
String类是用于描述字符串这个事物。其常见的方法有:
1)获取操作
1> 获取字符串长度:int length()
2> 获取指定位置上的字符:char charAt(int index)
3> 获取指定字符的位置有如下方法:

a.int indexOf(int ch):获取指定字符第一次出现的位置
b.int indexOf(int ch, int fromIndex):获取指定字符从fromIndex位置开始,第一次出现的位置
c.int indexOf(String str):获取子字符串第一次出现的位置,也可以用于判断字符串是否包含指定字符串
d.int indexOf(String str, int fromIndex):获取子字符串从fromIndex位置开始,第一次出现的位置
e.int lastIndexOf(char ch):反向查找指定字符

2)判断操作
1> 字符串中是否包含子字符串:boolean contains(CharSequence s)
2> 字符串是否长度为零:boolean isEmpty(String str)
3> 字符串是否以指定字符串开头:boolean startsWith(String str)
4> 字符串是否以指定字符串结尾:boolean endsWith(String str)

3)转换操作
1> 将字符数组转换成字符串:
>a.构造方法:
String(char[] ch):将字符数组转换成字符串
String(char[] ch, int offset, int count):将字符数组的一部分转换成字符串
b.静态方法:
static String copyValueOf(char[] ch):将字符数组转换为字符串
static String copyValueOf(char[] ch, int offset, int count):将字符数组的一部分转换成字符串
static String ValueOf(char[] ch) :将字符数组转换为字符串

2> 将字符串转换成字符数组:char[] toCharArray()
3> 将字节数组转换成字符串:
>String(byte[] ch)
String(byte[] ch, int offset, int count):将字节数组的一部分转换成字符串

4> 将字符串转换成字节数组:

byte[] getBytes()

注意:字符串和字节数组在转换过程中,可以指定编码表。

5> 将基本数据类型转换成字符串
>static String ValueOf(int)
static String ValueOf(double)

4)替换操作
1> 将子字符替换成目标字符:String replace(char oldChar, char newChar) //如果被替换数组不存在,返回原字符串
2> 将子字符串替换成目标字符串:String replace(CharSequence target, CharSequence replecement)

5)切割操作
1> 切割字符串:String[] split(Reg reg)

6)获取子串
1> 获取字符串中的子字符串:

String substring(int beginIndex)
String substring(int beginIndex, endIndex) //不存在的下标会出现字符串下标越界异常

7)去除空格,大小写转换,字符串比较大小
1> 字符串大小写转换
>String toUpperCase()
String toLowerCase()

2> 去除字符串两端多余空格:String trim()
3> 两个字符串比较大小:int compareTo(String string)

8)字符串方法代码示例:

package com.heisejiuhuche.String;

public class StringAPI {
    private static String str = "abcaaddefggut";

    public static void main(String[] args) {
//        get();
//        is();
        trans();
        replace();
        split();
        sub();
        other();
    }

    private static void get() {
        //获取长度
        print(str.length());
        //根据索引获取字符
        //下标越界会产生异常
        print(str.charAt(7));
        //根据字符获取索引
        //找不到目标字符返回-1
        print(str.indexOf('a', 1));
        //反向查找
        print(str.lastIndexOf('e'));
    }

    private static void is() {
        String str = "ExceptionTest.java";
        //判断是否以Exception开头
        print(str.startsWith("Exception"));
        //判断是否以.java结尾
        print(str.endsWith(".java"));
        //判断是否包含Test
        print(str.contains("Test"));
        //判断长度是否为0
        print(str.isEmpty());
    }

    private static void trans() {
        char[] ch = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
        //字符数组转字符串
        String str = new String(ch, 2, 3);
        print(str);

        String s1 = "zmsdjlfjxlk";
        //字符串转字符串数组
        char[] cha = s1.toCharArray();
        for(int x = 0; x < cha.length; x++) {
            print("ch= " + cha[x]);
        }
    }

    private static void replace() {
        String s1 = "hello java";
        //替换目标字符
        String s2 = s1.replace('a', 'n');
        print(s2);
        //替换目标字符串
        String s3 = s1.replace("java", "world");
        print(s3);
    }

    private static void split() {
        String s1 = "zhangsan, lisi, wangwu";
        //切割字符串
        String[] arr = s1.split(",");
        for(int x = 0; x < arr.length; x++) {
            print(arr[x]);
        }
    }

    private static void sub() {
        String s1 = "abcdefg";
        //获取子字符串
        print(s1.substring(2));
        print(s1.substring(2, 4));
    }

    private static void other() {
        String s1 = "     Hello Java     ";
        //转小写
        print(s1.toUpperCase());
        //转大写
        print(s1.toLowerCase());
        //去除两端空格
        print(s1.trim());
        String s2 = "acc";
        String s3 = "aaa";
        //字符串比较大小
        print(s2.compareTo(s3));
    }

    private static void print(Object obj) {
        System.out.println(obj);
    }
}

3.String类练习
1)模拟trim()方法
写一个trim()方法的模拟方法,去除字符串两端的空格,返回去除空格后的字符串。

示例代码:

package com.heisejiuhuche.String;

/**
 * 模拟trim()方法,去除字符串两端空格
 * @author jeremy
 *
 */

public class StringTest1 {
    public static void main(String[] args) {
        String string = "      abc def g hi      ";
        print("(" + string + ")");
        string = myTrim(string);
        print("(" + string + ")");
    }

    private static String myTrim(String string) {
        int start = 0;
        int end = string.length() - 1;

        //如果从下标0开始的字符为空格,则继续往后检查,直到字符不为空格
        while(start <= end && (string.charAt(start) == ' ')) {
            start++;
        }

        //如果从字符串结尾开始检查,字符为空格,则继续倒序检查,直到字符不为空格
        while(start <= end && (string.charAt(end) == ' ')) {
            end--;
        }

        //返回院字符串的子字符串,注意end要+1,不然丢失最后一个字符
        return string.substring(start, end + 1);
    }

    private static  void print(Object obj) {
        System.out.println(obj);
    }
}

程序输出结果:

(      abc def g hi      )
(abc def g hi)

2)反转字符串
将任意字符串反转输出。

示例代码:

package com.heisejiuhuche.String;

public class StringTest2 {
    public static void main(String[] args) {
        String string = "   abcd efg hi     ";
        print("(" + string + ")");
        string = reverseString(string);
        print("(" + string + ")");
    }

    /* 反转字符串 */
    private static String reverseString(String string) {
        char[] ch = string.toCharArray();
        reverse(ch);
        string = new String(ch);
        return string;
    }

    /* 反转数组 */
    private static void reverse(char[] ch) {
        for(int start = 0, end = ch.length - 1; start < end; start++, end--) {
            swap(ch, start, end);
        }
    }

    /* 交换元素 */
    private static void swap(char[] ch, int start, int end) {
        char tmp = ch[start];
        ch[start] = ch[end];
        ch[end] = tmp;
    }

    private static  void print(Object obj) {
        System.out.println(obj);
    }
}

程序输出结果:

(   abcd efg hi     )
(     ih gfe dcba   )

3)反转指定字符串
将任意字符串中的指定部分反转输出。

示例代码:

package com.heisejiuhuche.String;

public class StringTest3 {
    public static void main(String[] args) {
        String string = "   abcd efg hi     ";
        print("(" + string + ")");
        string = reverseString(string);
        print("(" + string + ")");
    }

    /* 反转字符串 */
    private static String reverseString(String string) {

        return reverseString(string, 5, 9);
    }

    /* 反转指定字符串 */
    private static String reverseString(String string, int start, int end) {
        char[] ch = string.toCharArray();
        reverse(ch, start, end);
        string = new String(ch);
        return string;
    }

    /* 反转数组 */
    private static void reverse(char[] ch, int x, int y) {
        for(int start = x, end = y - 1; start < end; start++, end--) {
            swap(ch, start, end);
        }
    }

    /* 交换元素 */
    private static void swap(char[] ch, int start, int end) {
        char tmp = ch[start];
        ch[start] = ch[end];
        ch[end] = tmp;
    }

    private static  void print(Object obj) {
        System.out.println(obj);
    }
}

程序输出结果:

(   abcd efg hi     )
(   abe dcfg hi     )

4)获取一个字符串在另一个字符串中出现的次数

示例代码:

package com.heisejiuhuche.String;

public class StringTest4 {
    public static void main(String[] args) {
        String str = "kkabkkckkdkkefkkskkdddddkk";
        System.out.println(getSubCount2(str, "kk"));
    }

    /* 方法一,使用indexOf(String str)方法 */
    private static int getSubCount(String str, String key) {
        int count = 0;
        int index = 0;

        /*在str中寻找key,能找到,就继续往后找,index记录每次找到key的下标
        下标加上key的长度,就是剩下字符串的起始位置,截取剩下的字符串
        然后在剩下的字符串里继续寻找key,直到indexOf()方法返回-1
        最后返回count */
        while((index = str.indexOf(key)) != -1) {
            str = str.substring(index + key.length());
            count++;
        }
        return count;
    }

    /*方法二,使用indexOf(String str, int fromIndex)方法,较高效 
     * index记录找到key的下标位置,加上key的长度,就是下一次应该开始寻找的下标
     * 让indexOf()方法直接从这个位置开始寻找即可*/
    private static int getSubCount2(String str, String key) {
        int count = 0;
        int index = 0;

        while((index = str.indexOf(key, index)) != -1) {
            index += key.length();
            count++;
        }
        return count;
    }
}

程序输出结果:

7

5)获取两个字符串中最大相同子串
在字符串"sdwrtuiohellojavacbsdwrtwtwhdfh";和"dsewrwhellojavadcwry";中,输出最大相同子串,即hellojava

示例代码:

package com.heisejiuhuche.String;

/**
 * 1.先确定较短的字符串;在长字符串中搜索整个较短的字符串;
 * 2.如果没有匹配,就将较短的字符串长度-1;
 * 3.长度-1之后的较短字符串有两种情况,末尾减少一个字符,和首部减少一个字符的情况;
 * 4.用substring()方法得到这两个字符串;这个过程,就是先取0到较短字符串长度-1的子串
 *       再取首尾下标都自增1之后的子串;
 * 5.以此类推,如果这两个子串还是没有在较长字符串中找到匹配,就将较短字符串的长度-2;
 * 6.再通过取子串的过程,得到3个子串(0到较短的长度-2,然后下标自增,即1到较短的长度-1,
 *   然后下标再自增,即2到较短的长度),直到尾部下标等于较短字符串长度为止;
 * 7.每次截取字符串,都判断这个子串是否能在较长字符串中匹配;
 * 8.外层循环控制循环次数(循环较短字符串的长度次),内循环控制每次要截取的子串个数,并进行匹配
 *   匹配上,返回该子串,匹配不上返回空字符串
 * @author jeremy
 *
 */

public class StringTest5 {
    public static void main(String[] args) {
        String s1 = "sdwrtuiohellojavacbsdwrtwtwhdfh";
        String s2 = "dsewrwhellojavadcwry";
        System.out.println(getMaxSubString(s2, s1));
    }

    private static String getMaxSubString(String s1, String s2) {
        String longer;
        String shorter;

        //如果s1长于s2,longer等于s1
        longer = (s1.length() > s2.length()) ? s1 : s2;
        //如果longer等于s1,那么s2较短
        shorter = (longer == s1) ? s2 : s1;

        for(int x = 0; x < shorter.length(); x++) {
            for(int y = 0, z = shorter.length() - x; z != shorter.length() + 1; y++, z++) {
                String tmp = shorter.substring(y, z);
                if(longer.contains(tmp)) {
                    return tmp;
                }
            }
        }
        return "";
    }
}

程序运行结果:

hellojava

二、StringBuffer类

1.定义
StringBuffer是一个字符串缓冲区,是一个容器。

2.StringBuffer的特点
1)长度可变;
2)可以用于对字符串进行修改;
2)可以直接操作多个数据类型;
3)最终通过toString()方法输出字符串

3.StringBuffer的功能
1> 存储功能
-StringBuffer append():将指定的数据作为参数添加到已有数据的结尾处

示例代码:

StringBuffer sb = new StringBuffer();
sb.append("3").append("sdjfkd").append(sdjfkd);

代码输出:3sdjfkdsdjfkd

高能:
连续调用append()方法的现象叫做方法调用链;因为append()方法返回一个StringBuffer对象,对象还能调用本类方法。

-StringBuffer insert(int offset, String str):在指定位置插入字符串

示例代码:

StringBuffer sb = new StringBuffer();
sb.append("3").append("sdjfkd").append(true);
sb.insert(1, "qq");

代码输出:3qqsdjfkdsdjfkd

注意:
如果插入的下标不存在,会出现字符串下标越界异常。

2> 删除功能
-StringBuffer delete(int start, int end):删除从start开始到end(不包含)技术的字符串

示例代码:

StringBuffer sb = new StringBuffer("abcde");
sb.delete(1, 3);

代码输出:ade

-StringBuffer deleteCharAt(int index):删除指定位置的字符串

示例代码:

StringBuffer sb = new StringBuffer("abcde");
sb.deleteCharAt(2);

代码输出:abde

3> 获取功能

-char charAt(int index):通过下标获取字符
-int indexOf(String str):获取目标字符串出现的第一个位置
-int lastIndexOf(String str):反向查找目标字符串出现的第一个位置
-int length():获取字符串长度
-String substring(int start, int end):获取子串

4> 修改功能
-StringBuffer replace(int start, int end, String str):将从start开始到end(不包含)结束的字符串替换为目标字符串

示例代码:

StringBuffer sb = new StringBuffer("abcde");
sb.replace(1, 4, "java");

代码输出:ajavae
-void setCharAt(int index, char ch):将下标所在字符替换成目标字符

示例代码:

StringBuffer sb = new StringBuffer("abcde");
sb.setCharAt(2, 'k');

代码输出:abkde
-StringBuffer reverse():反转字符串
-void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin):将缓冲区中的指定数据存储到指定数组的指定位置

示例代码:

StringBuffer sb = new StringBuffer("abcdef");
char[] ch = new char[6];
sb.getChars(1, 4, ch, 1);
for(int x = 0; x < ch.length; x++) {
    System.out.println(ch[x]);
}

代码输出:

ch[0] = 
ch[1] = b
ch[2] = c
ch[3] = d
ch[4] = 
ch[5] = 

三、StringBuilder类

1.定义
StringBuilder是一个可变的字符序列,与StringBuffer功能相同,是StringBuffer的一个简易替换。

2.与StringBuffer的区别
StringBuffer是线程同步的,而StringBuilder不同步,其在多线程情况下会出现安全问题。

3.开发建议
StringBuilder始于JDK5.0,叫StringBuffer而言是一个更新的类。JDK的升级无外乎提升效率,简化代码,提高安全性。StringBuilder的出现提高了代码运行效率。实际开发中,建议使用StringBuilder;需要同步的时候,由开发者自行加锁,解锁。

四、基本数据类型包装类

1.定义
Java视一切为对象,包括基本数据类型。八种基本数据类型对应着八种基本数据类型的包装类。包装类中定义了一些列操作基本数据类型的方法和属性,便于开发者使用。

2.包装类的意义
一个int型的数据,有自己的取值范围,有自己的表现形式,这些相当于是int类型数据的属性;如何将一个int型数据转换为其他进制的表现形式,只有int类型数据自己最清楚。如果将int类型数据封装为类,在类中定义进制转换的方法,这样操作int类型数据就会很方便。

3.包装类的应用
包装类通常用于基本数据类型和字符串之间做转换。
1)基本数据类型转换成字符串

示例代码:
Integer.toString(34);//将34整数转换为字符串34`

2)字符串转换成基本数据类型

示例代码:
Integer.parseInt("34");//将字符串34转换为整数34

注意:
-包装类Character没有parse方法,因为其本身就是字符;
-在字符串转换为基本数据类型时,传入了字符,会出现数字格式异常

3)字符串进制表现形式转换成十进制数

示例代码:
Integer.parseInt("110", 2);//将字符串110作为二进制数转为十进制整数,结果为6
Integer.parseInt("3c", 16)//结果为60

小扩展
将字符串"123"转换成int类型数据的另一种方法:
Integer i = new Integer("123");
int num = i.intValue();//非静态方法

4)数字比较:int compareTo(Integer anotherInteger)

4.包装类新特性
1)JDK5.0版本之后,基本数据类型引入了自动装箱,自动拆箱的概念,以简化代码。

示例代码:

Integer x = new Integer(4);//这行代码相当于
Integer x = 4;//自动装箱,4是Integer对象
x += 2;//可以直接进行运算,先将x自动拆箱,变为int类型,再进行运算,最后将和自动装箱

注意:
-自动拆箱的原理是,先执行了x.intValue();得到x的int类型数据,再进行运算;
-如果声明x为Integer引用,其值可以被赋为空(null);此时如果再进行算数运算,会出现空指针异常;因为自动拆箱时,需要调用intValue()方法,而x = null;程序出错

前方高能:Integer取值范围(面试用)

示例代码:
Integer m = 128;
Integer n = 128;
System.out.println("m == n: " + (m == n));

代码输出:false

示例代码:
Integer a = 127;
Integer b = 127;
System.out.println("a == b: " + (a == b));

代码输出:true

因为a和b指向同一个Integer对象。当数值在byte范围内时,如果该数值已经存在,包装类新特性就不会再开辟新的内存空间。