String

String:

1641529928284

重点概念:

  1. 用来保存字符串,也就是一组字符序列

  2. 字符串用的是Unicode编码,不管是字母还是汉字都占两个字节

  3. 字符串构造器很多

  4. String类实现了Serializable接口【可以串行化,进行网络传输

  5. String类实现了Comparable接口【String对象可以进行比较】

  6. 是一个final类,不能被继承

  7. 底层是实现了一个 char value[]数组**

    • private final char value[];
      
  8. final定义就不能被修改了(地址不可修改

String创建:

1641531713528

  • 两种方式
    • 直接赋值:String s="abc";直接赋值就是在常量池中
    • 调用构造器:String s=new String("ABC");用构造器,会在堆中char数组中保存一个地址指向常量池
public static void main(String[] args) {
    String s1 = new String("abc");
    String s2="abc";
    String s3="abc";
        System.out.println(s2.equals(s3));//T
        System.out.println(s2 == s3);//T
        System.out.println(s1==s2);//F		s1指向的是堆中地址(虽然堆中地址里保存的内容指向常量池,但堆中的地址不等于常量池地址),s2指向常量池中地址
        System.out.println(s3.intern()==s2);//T
        System.out.println(s3.intern()==s1);//F
//        intern:在常量池中如果有这个字符串了就返回一个字符串,如果没有就创建字符串并返回地址
  
        person p1 = new person();
        person p2 = new person();
        System.out.println(p1.name == p2.name);//T,p1和p2指向不同的堆空间,但是里面保存的name是同一个地址都指向同一个常量池,所以相等
    }
    }
}

String的特性:

    public static void main(String[] args) {
//    	  1.创建了几个对象?    两个
//    重新赋值时,s会判断值改变没有,改变的话就重新创建一个对象,s重新指向这个对象,是不是跟前面说的地址不改变冲突?
//        其实并不是,abc的地址确实没有改变,我们只是修改了s指向的地址而已
        String s="abc";
        s="bcd";

//        2.创建了几个对象     一个
//        编译器会帮我做优化 变成==》"abcd"
        String s1="ab"+"cd";

//        3.创建3个,但是
//      ss3创建的时候,执行了3步:stringbuiiler先append:ss1,再append:ss2,最后才和成c并去除多余数据的空间
        String ss1="Hello";
        String ss2="World";
        String ss3=ss1+ss2;
    }
小结:1.字符串的修改,不修改内容,会重新生成一个对象,并重新指向
     2.字符串的拼接和引用的拼接不同,字符串拼接直接再常量池,而引用会经过Stringbuiller会在堆对象里
    

470p图看不懂,class内存不太清晰

1641535787132

String常用方法:

  1. equals //区分大小写,判断内容是否相等
  2. equalslgnoreCase //忽略大小写的判断内容是否相等
  3. length /获取字符的个数,字符串的长度
  4. indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1
  5. lastlndexOf //获取字符在字符串中最后1次出现的索引,索引从开始,如找不到,返回-1
  6. substring //截取指定范围的子串(左闭右开)
  7. trim //去前后空格
  8. charAt:获取某索引处的字符,注意不能使用Str[index]这种方式.
  9. toUpperCase:大写
  10. toLowerCase:小写
  11. concat:拼接
  12. replace替换字符串中的字符,(本身字符串并没有改变,只是返回的结果改变了)
  13. split分割字符串,对于某些分割字符,我们需要转义比如| \等
  14. compareTo //比较两个字符串的大小(继承了Comparable接口)
  15. toCharArray //转换成字符数组
  16. format //占位符,%s字符串%c字符%d整型%.2f浮点型
    public static void main(String[] args) {
// 1. **equals //区分大小写,判断内容是否相等**
        String a1="abccba";
        String a2="abccba";
        String a3="ABcCBA";
        String a4="   avas  ";
        System.out.println("1:  "+a1.equals(a2));;
//2. **equalslgnoreCase //忽略大小写的判断内容是否相等**
        System.out.println("2:  "+a1.equalsIgnoreCase(a3));
//3. **length /获取字符的个数,字符串的长度**
        System.out.println("3:  "+a1.length());
//4. **indexOf //获取字符在字符串中第1次出现的索引,索引从0开始,如果找不到,返回-1**
        System.out.println("4:  "+a1.indexOf("c"));
//5. **lastlndexOf //获取字符在字符串中最后1次出现的索引,索引从开始,如找不到,返回-1**
        System.out.println("5:  "+a1.lastIndexOf("a"));
//6. **substring //截取指定范围的子串**
        System.out.println("6:  "+a1.substring(2));
        System.out.println(":  "+a1.substring(2,4));
//7. **trim //去前后空格**
        System.out.println("7:  "+a4.trim());
//8. **charAt:获取某索引处的字符,注意不能使用Str[index]这种方式.**
        System.out.println("8:  "+a1.charAt(2));
//        9. toUpperCase转成大写
        System.out.println("9:  "+a1.toUpperCase());
//10. toLowerCase转成小写
        System.out.println("10:  "+a3.toLowerCase());
//11. concat拼接字符串
        System.out.println("11:  "+a1.concat(a2));
//12. replace替换字符串中的字符
        System.out.println("12:  "+a1.replace('a', 'A'));
//12. split分割字符串,对于某些分割字符,我们需要转义比如| \\等
//        以“,”进行分隔
        String p = "锄禾日当午,汗滴禾下土,谁知盘中餐,粒粒皆辛苦";
      String s[]= p.split(",");//会转成一个数组
        for (int i = 0; i <p.split(",").length ; i++) {
            System.out.println("13:  "+s[i]);
        }
//      分隔文件地址D:\\e\\a
        String p2="D:\\\\e\\\\a";
       String P[]= p2.split("\\\\");//这里需要加上\\转义符,不然报错,为什么要加两个因为你有两个\,所以要有两个转义符\
        for (String s1:P){
            System.out.println("13: "+s1);
        }
//14. compareTo //比较两个字符串的大小.前大正数,后大负数,,相等为0  //相同返回0,不同返回差值
        System.out.println("14:  "+a1.compareTo(a2));
//15. toCharArray //转换成字符数组
        char[] chars = a1.toCharArray();
        System.out.println(chars);
//16. format //占位符(让字符串变得灵活)
//    1、%s,%d,%.2f,%c称为占位符,占位符由后面变量代替
//    2.%s后面由字符串替换
//    3.%d后面由整数替换
//    4.%.2f由小数替换,并只显示小数后两位
//    5.%c由字符替换
       int age=20;
       String js="你好,我叫%d,年龄%s";
       String name="lc";
       String js2=String.format(js,20,name);
        System.out.println(js2);
    }

