String常用类

String

介绍

关于Java JDK中内置的一个类:java.lang.String。

  1. String表示字符串类型,属于引用数据类型,不属于基本数据类型。

  2. 在java中随便使用双引号括起来的都是String对象。例如:“abc”,"hello world"等等。

  3. java中规定,双引号括起来的字符串,是不可变的,也就是说"adc"自出生到最终死亡,不可变,不能变成"abcd",也不能变成"ab"。

  4. 在JDK当中双引号括起来的字符串,例如:“abc”,"def"都是直接存储在方法区的字符串常量池当中的。

  5. 为什么SUN公司把字符串存储在一个"字符串常量池"当中呢?

    因为字符串在实际的开发中使用太频繁,为了执行效率,所以把字符串放到了方法区的字符串常量池当中。

内存分析

  1. 如:

    public class StringTest01 {
        public static void main(String[] args) {
            //这两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。
            String s1="abcdef";
            String s2="abcdef"+"xy";
            //分析:这是使用new的方式创建的字符串对象,这个代码中的"xy"是从哪里来的?
            //凡是双引号括起来的都在字符串常量池中有一份。
            //new对象的时候一定在堆内存当中开辟空间
            String s3=new String("xy");
        }
    }
    

    内存分析图:

在这里插入图片描述

  1. 面试题:

    /*
    分析以下程序,一个创建几个对象
    */
    public class StringTest02 {
        public static void main(String[] args) {
    /*
    * 一共创建3个对象:
    *     方法区字符串常量池中有1个:"hello"。
    *     堆内存当中有两个String对象。
    * */
         String s1=new String("hello");
         String s2=new String("hello");
        }
    }
    

String类中常见的构造方法

/*
* 关于String类中的构造方法
* 1:String s=new String("");
* 2: String s=""; 最常用的
* 3: String s=new String(char数组);
* 4: String s=new String(char数组,起始下标,长度);
* 5:String s=new String(byte数组);
* 6: String s=new String(byte数组,起始下标,长度);
* */
public class StringTest04 {
    public static void main(String[] args) {
        //创建字符串对象最常用的一种方式
        String s="hello world";
        String s1=new String("hello world");

        // 这里的常用构造方法
        byte[]bytes={97,98,99};//97是a,98是b,99是c
        String s2=new String(bytes);
        //输出一个引用的时候,会自动调用toString()方法,默认Object的话,会自动输出对象的内存地址
        //通过输出结果,我们可知:String类已经重写了toString()方法。
        //输出字符串对象的话,输出的不是对象内存地址,而是字符串本身。
        System.out.println(s2);//abc

        //String(字节数组,数组元素下标的起始位置,长度)
        String s3=new String(bytes,1,2);  //从下标为1的元素开始,取2个
        System.out.println(s3);//bc


        //将char数组全部转化成字符串
        char[]chars={'我','是','小','马'};
        String s4=new String(chars);
        System.out.println(chars);//我是小马
        String s5=new String(chars,2,2);
        System.out.println(s5);//小马
    }
}

String类中常用方法

