JavaSE—String类

前情提要:

        在此前我们谈到数据类型和变量的时候了解到了String类,但是没有并没有详细地讲到String类的应用以及jvm提供许多相关API的应用,这篇博客就来了解一下String类以及相关API的应用。 


String类的重要性: 

        在学习C语言的时候就已经对字符串有所涉猎,但是C语言中要表达字符串只能使用字符数组或者字符指针,再调用标准库提供的已经完成的相关函数来完成编译需求。因为讲数据和操作数据的方法分离不符合面向对象编程的理念,Java中为了满足string类广泛的应用要求,所以提供了String类。


常用方法:

字符构造:

        String类提供的构造方式非常多,常用的就以下三种:

    public static void main(String[] args) {
        //第一种:直接new一个String类对象
        String s1 = new String("abcd");

        //第二种:直接创建一个常量字符串
        String s2 = "abcde";

        //第三种:使用字符数组构建
        char[] ch = {'a','b','c','d','e'};
        String s3 = new String(ch);

    }

 注意:String本身是引用类型,内部并不储存字符串本身


String类对象进行比较:

1、==用于比较是否引用同一个对象

         String属于引用类型,引用变量与基本类型变量的比较方式有所不同。

    public static void main(String[] args) {
 
        int a = 10;
        int b = 10;
        System.out.println(a==b);               //true

        //引用类型进行比较,==则是比较引用对象是否为同一个
        String s1 = new String("abc");
        String s2 = new String("abc");
        System.out.println(s1==s2);             //false
    }

        ==在比较引用类型变量的时候比较的是地址(如果地址相同说明是同一个对象,返回值会是true),比较基本类型变量的时候比较的是内置储存的值是否一样。

2、boolean equals(Object anObject)方法:按照字典序比较

        我们用ctrl+鼠标左键点击equals()可以直接看对应API中的方法是怎么进行重写的 

        字典序比较:按照字符大小写进行比较 

public boolean equals(Object anObject) {
    // 1. 先检测this 和 anObject 是否为同一个对象比较,如果是返回true
    if (this == anObject) {
                return true;
            }    
    // 2. 检测anObject是否为String类型的对象,如果是继续比较,否则返回false
    if (anObject instanceof String) {
       // 将anObject向下转型为String类型对象
            String anotherString = (String)anObject;
            int n = value.length;
    // 3. this和anObject两个字符串的长度是否相同,是继续比较,否则返回false
    if (n == anotherString.value.length) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = 0;
    // 4. 按照字典序,从前往后逐个字符进行比较
        while (n-- != 0) {
        if (v1[i] != v2[i])
            return false;
            i++;
        }
        return true;
        }
    }
return false;

 例:

        三个实例化对象s1,s2,s3,我们可以知道不同于==比较,equals不仅比较对象,还看引用对象的内容:

        不同引用对象但存放内容相同——返回true

        不同引用对象存放内容不同——返回false

    public static void main(String[] args) {

        String s1 = new String("abc");
        String s2 = new String("abc");
        String s3 = new String("abd");
        System.out.println(s1.equals(s2));       //true  虽然经过比较发现不是同一个引用对象,但是引用对象存放的内容相同所以返回值是true
        System.out.println(s1.equals(s3));       //false 因为不是同一个引用对象内容也不同,所以返回值是false
    }

3、int compareTo(String s)方法比较:按照字典序比较

        与equals()不同的是compareTo()的返回值是int类型,具体比较方式:
        1、先按字符序比较,当比较到不同的字符时返回两个字符串的长度差

        2、前n个字符相同,则返回两个字符串的长度差

    public static void main(String[] args) {

        String s1 = new String("abc");
        String s2 = new String("ad");
        String s3 = new String("abcd");
        String s4 = new String("abc");
        System.out.println(s1.compareTo(s2));       //-1    s1和s2进行比较,b≠c且c>b,所以返回值是ascii值 s1-s2 = -1
        System.out.println(s1.compareTo(s3));       //-1    s1和s3比较,前面相同但是s3长度比s1大1,返回值是s1.length-s3.length
        System.out.println(s1.compareTo(s4));       //0     s1和s4比较,内容一样所以返回0
    }

 字符串查找

        我们可以给字符串查找分类:直接查找、顺序查找、逆序查找

直接查找:

        直接查找用到的实例方法是char charAt(int ch),直接访问字符串下标为ch的字符

例:

    public static void main(String[] args) {
        String s1 = new String("abcd");
        System.out.println(s1.charAt(3));           //char charAt(int index) 返回index下标所在的符号
  
    }

        还有顺序直接查找int index(int ch,int fromIndex),逆序直接查找int lastIndex(int ch,int fromIndex)

     

   public static void main(String[] args) {
        String string = new String("Harry Porter");
        System.out.println(string.indexOf('a',0));
        System.out.println(string.lastIndexOf('a',5));
    }

 

顺序查找:

        也就是从前往后查找字符,要用到的方法是int index()

    public static void main(String[] args) {
        String s2 = new String("hello");

            System.out.println(s2.indexOf('e'));        //int indexof(int ch)    返回字符ch 所在的下标index,没有的话返回-1
            System.out.println(s2.indexOf("ell"));        //int indexof(String ch) 返回字符ch第一次出现的下标index,没有的话返回-1
            System.out.println(s2.indexOf("el",3));        //int indexof(String ch,int fromindex) 从fromindex开始找字符ch,返回字符ch第一次出现的下标index,没有的话返回-1
        }

运行结果是:

         

