每天学一点之字符串真不难

字符串常用API

一、字符串的特点

  1. 字符串不可变。这种不可变性是通过内部的private final char[]字段,以及没有任何修改char[]的方法实现的。修改一个字符串变量值,相当于新生成一个字符串对象。
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
  1. private final char value[];也是字符串对象的内部存储形式。

JDK1.9之前有一个char[] value数组,JDK1.9之后byte[]数组

例如: 
String str = "abc";

相当于: 
char data[] = {'a', 'b', 'c'};     
String str = new String(data);
// String底层是靠字符数组实现的。
  1. 字符串字面量也是一个String类的实例,存储在字符串常量池中,相同的字符串字面量表示的对象在内存中只有一份。
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
// 内存中只有一个"abc"对象被创建,同时被s1和s2共享。
  1. 字符串String类型本身是final声明的,不能继承String,也不能去重写他的方法。

二、构造字符串对象

  1. 使用构造方法
  • public String() :初始化新创建的 String对象,以使其表示空字符序列。
  • String(String original): 初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。使用这种方式如果前面没有声明一个相同的字符串会产生两个对象。

例:new String(“abc”)会在常量池生成一个,然后在堆空间new一个一样的字符串

  • public String(char[] value) :通过当前参数中的字符数组来构造新的String。
  • public String(char[] value,int offset, int count) :通过字符数组的一部分来构造新的String。
  • public String(byte[] bytes) :通过使用平台的默认字符集解码当前参数中的字节数组来构造新的String。
  • public String(byte[] bytes,String charsetName) :通过使用指定的字符集解码当前参数中的字节数组来构造新的String。

代码示例:

//字符串常量对象,推荐
String str = "hello";

// 无参构造,不推荐
String str1 = new String();

//创建"hello"字符串常量的副本,不推荐
String str2 = new String("hello");

//通过字符数组构造
char chars[] = {'a', 'b', 'c','d','e'};     
String str3 = new String(chars);
String str4 = new String(chars,0,3);

// 通过字节数组构造
byte bytes[] = {97, 98, 99 };     
String str5 = new String(bytes);
String str6 = new String(bytes,"GBK");
  1. 使用"+"
    任意数据类型与"字符串"进行拼接,结果都是字符串
        Student stu = new Student();
		String s2 = stu + "";//自动调用对象的toString(),然后与""进行拼接,如果Student类没有重写toString方法,则输出的是地址值。
		System.out.println(s2);

