String类 超详解!!! --- Java内功心法

目录

1.String常用方法

1.1构造方法

1.2 String对象的比较

1.==

2.equals方法

3.compareTo方法

1.3其他方法

2.字符串的不可变性

3.字符串的修改

3.1直接修改String对象的弊端

3.2StringBuilder类/StringBuffer类

1.常用方法

3.2String、StringBuffer、StringBuilder的区别


1.String常用方法

1.1构造方法

String提供的构造方法很多,其中常用的有三种:

    public static void main(String[] args) {
        String str1 = "abc";//1.使用常量字符串进行构造

        String str2 = new String("abc");//2.直接new String对象

        char[] ch = {'a', 'b', 'c'};//3.使用字符数组进行构造
        String str3 = new String(ch);
    }


String是引用类型,内部并不存储字符串,而是一个字符数组。
这是源码:


在JAVA中用 双引号"" 引起来的也是String类型对象。

System.out.println("helloworld".length());//这个helloworld就是一个String对象,
                                          //它能调用String的方法
                                          //执行结果:10

1.2 String对象的比较


1.==

1.对于基本类型变量,==比较的是两个变量的值是否相等。

        int a = 10;
        int b = 10;
        System.out.println(a == b);//执行结果:true

2.对于引用变量,==比较是否指向同一个对象。采用new关键字创建对象时,每次new出来的都是一个新的对象,也即是说引用str1和str2指向的是两个不同的对象。

        String str1 = new String("hello");
        String str2 = new String("hello");
        System.out.println(str1 == str2);//执行结果:false

3.在我们的String中,存在字符串常量池。

        JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存空间,这一块空间就是字符串常量池。

        我们采用常量字符串来构造一个String对象的时候,JVM会先在常量池中查找这个字符串是否存在,如果不存在则将这个字符串加入常量池中。如果存在,则不创建任何新的对象,直接将常量池中已有的对象的引用返回。

        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);//执行结果:true

        值得一提的是,如果在使用new关键字创建String对象的时候,当常量池里不存在这个字符串,会现在常量池创建这个字符串,然后再在堆上创建一个新的对象,返回的是堆上的对象的引用。

        如果常量池已经存在这个字符串,那么就不在常量池再创建一次了会在堆上创建对象,返回的也是堆上对象的引用。


2.equals方法

equals方法用来比较两个String对象是否相等:

        String str1 = new String("hello");
        String str2 = new String("hello");
        System.out.println(str1 .equals(str2));//执行结果:true