逆序查找:

        倒序查找,从字符串的尾端开始查找,要用到的方法是int lastIndexOf() 

   public static void main(String[] args) {
        String s1 = new String("abcd");

        System.out.println(s1.lastIndexOf('a'));                //int lastIndexOf(int ch)    返回字符ch 所在的下标index,没有的话返回-1
        System.out.println(s1.lastIndexOf("abc"));              //int lastIndexOf(String str) 从后往前找,返回字符str第一次出现的下标index,没有的话返回-1
        System.out.println(s1.lastIndexOf('b',3));  //int lastIndexOf(String str,int fromindex) 从fromindex开始,从后往前面找字符ch,返回字符str第一次出现的下标index,没有的话返回-1
    }

运行结果:

 特别注意:在调用index()和fromIndexOf()方法的时候,查找字符要用' '引用,查找字符串要用" "引用,不然容易搞出乌龙

        


字符串拆分 

        字符拆分用到的方法String split(String regex)和String split(String regex,int limit)

        前者是整个字符串都按照字符regex部分进行整体拆分,后者是按照字符regex进行拆分的同时还将字符串拆分成limit份(也就是部分拆分)

        我们用代码实例来体会一下二者的区别:

调用前者:

   public static void main(String[] args) {
        String string = new String("Harry Porter great magic");
        String[] sp1 = string.split(" ");        //split(String regex) ,该例子中按照" "空格切割
        for(String st:sp1)
        {
            System.out.println(st);
        }
     
    }

 按照空格切割整个字符串:

调用后者:

    public static void main(String[] args) {
        String string = new String("Harry Porter great magic");
   
        String[] sp2 = string.split(" ",2);
        for(String st:sp2)
        {
            System.out.println(st);
        }
    }

 按照空格切割,limit=2,所以将字符串拆分成两部分:


字符串替换:

        字符串替换用到的方法是String replaceAll(String regex, String replacement) String replaceFirst(String regex, String replacement)

        方法中第一个参数是原字符中要被替换的字符串,第二个参数是替换内容,上述两个方法前者是将原字符串中符合参数的字符串全部替换,后者是替换第一个符合参数字符串的字符串

    public static void main(String[] args) {
        String string = new String("Iron man and Bat man");
        System.out.println(string.replaceAll("man","woman"));
        System.out.println(string.replaceFirst("man", "woman"));

    }

 运行结果:


字符串截取: 

        字符串截取用到的方法是String substring(int beginIndex)和String substring(int beginIndex, int endIndex)

        在字符串中从区间(begin,end)截取字符

    public static void main(String[] args) {
        String str = "helloworld" ;
        System.out.println(str.substring(5));
        System.out.println(str.substring(0, 5));

    }

运行结果:

 


String的引用雷点:

        在日常开发时有时会涉及到修改字符串的操作,但是有一个特点非常重要!!          

        那就是——String引用变量的内容不能直接进行修改!!

        此前,对于String类引用变量不可修改有一种说法——之所以不可修改是因为String类内部方法被final关键字修饰,所以不能被修改。但是这种说法是错的,final修饰的类表明该类不想被继承,final修饰的方法和成员变量表明不想被其他对象引用,但是引用对象中的内容是可以被修改的

        String类的各种修改操作都是通过调用新的对象来进行修改(new一个新的对象接受修改对象的属性,在新的对象上对这些属性进行修改,最后将新的对象作为返回类型替换旧的对象) 

        为什么String类引用不支持直接修改? 

        答:因为如果String类引用如果课修改的话,那么对象池就得考虑临时拷贝的问题,而且不可变对象的线程是安全的。

      


StringBuffer和StringBuilder

           因为在日常开发难免会有修改需求,所以大佬们设计了StringBuffer和StringBuilder这两个引用类型并封装在String的API中。

        二者可调用的引用方法基本上一致

 public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer("abc");

        System.out.println(s1.append("abcd"));                           // append(str) 在字符串末尾追加str
        System.out.println(s1.delete(0, 4));                             // delete(起始,截止] 左边为开区间,右边是闭区间 删除区间内的字符
        System.out.println(s1.deleteCharAt(2));                    // delete (index:下标)  删除下标所在的字符
        System.out.println(s1.indexOf("abcd"));                          // indexof(String str)返回str 第一次出现的位置
        System.out.println(s1.capacity());                               // capacity() 获得底层保存字符串的空间大小
        System.out.println(s1.substring(2));                        // substring(int start) 将start下标开始的字符以string的方式返回
        System.out.println(s1.substring(0,3));                           // substring(int start,int end) 截取start下标开始到end下标的字符以string的方式返回
        System.out.println(s1.replace(1,4,"abc"));         // replace(start,end,str) 从起始下标到截止下标的字符用str替代
        System.out.println(s1.reverse());                                // reverse() 将字符串旋转abc——>cba然后以String的方式返回
        System.out.println(s1.lastIndexOf("abcd"));                  // lastIndexOf(str:) 找到最后一次出现str的位置并且返回
        System.out.println(s1.lastIndexOf("abcd",0));       // lastIndexOf(str,fromindex) 从fromIndex 位置开始寻找最后一次str出现的位置*/
        s1.ensureCapacity(20);                             //扩容
        s1.toString();                                                    //将整个字符串以String方式返回
    }

Tips:

        StringBuffer和String不能直接进行转换,要想相互转换就得遵守一下规则:

        StringBuffer——>String:调用toString()方法

        String——>StringBuffer:利用StringBuffer的构造方法或者调用append()方法

经典面试题:

        String、 StringBuffer和StringBuilder三者有何区别?

        答:1、String的内容不可修改,而 StringBuffer和StringBuilder的内容可以修改

                2、StringBuffer与StringBuilder大部分功能是相似的

                3、StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

 


本次博客内容分享到此啦!!请您看完后不要吝啬您的三连!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值