三、字符串的常用方法

  1. 基本操作
    (1)boolean isEmpty():字符串是否为空
    (2)int length():返回字符串的长度
    (3)String concat(xx):拼接,等价于+
    (4)boolean equals(Object obj):比较字符串是否相等,区分大小写
    (5)boolean equalsIgnoreCase(Object obj):比较字符串是否相等,不区分大小写
    (6)int compareTo(String other):比较字符串大小,区分大小写,按照Unicode编码值比较大小
    (7)int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
    (8)String toLowerCase():将字符串中大写字母转为小写
    (9)String toUpperCase():将字符串中小写字母转为大写
    (10)String trim():去掉字符串前后空白符

  2. 查找
    (11)boolean contains(String xx):是否包含xx
    (12)int indexOf(String xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1
    (13)int lastIndexOf(String xx):从前往后找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1
    (13)int indexOf(String xx, int from ):从from位置开始找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1

  3. 字符串截取
    (14)String substring(int beginIndex) :返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
    (15)String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。

案例:查看字符串中包含几个符合要求的字符串

public class StringTest {
    public static void main(String[] args) {
        String s = "好好学习,天天向上,每天写一写,记一记,每天都能进步一点点,加油,祝你我都能找到好工作!";
        String s1 = "写一写";
        int i = countNum2(s, s1);
        System.out.println(i);

    }

    public static int countNum(String s, String s1) {
        int count = 0;
        int index = 0;
        while ((s.indexOf(s1, index)) != -1) {
            index = s.indexOf(s1, index) + s1.length();
            count++;
        }

        return count;
    }

    public static int countNum1(String s, String s1) {
        int count = 0;
        for (int i = 0; i < s.length(); i++) {
            int i1 = s.indexOf(s1);
            if (i1 != -1) {
                i1 += s1.length();
                s = s.substring(i1);
                count++;
            }
        }
        return count;

    }
    public static int countNum2(String s,String s1){
        int count =0;
        char[] chars = s.toCharArray();
        char[] chars1 = s1.toCharArray();
        for (int i = 0; i < s.length();) {
            if(chars[i]==chars1[0]){
                if(chars[i+1]==chars1[1]){
                    if(chars[i+2]==chars1[2]){
                        count++;
                        i+=s1.length();
                    }
                }
            }
            i++;
        }

        return count;
    }
}
  1. 和字符相关
    (16)char charAt(index):返回[index]位置的字符
    (17)char[] toCharArray(): 将此字符串转换为一个新的字符数组返回
    (18)String(char[] value):返回指定数组中表示该字符序列的 String。
    (19)String(char[] value, int offset, int count):返回指定数组中表示该字符序列的 String。
    (20)static String copyValueOf(char[] data): 返回指定数组中表示该字符序列的 String
    (21)static String copyValueOf(char[] data, int offset, int count):返回指定数组中表示该字符序列的 String
    (22)static String valueOf(char[] data, int offset, int count) : 返回指定数组中表示该字符序列的 String
    (23)static String valueOf(char[] data) :返回指定数组中表示该字符序列的 String

  2. 编码与解码
    (24)byte[] getBytes():编码,把字符串变为字节数组,按照平台默认的字符编码进行编码
    byte[] getBytes(字符编码方式):按照指定的编码方式进行编码
    (25)new String(byte[] ) 或 new String(byte[], int, int):解码,按照平台默认的字符编码进行解码new String(byte[],字符编码方式 ) 或 new String(byte[], int, int,字符编码方式):解码,按照指定的编码方式进行解码

  3. 开头与结尾
    (26)boolean startsWith(xx):是否以xx开头
    (27)boolean endsWith(xx):是否以xx结尾

  4. 正则匹配
    boolean matches(正则表达式):判断当前字符串是否匹配某个正则表达式

  5. 替换
    (29)String replace(xx,xx):不支持正则
    (30)String replaceFirst(正则,value):替换第一个匹配部分
    (31)String repalceAll(正则, value):替换所有匹配部分

    @Test
     public void test4(){
     	String str = "hello244world.java;887";
     	//把其中的非字母去掉
     	str = str.replaceAll("[^a-zA-Z]", "");
     	System.out.println(str);  //helloworldjava
     }
    
  6. 拆分
    (32)String[] split(正则):按照某种规则进行拆分

String str = "Hello World java atguigu";
		String[] all = str.split(" ");

四、字符串对象的内存分析

@Test
	public void test02(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = s1 + "world";//s4字符串内容也helloworld,s1是变量,"world"常量,变量 + 常量的结果在堆中
		String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是变量,变量 + 变量的结果在堆中
		String s6 = "hello" + "world";//常量+常量,编译期经过优化,跟s3完全相同的情况。
		
		System.out.println(s3 == s4);//false
		System.out.println(s3 == s5);//false
		System.out.println(s3 == s6);//true
	}	
@Test
	public void test03(){
		final String s1 = "hello";
		final String s2 = "world";
		String s3 = "helloworld";
		final String s7=new String("world");
		
		String s4 = s1 + "world";//s4字符串内容也helloworld,s1是常量,"world"常量,常量+ 常量 结果在常量池中
		String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是常量,常量+ 常量 结果在常量池中
		String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
		String s8=s7+s1;//s7是new出来的在堆内存中,最终不是同一个地址。
		
		System.out.println(s3 == s4);//true
		System.out.println(s3 == s5);//true
		System.out.println(s3 == s6);//true
		System.out.println(s3 == s8);//false
	}
@Test
	public void test04(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = (s1 + "world").intern();//如果常量池已经有“helloworld”,直接返回,否则把拼接结果的引用放到常量池中
		String s5 = (s1 + s2).intern();
		
		System.out.println(s3 == s4);//true
		System.out.println(s3 == s5);//true
	}

在这里插入图片描述

结论:

  • 常量+常量:结果是常量池
  • 常量与变量 或 变量与变量:结果是堆
  • intern方法有jvm版本的区别,这里不再深入分析,jdk8中执行原理是如果字符串常量池有内容相同的字符串则直接返回,否则把堆中创建的字符串引用放入字符串常量池,返回此引用,jdk8之前是常量池中没有则把值(而不是地址值)复制到常量池。总之所有版本都是通过字符串常量池返回的内容。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力奋斗的JAVA小余

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值