equals源码:

    public boolean equals(Object anObject) {
        if (this == anObject) {//如果是指向的是同一个对象
            return true;//直接返回true
        }
        if (anObject instanceof String) {//如果都是String类则进行比较
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {//如果两个字符串长度相等
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }


3.compareTo方法

compareTo方法用来比较两个字符的大小:

如果两个字符串相等,返回0。

        //如果两个字符串相等,返回0。
        String str1 = new String("hello");
        String str2 = new String("hello");
        System.out.println(str1 .compareTo(str2));//执行结果:0


先按照字典序比较,如果出现不同的字符则直接返回这两个字符的大小差值。

        //先按照字典序比较,如果出现不同的字符则直接返回这两个字符的大小差值。
        String str3 = new String("world");
        String str4 = new String("hello");
        System.out.println(str3 .compareTo(str4));//执行结果:15


如果前k个字符相等(k为两个字符长度最小值),就返回两个字符串长度差值。

        //如果前k个字符相等(k为两个字符长度最小值),就返回两个字符串长度差值。
        String str5 = new String("hello");
        String str6 = new String("helloworld");
        System.out.println(str5 .compareTo(str6));//执行结果:-5

compareTo源码:

    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

1.3其他方法

1.字符串查找

方法功能
char charAt(int index)返回index位置上字符,如果index为负数或者越界,抛出 IndexOutOfBoundsException异常
int indexOf(int ch)返回ch第一次出现的位置,没有返回-1
int indexOf(int ch, int fromIndex)从fromIndex位置开始找ch第一次出现的位置,没有返回-1
int indexOf(String str)返回str第一次出现的位置,没有返回-1
int indexOf(String str, int fromIndex)从fromIndex位置开始找str第一次出现的位置,没有返回-1
int lastIndexOf(int ch)从后往前找,返回ch第一次出现的位置,没有返回-1
int lastIndexOf(int ch, int fromIndex)从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返 回-1
int lastIndexOf(String str)从后往前找,返回str第一次出现的位置,没有返回-1
int lastIndexOf(String str, int fromIndex)从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返 回-1

2.字符串替换

方法功能
String replaceAll(String regex, String replacement)替换所有的指定内容
String replaceFirst(String regex, String replacement)替换首个内容

3.字符串拆分

方法功能
String[] split(String regex)将字符串全部拆分
String[] split(String regex, int limit)将字符串以指定的格式,拆分为limit组

4.字符串截取

方法功能
String substring(int beginIndex)从指定索引截取到结尾
String substring(int beginIndex, int endIndex)截取部分内容

5.其他操作方法

方法功能
String trim()去掉字符串中的左右空格,保留中间空格
String toUpperCase()字符串转大写,只转换字母
String toLowerCase()字符串转小写,只转换字母

char[] toCharArray()

将字符串转换为字符数组

2.字符串的不可变性

        String类是一种不可变的对象,也就是说字符串不能被修改,原因如下:

1.这是源码中的一段话:字符串是常量;它们的值在创建后不能更改。

        以及这个String类被final修饰,表示它不能被继承。它的value数组也被final修饰,表示value本身的值不能改变,它不能引用其他字符数组,但是它所引用的空间的内容是可以改变的。

 

 2.所有涉及到更改字符串内容的操作,本质上都new了一个新对象:

以replace为例,这是replace源码:

public String replace(char oldChar, char newChar) {
        if (oldChar != newChar) {
            int len = value.length;
            int i = -1;
            char[] val = value; /* avoid getfield opcode */

            while (++i < len) {
                if (val[i] == oldChar) {
                    break;
                }
            }
            if (i < len) {
                char buf[] = new char[len];
                for (int j = 0; j < i; j++) {
                    buf[j] = val[j];
                }
                while (i < len) {
                    char c = val[i];
                    buf[i] = (c == oldChar) ? newChar : c;
                    i++;
                }
                return new String(buf, true);//返回了一个新的对象
            }
        }
        return this;
    }

为什么要将String设置为不可变呢?

1.方便实现字符串常量池,如果可变就要考虑常量池里的拷贝问题了。

2.不可变的是线程安全的(线程后面再讲)。

3.不可变对象可以更方便地缓存hashcode,作为key可以更高效地存入hashmap中。

3.字符串的修改

3.1直接修改String对象的弊端

在修改字符串的时候,我们应该避免直接使用String类进行修改,因为在修改String类的时候会创建一个新的对象效率十分低下 ->

        String str = new String();
        for (int i = 0; i < 100; i++) {
            str += 'a';
        }

        (在不考虑常量池已有对象的情况下)循环体中的 str += 'a';语句可以写为 str = new String(str) + new String("a"),而执行这条语句就会创建一个新的StringBuilder类的对象,假设它叫tmp,是一个空字符串,它会追加一个new String(str)和一个new String("a"),然后将这个结果再toString(转换为字符串),所以一共创建了6个对象~~

对象1:new StringBuilder()

对象2:new String("a")

对象3:常量池中的"a"

对象4:new String("b")

对象5:常量池中的"b"

对象6:new String("ab")

以上代码由于直接作用于String类,所以会创建很多对象。

那我们在修改字符串的时候最好用StringBuilder或者StringBuffer类来进行修改。

3.2StringBuilder类/StringBuffer类

1.常用方法

这两个类的方法相差不大,这里以StringBuffer类的方法为例

方法功能
StringBuffer append(String str)在尾部追加,相当于String的+=,可以追加:boolean、char、char[]、 double、float、int、long、Object、String、StringBuff的变量
char charAt(int index)获取index位置的字符
int length()获取字符串的长度
int capacity()获取底层保存字符串空间总的大小
void ensureCapacity(int mininmumCapacity)扩容
void setCharAt(int index, char ch)将index位置的字符设置为ch
int indexOf(String str)返回str第一次出现的位置
int indexOf(String str, int fromIndex)从fromIndex位置开始查找str第一次出现的位置
int lastIndexOf(String str)返回最后一次出现str的位置
int lastIndexOf(String str, int fromIndex)从fromIndex位置开始找str最后一次出现的位置
StringBuffer insert(int offset, String str)在offset位置插入:八种基类类型 & String类型 & Object类型数据
StringBuffer deleteCharAt(int index)删除index位置字符
StringBuffer delete(int start, int end)删除[start, end)区间内的字符
StringBuffer replace(int start, int end, String str)删除[start, end)区间内的字符
String substring(int start)从start开始一直到末尾的字符以String的方式返回
String substring(int start,int end)将[start, end)范围内的字符以String的方式返回
StringBuffer reverse()反转字符串
String toString()将所有字符按照String的方式返回

3.2String、StringBuffer、StringBuilder的区别

1.String的内容不能修改,StringBuffer、StringBuilder的内容可以修改。

2.StringBuffer、StringBuilder的大部分功能是类似的。

3.StringBuffer采用同步处理,是线程安全的,StringBuilder未采用同步处理,是线程不安全的。

结语:最近越来越理解“书读百遍,其意自见”的含义了,不懂的代码就多敲,不会的知识点就多看~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值