StringBuffer:

为什么要有StringBuffer?

  • String保存的是字符串常量,前面说过,String类型底层value数组是一个,final修饰的数组,所以每次改变字符串,都会重新生成一个对象再引用,效率低
  • 而StringBuffer保存的是字符串变量,底层是一个value数组,没有final修饰,数组在堆里,每次修改字符串,都只修改数组的内容,再指向常量池,不改变地址,效率高

基础特性:

  1. 直接父类AbstractStringBuilder
  2. 实现了Serializable,可串行化
  3. 父类中的char[] value;,存放我们的内容,不是final
  4. 是一个final类,不能被继承
  5. 因为StringBuffer底层是char[]数组,每次改变不需要每次更换地址(不说每次都要产生新的对象),所以效率高

构造器:

    public static void main(String[] args) {
//        首先会创建一个大小为16的char[]数组
        StringBuffer SB = new StringBuffer();
//        自己指定数组的长度
        StringBuffer SB2=new StringBuffer(100);
//         此时长度为5+16
        StringBuffer SB3=new StringBuffer("Hello");
    }

String和StringBuffer的转换:

  • Stirng==》StringBuffer
  • 放入构造器
  • 用append()
  • StringBuffer==》String
  • tostring()
  • 构造器
    public static void main(String[] args) {
//        Stirng==》StringBuffer
//        放入构造器
        String s="Hello";
        StringBuffer SB = new StringBuffer(s);
//        第二种用append()
        StringBuffer SB2 = SB.append(s);
       
//        StringBuffer==》String
//        第一种tostring
        String s1 = SB.toString();
//        第二种构造器
        String string = new String(SB2);
    }

StringBuffer方法:

  1. append
  2. delete
  3. charAt
  4. indexOf
  5. replace
  6. insert
 public static void main(String[] args) {
        StringBuffer SB = new StringBuffer();
        SB.append("你你好");       //增
        SB.delete(1,2);           //删
        SB.charAt(1);             //查
        SB.indexOf("好");
        SB.replace(0,2,"好的");  //改(替换)
        SB.insert(0,"你也");          //插
        System.out.println(SB);
    }

StringBuilder:

  • 跟StringBuffer API兼容,线程不安全(在单线程中使用),但是要比StringBuffer效率高

总结:

  • String

    • 每一个字符串中汉字和字母都是两个字节

    • String底层是一个final char [] 的一个数组,被fanal修饰,不能修改地址,所以String是一个常量字符串,当被修改时,就会重新生成一个对象,重新指向

    • 实现了Ser接口可以网络传输,实现了comparable重写了比较方法

    • String 自己创建和用构造器创建,直接创建指向常量池,用构造器创建会指向堆里的对象,对象里保存着指向常量池的地址

    • String常用方法:lastindexof,indexof,charat,equals,equal啥,Toup,Tolow,substring,split,format,comparto(实现接口),ToChar(底层是char数组),replace,trim

  • StringBuffer

    • 上文中说到了String的缺点,那就是每一次修改字符串都会重新指向,效率低,所以就有了StringBuffer

    • 底层是一个没有final的char[]数组,添加字符串时会扩容,+16

    • 方法:append,delete,replace,indexof,charat,insert

    • 和String的转换

  • StringBuilder

    • 跟StringBuffer兼容一样,线程不安全,单线程时比StringBuffer效率高
posted @   又菜又ai  阅读(821)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示