String

139 阅读4分钟

image.png 虽然我们经常使用到String,但其实对于里面的特性还是很多没有被发现的。

String的实例化方式:

1.通过字面量定义

2.通过new+构造器的方式

String:字符串,使用一对“”引起来表示

1.String声明为final的,不可被继承

2.String实现了Serializable(可序列化)接口:表示字符串支持序列化

实现了Comparable接口:表示String可以比较大小

3.String内部定义了final char[] value用于存储字符串数据

4.String:代表不可变的字符序列,简称:不可变性

体现:1.当对字符串重新赋值时,需要重写指定内存区域赋值不能使用原有的value进行赋值(在对s1重新赋值中有所体现)

2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值不能使用原有的value进行赋值(在对s3=s2+“def”两者字面量不同中有所体现)

3.调用replace()方法时也类似。

5.通过字面量的方式(区别于new方法)给一个字符串赋值,此时的字符串值声明在字符串常量池中。

6.字符串常量池中是不会存储相同内容的字符串的

4,5,6下面给出解析:

字面量的定义方式:String s1 = “abc”;

String s2 = “abc”;

此时s1与s2指向同一个地址

image.png 因为在方法区中:不会出现字面量相同的两个地址值,因此在给s2赋值时,会先观察方法区中是否有对应的值,若有,直接把地址给s2,若没有,再新创

若s1=“hello",由于String的不可变性,因此会在方法区中重新定义”hello“并使s1拿到它的地址

image.png

image.png

image.png

image.png new就相当于在堆中新建了value值,那么每new一个对象就会在堆中新建,地址值也因此不同,堆中的value存储着指向常量池的引用地址

面试题:

String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?

2个,一个是堆空间中new的对象,另一个是char【】对应的常量池中的数据:“abc”

image.png 结论:只要有变量参与的就地址就指向堆中的数据

image.png 涉及到了些JVM的知识没有记录,后续再专门学习JVM吧。

下面列举一些String的常用方法,

也可在菜鸟文档进行搜索

[Java String 类 | 菜鸟教程 (runoob.com)

image.png

image.png

image.png

String与基本数据类型转换:

image.png UTF-8:用三个二进制数据存储汉字

gbk:用两个二进制数据存储汉字

image.png

算法题:

image.png

image.png

public class StringTest1 {//模拟一个trim方法,去除字符串两端的空格
    public static void main(String[] args) {
        String str = " addadasd   ";
        StringTest1 s = new StringTest1();
        String s1 = s.trim1(str);
        System.out.println(s1);


    }
    public String trim1(String str){
        int start = 0;
        int end = str.length()-1;
        while(start<=end&&str.charAt(start)==' '){
            start++;
        }
        while(start<=end&&str.charAt(end)==' '){
            end--;
        }
        return str.substring(start,end+1);
    }

}
public class StringTest2 {//将一个字符串进行反转,将字符串中指定部分进行反转,比如“abcdefg”反转为“abfedcg”

    public static void main(String[] args) {
        StringTest2 stringTest2 = new StringTest2();
        String str = "abcdefg";
        String reverse = stringTest2.reverse(str, 3, 6);
        System.out.println(reverse);
    }



    public String reverse(String str,int start,int end){//start表示需要反转的起始位置,end表示末尾位置
        String reverse = "";
        String reverse1 = "";
        String reverse2 = "";
        char []array = str.toCharArray();
        for(int i = end-1;i>start-2;i--){
            reverse+=array[i];
        }
        for(int i = 0;i<start-1;i++){
            reverse1+=array[i];
        }
        for(int i = end;i<array.length;i++){
            reverse2+=array[i];
        }
        String s = reverse1 + reverse + reverse2;
        return s;
    }

}

//获取一个字符串在另一个字符串中出现的次数
//比如:ab在abkkcadkabkebfbabkskab出现的次数
public class StringTest3 {
    public static void main(String[] args) {
        String str1 = "abkkcadkabkebfbabkskab";
        String str2 = "ab";
        StringTest3 s = new StringTest3();
        int sum = s.fench(str1,str2);
        System.out.println(sum);
    }

    public int fench(String str1,String str2){
        int sum = 0;
        int index = 0;
        if(str1.length()>str2.length()){
            while((index=str1.indexOf(str2,index))!=-1){
                sum++;
                index+=str2.length();

            }
            return sum;

        }else{
            return 0;
        }
    }
}
//获取两个字符串最大相同子串
public class StringTest4 {
    public static void main(String[] args) {
        StringTest4 stringTest4 = new StringTest4();
        String st = stringTest4.st("abcd", "abc");
        System.out.println(st);
    }





    public String st(String str1,String str2){
        int a = str1.length();
        int b = str2.length();
        if(str1.length()<=str2.length()){
            int temp = a;
            a = b;
            b=temp;
        }
        for(int x = 0;x<b;x++){
            for(int y =0,z=b-x;z!=b+1;y++,z++){
                String temp = str2.substring(y,z);
                return temp;
            }
        }return null;

    }
}

StringBuffer,StringBuilder,String三者的异同?

效率从高到低:StringBuilder,StringBuffer,String

String:不可变的字符序列,底层使用char[]存储

StringBuffer:可变的字符序列,效率安全,效率低

StringBuilder:JDK5.0新增的,可变的字符序列,线程不安全,效率高

源码分析:

String str = new String();//char[]value=new char[0];

String str1 = new String("abc");//new char[]{'a','b','b'};

StringBuffer sb1= new StringBuffer();//char[]value=new char[16];底层创建了一个长度是16的数组

sb1.append('a')//value[0]='a';

sb1.append('b');

StringBuffer sb2= new StringBuffer("abc");//char[]value=new char["abc".length+16];

问题1:输出sb2.length()返回3

问题2:扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组?

默认情况下:扩容为原来容量的2倍+2,同时将原有数组的元素复制到新的数组中。

指导意义:开发中建议StringBuffer(int capacity)或StringBuilder(int capacity)

StringBuffer,StringBuilder类的常用方法

image.png 增:append(xxx)

删:delete(int start,int end)

改:replace(int start,int end,String str)/setCharAt(int n,char ch)

查:charAt(int n)

插:insert(int offset,xxx)

长度:length()

遍历:for()+charAt() / toString()