public class StringTest05 {
    public static void main(String[] args) {
        //String类中常用方法
        //1(掌握).char charAt(int index)
        char c="小马呀".charAt(1);
        System.out.println(c);//马

        //2(了解).int compareTo(String anotherString)
        //拿着字符串第一个字母和后面字符串的第一个字母比较,能分胜负就不比了。
        //字符串之间比较大小不能直接用><,需要使用compareTo
        int result="abc".compareTo("abc");
        System.out.println(result);//0(等于0)  前后一致

        int result1="abcd".compareTo("abce");
        System.out.println(result1);//-1(小于0) 前小后大

        int result2="abce".compareTo("abcd");
        System.out.println(result2);//1(大于0)  前大后小

        //3(掌握):boolean contains(CharSequence s)
        //判断前面的字符串中是否包含后面的子字符串
        System.out.println("小马".contains("马"));//true
        System.out.println("http://www.baidu.com".contains("https://"));//false

        //4(掌握): boolean endsWith(String suffix)
        //判断当前字符串是否以某个子字符串结尾
        System.out.println("test.txt".endsWith("txt"));//true
        System.out.println("test.txt".endsWith("md"));//false

        //5(掌握):boolean equals(Object anObject)
        // 比较两个字符串必须使用equals方法,不能使用"=="
        System.out.println("abc".equals("abc"));//true

        //6(掌握): boolean equalsIgnoreCase(String anotherString)
        // 判断两个字符串是否相等,忽略大小写
        System.out.println("XiaoMa".equalsIgnoreCase("xiaoma"));//true

        //7(掌握): byte[] getBytes()
        // 将字符串对象转化成字节数组
        byte[]bytes="abc".getBytes();
        System.out.println(Arrays.toString(bytes));//[97, 98, 99]

        //8(掌握):int indexOf(String str)
        //判断某个子字符串在当前字符串中第一次出现处的索引(下标)
        System.out.println("matianciailianha".indexOf("ha"));//14

        //9(掌握): boolean isEmpty()
        //判断某个字符串是否为空。
        String s="";
        String s1="a";
        System.out.println(s.isEmpty());//true
        System.out.println(s1.isEmpty());//false

        //10(掌握):int length()
        //返回字符串长度
        //注意:判断数组长度和判断字符串长度不一样
        //判断数组长度是length属性,判断字符串长度是length()方法
        System.out.println("abc".length());//3
        System.out.println("".length());//0

        //11(掌握): int lastIndexOf(String str)
        //判断某个子字符串在当前字符串中最后一次出现的索引(下标)
        System.out.println("1java8ndsdjavanfad".lastIndexOf("java"));//10


        //12(掌握):  String replace(CharSequence target, CharSequence replacement)
        //String的父接口就是:charSequence
        //通过新字符替换旧字符,返回一个新字符串
        System.out.println("abcb".replace("b","e"));//aece

        //13(掌握):  String[] split(String regex)
        // 拆分字符串
       String[]ymd= "1997-09-30".split("-");//将 "1997-09-30" 以"-"分隔符进行拆分
        System.out.println(Arrays.toString(ymd));//[1997, 09, 30]

        //14(掌握): boolean startsWith(String prefix)
        // 判断某个字符串是否以某个子字符串开始
        System.out.println("http://www.baidu.com".startsWith("http://"));//true
        System.out.println("http://www.baidu.com".startsWith("https://"));//false

        //15(掌握): String substring(int beginIndex) 参数是起始下标
        //截取字符串
        System.out.println("http://www.baidu.com".substring(7));//www.baidu.com

        //16(掌握):  String substring(int beginIndex, int endIndex)
        //左闭右开 beginIndex(起始位置):包含  endIndex(结束位置):不包含
        System.out.println("http://www.baidu.com".substring(11,16));//baidu

        //17(掌握):  char[] toCharArray()
        // 将字符串转化为char数组
        char[]chars="我是小马呀".toCharArray();
        System.out.println(Arrays.toString(chars));//[我, 是, 小, 马, 呀]

        //18(掌握): String toLowerCase()
        //全部转化为小写
        System.out.println("WoshiXIAOMA".toLowerCase());//woshixiaoma

        //19(掌握): String toUpperCase()
        // 全部转化为大写
        System.out.println("WOshixiaoma".toUpperCase());//WOSHIXIAOMA

        //20(掌握):String trim()
        // 去除字符串前后空白 中间空白不可去
        System.out.println("   hello  world   ".trim());//hello  world

        //21(掌握):String中只有一个方法是静态的,不需要new
        //这个方法是valueof
        //作用:将非字符串转化为字符串
        System.out.println(String.valueOf(true));//字符串true
        System.out.println(String.valueOf(100));//字符串100
        //这个静态的valueof()方法,参数是一个对象的时候,会自动调用该对象的toString()方法
        String s2=String.valueOf(new User1());
        System.out.println(s2);//没有重写toString()方法之前是对象内存地址:com.ma.StringClass.User1@73035e27
        //通过源代码可以看出:System.out.println()这个方法,本质上在输出任何数据的时候
        //都是先转化成字符串,再输出
        System.out.println(s2);//重写后调用toString():用户


    }
}

class User1{
//重写toString()

    @Override
    public String toString() {
        return "用户";
    }
}

StringBuffer

  1. 当进行字符串拼接时,若使用String进行拼接,如下:

    /*
    * 我们在实际开发中,如果需要进行字符串的频繁拼接,会有什么问题?
    * 因为java中的字符串是不可变的,每一次拼接都会产生新字符串。
    * 这样会占用大量的方法区内存。造成内存空间的浪费
    * String s="abc";
    * s+="hello";
    * 就以上两行代码,就导致在方法区字符串常量池当中创建了3个对象;
    * "abc" "hello" "abchello"
    * */
    public class StringBufferTest01 {
        public static void main(String[] args) {
        String s="";
        //这样做会给java的方法区字符串常量池带来很大的压力
            for (int i=0;i<100;i++){
                s+=i;
                System.out.println(s);
      
           }
    
        }
    } 
    
  2. 如果以后需要进行大量字符串的拼接操作,建议使用JDK自带的:
    java.lang.StringBuffer
    java.lang.StringBuilder

    1. 如何优化StringBuffer的性能:
      在创建StringBuffer的时候尽可能给定一个初始化容量,最好减少底层数组的扩容次数,预估计一下,给一个大些的初始化容量。
      关键点:给一个合适的初始化容量

    如:

    /*
    * 如果以后需要进行大量字符串的拼接操作,建议使用JDK自带的:
    * java.lang.StringBuffer
    * java.lang.StringBuilder
    *
    * 如何优化StringBuffer的性能:
    *   在创建StringBuffer的时候尽可能给定一个初始化容量
    *   最好减少底层数组的扩容次数,预估计一下,给一个大些的初始化容量
    *   关键点给一个合适的初始化容量
    * */
    public class StringBufferTest02 {
        public static void main(String[] args) {
    //创建一个初始化容量为16的byte[]数组(字符串缓冲区对象)
            StringBuffer stringBuffer=new StringBuffer();
    
            //拼接字符串,以后拼接字符串统一调用append()方法
            //append是追加
            //append方法底层在进行追加的时候,如果byte数组满了,会自动扩容
            stringBuffer.append("a");
            stringBuffer.append("b");
            stringBuffer.append("c");
            stringBuffer.append(3.14);
            stringBuffer.append(true);
            System.out.println(stringBuffer);
    
            //指定初始化容量的StringBuffer对象(字符串缓冲区对象)
            StringBuffer sb=new StringBuffer(10);
            sb.append("hello");
            sb.append("world");
            System.out.println(sb);
    
        }
    }
    

StringBuilder

/*
* java.lang.StringBuilder
*
* StringBuffer和StringBuilder的区别
*  StringBuffer中的方法都有:synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
*  StringBuilder中的方法都没有synchronized关键字修饰。表示StringBuilder在多线程环境下运行是不安全的。
*  StringBuffer是线程安全的,StringBuilder是非线程安全的。
* */
public class StringBuilderTest01 {
    public static void main(String[] args) {
        //使用StringBuilder也是可以完成字符串的拼接
        StringBuilder sb=new StringBuilder();
        sb.append(100);
        sb.append(true);
        sb.append("hello");
        sb.append("world");
        System.out.println(sb);
    }
}

面试题

  1. String为什么是不可变的?

    我看过源代码,String类中有一个byte[]数组,这个byte[]数组用final修饰的,因为数组一旦创建长度是不可变的。并且被final修饰的引用一旦指向某个对象后,不可再指向其他对象,所以String是不可变的。

  2. StringBuilder或StringBuffer为什么是可变的?

    我看过源代码,StringBuilder或StringBuffer内部实际上是一个byte[]数组,这个byte[]数组没有被final修饰,StringBuilder或StringBuffer的初始化容量我记得应该是16,当存满之后会进行扩容,底层调用了数组拷贝的方法System.arraycopy()…是这样扩容的。所有StringBuilder或StringBuffer适合于字符串的频繁拼接操作。

  3. String字符串不可变是什么意思:

    public class StringBufferTest03 {
        public static void main(String[] args) {
            //字符串不可变是什么意思?
            //是说双引号里面的字符串对象一旦创建不可变
            String s="abc"; //"abc"放在字符串常量池,"abc"不可变
            
            //s变量是可以指向其他对象的
            //字符串不可变不是说以上变量s不可变。说的是"abc"
            s="xyz"; //"xyz"放在字符串常量池,"xyz"不可变
            System.out.println(s);//xzy
        }
    }
    
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值