String

发布时间:2024年01月20日

本章目标

  1. String类概念

  2. String API

  3. String类型字符串对象内存分析

  4. StringBuilder和StringBuffer

  5. String StringBuilder StringBuffer对比

  6. 字符串常量池

本章内容

一、String概念

java.lang

String是一个用final修饰过的类,使用方式有两种

  1. 赋值一个字面量,字面量存放在字符串常量池中

    String s=”abcde”;//指向的是字符串常量池中的字符串对象

  2. 调用String类的构造方法,会在堆区(非常量池)中创建一个字符串对象,每new一次,都会重新创建一个新的字符串对象

    1)调用String类型的参数的构造方法:String s=new String(“abcde”).

    2)调用char 数组类型参数的构造方法

    3)调用byte类型数组的构造方法:通过使用平台的默认字符集解码将指定的字节数组来构造新的 String

    4)调用byte类型数组的构造方法:通过使用指定的编码指定的字节数组来构造新的 String

package a_info;
?
import java.io.UnsupportedEncodingException;
?
public class Demo1 {
    //String类存放在java.lang包
    //String类被final修饰,说明不能被继承
    //private final char value[]
    //String类中存储的字符串,底层是字符数组
    //被final修饰,不能进行修改,String也有不可变的特性
    //学习API,就是学习类、包、属性、构造方法、方法
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "abc"; ?//"abc"存在常量池中,第一次使用时,需要在常量池中存入abc,将地址赋给str
        String str2 = "abc"; //在常量池中查找是否有abc,如果有,直接将abc的地址赋给str2
//      System.out.println(str==str2);
        
//      String str3 = new String(); //声明没有内容的字符串对象
//      System.out.println(str3);
        
//      String str4 = new String("abc");
//      System.out.println(str==str4);
//      System.out.println(str.equals(str4));
        
?
//      byte[] bytes2 = {97,98,99};
//      String str8 = new String(bytes2);   //以字节数组为参数,构造成字符串,没有指定编码,可能会出现乱码
//      System.out.println(str8);
        
        
        String str5 = "早上好";
        byte[] bytes = str5.getBytes("UTF-8");
        
        String str6 = new String(bytes,"UTF-8");    //以字节数组和编码名称做为参数,构造成字符串,避免乱码
        System.out.println(str6);
        
    }
?
}
?

二、String API(String提供的一些常用的方法)

image-20220518100932364

  1. ==和equals的区别?(重要)

    等号比对的是两个字符串对象的地址信息,可以比对null对象 str==str2,str可以为null

    equals:用途:比较字符串的内容,重写Object的方法

    equals的比较过程:首先比较两个字符串对象的地址,如果地址一样直接返回true, 如果地址不一样,再比对字符串的内容,字符串内容一样返回true,不一样返回false,不能使用Null对象调用,str.equals(str2) .

    实例

    String str="abcde";
    String str1="abcde";
    String str2 = new String("abcde");
    System.out.println(str.equals(str2));//true
    System.out.println(str==str1);//true
    System.out.println(str==str2);//false
  2. String常见操作

    • public int length():非静态方法,获取字符串长度

              //获得字符串的长度
              int length = str.length();
              System.out.println(length);

    • public char charAt(位置):返回某一个位置的字符,位置范围为:[0~字符串长度-1]

      //char charAt(int index)    
              //根据参数index的位置返回字符串中该位置的字符
              char c = str.charAt(0);
              System.out.println(c);

    • public int indexOf(字符|字符串):返回某一个字符或者字符串第一次出现的的位置,找不到返回-1

    • public int indexOf(字符|字符串,开始位置):从指定位置开始找,返回某一个字符或者字符串第一次出现的的位置,找不到返回-1

              //int indexOf(int ch)
              //找出ch数字对应字符在原串中第一次出现的位置
      //      int i = str.indexOf(97);
      //      System.out.println(i);
              //int indexOf(int ch,int fromIndex)
              // 从fromIndex找出ch数字对应字符在原串中第一次出现的位置
              //int indexOf(String str)
              //找出str在原串中第一次出现的位置
              //int indexOf(int ch,int fromIndex)
              // 从fromIndex找出str在原串中第一次出现的位置
              //如果找不到,返回-1

    • public int lastIndexOf(字符|字符串):从后向前找第一次出现的位置

      //获得文件的名字
              int lastIndexOf = filename.lastIndexOf('.');
              String fname = filename.substring(0, lastIndexOf);
              System.out.println(fname);

    • public String substring(起始位置):从开始位置截取字符串

    • public String substring(起始位置,结束位置):截取字符串,包含起始位置,但是不包含结束位置

      //String substring(int beginIndex) 从beginIndex截取到字符串末尾,并将截取后的结果返回
      //String substring(int beginIndex, int endIndex); 从beginIndex截取到endIndex(不包含endIndex),并将截取后的结果返回

    • public boolean equals(Object str):比较两个字符串的内容

    • public String toUpperCase():将一个字符串转换为纯大写

    • public String toLowerCase():将一个字符串转换为纯小写

    • public boolean equalsIgnoreCase(另一个字符串):忽略大小写进行比较

              String str = "This is a student.";
      //      public String toUpperCase():将一个字符串转换为纯大小
              System.out.println(str.toUpperCase());
              
      //      public String toLowerCase():将一个字符串转换为纯小写
              System.out.println(str.toLowerCase());
              
      //      public boolean equalsIgnoreCase(另一个字符串):忽略大小写进行比较
              System.out.println(str.equalsIgnoreCase("this is a student."));

    • public String concat(另一个字符串):连接字符串,另一个字符串长度不为0的时候,连接的结果为新创建了一个字符串对象,反之,返回的是当前对象

    • public String replace(char oldCh, char newCh):将字符串的字符oldCh替换为字符串newCh

    • public int compareTo(Stirng str):

    • //比较两个字符串,如果完全一样,则返回0 //如果长度不相同,返回长度差 //如果长度相同,字符不同,返回第一个不同的字符差

    • public boolean startsWith(String prefix):是否以某个字符串开始

    • public boolean endsWith(String suffix):是否以某个字符串结尾

      		String[] files = {"abc.txt","abb.jpg","bcc.doc","ccc.txt"};
      //		public boolean startsWith(String prefix):是否以某个字符串开始
      		//1、找出以a开头的文件
      		for(String file:files) {
      			if(file.startsWith("a")) {
      				System.out.println(file);
      			}
      		}
      //		public boolean endsWith(String suffix):是否以某个字符串结尾
      		//2、找出以.txt为结尾的文件
      		for(String file:files) {
      			if(file.endsWith(".txt")) {
      				System.out.println(file);
      			}
      		}

    • public boolean contains(String str):是否包含某一个字符串

      //3、找出文件名中有c的文件
      		for(String file:files) {
      			if(file.contains("c")) {
      				System.out.println(file);
      			}
      		}

    • public String [] split(String str):对一个字符串按照指定字符做分割

      //按照参数将原字符串分割成若干份
      		//"name:andy,age:18,score:80"
      		String stuStr = "name:andy,age:18,score:80";
      		//{"name:andy","age:18","score:80"}
      		String[] strings = stuStr.split(",");
      		for (String string : strings) {
      			System.out.println(string);
      		}

    • public byte [] getBytes():返回一个字符串的字节数组形式,数组中存放的是字符串中每个字符的编码,编码方式默认为平台默认编码

    • public byte [] getBytes(字符集编码):返回一个字符串的字节数组形式,数组中存放的是字符串中每个字符的编码,编码方式默认为平台默认编码

    • public String toString():返回当前字符串对象

    • public char[] toCharArray():将一个字符串转换字符数组形式

    • static valueOf(各种数据类型的参数)

  3. 字符串应用

    实例一:判断一个字符串在另一个字符串中出现的次数

    public static int countTimes(String source,String searchStr) {
    		int times = 0;
    		int from = 0;
    		int index = source.indexOf(searchStr,from);
    		while(index>-1) {
    			times++;
    			from = index + 1;
    			index = source.indexOf(searchStr,from);
    		}
    		return times;
    	}

    实例二:判断字符在一个字符串中有没有重复

    实例三:遍历字符串

    实例四:各种转换

    将字符数组转换为字符串的两种方式

    方式一

    char cs[]={'a','b','c'};
    String str=String.valueOf(cs);//"abc"

    方式二:

    char cs[]={'a','b','c'};
    String str = new String(cs);

    将字符串转换为字符数组的方式

    String str="abcde";//将一个字符串转换为char类型的数组
    char cs[]=str.toCharArray();

实例五:

package b_api;

public class App5 {

	public static void main(String[] args) {
	  
		String str2 = "tHis iS A sTuDENT!";
		//将这个英文句子每个单词首字母大写,其他字母全小写
		//1、将这个英文句子全转小写
		//this is a student!
		str2 = str2.toLowerCase();
		//2、获得字符串的字符数组
		char[] charArray = str2.toCharArray();
		//3、循环遍历第0位和空格后面的位置,将字符数组中对应的字符转成大写
		for (int i = 0; i < charArray.length; i++) {
			if(i==0) {
				charArray[0] = (char)(charArray[0]-('a'-'A'));
			}
			if(charArray[i]==' ') {
				charArray[i+1] = (char)(charArray[i+1]-('a'-'A'));
			}
			
		}
		//4、将字符数组转回字符串
		str2 = new String(charArray);
		
		System.out.println(str2);
	}

}

三、String类型的字符串内存分析
  1. 两种创建字符串对象的方式的区别

    String str=”abcde”;//str指向的是常量池中的字符串对象,常量池中没有重复的字符串对象

    String str1=”abcde”;

    sout(str==str1)//true

    String str=new String(“abcde”);//str指向堆里面开辟的新空间

    String str1=new String(“abcde”)

    sout(str==str1)//false

    String str1=new String(“abcde”)

    注意:以下代码创建了几个字符串对象

    String str1=new String(“abcde”)

    如果字符串常量池中没有abcde,就是两个,如果有,就是1个,

    如果是两个。则两个字符串对象的value属性的属性值是一样,value属性存放的是字符串的内容,体现为char类型的数组,

  2. String类型的底层存储结构 String类型的字符串的底层结构,是一个字符类型的数组,并且用final修饰过,String类型的对象有一个重要的属性value,value中存放的是字符数组的地址信息,实际的字符串的内容子啊字符数组中存放

3.String不可变字符串

  • 不可变的现象

    String类型的字符串,不可改变,每次对String类型的字符串对象做修改拼接等操作的时候,都会形成一个新的字符串对象,原有字符串对象的内容不可改变

  • 如何做到不可变的

    底层char []value,用final修饰过,只能被赋值一次,只能指向一个字符数组,如果要更改,只能创建一个新的String类型的对象。

  • 应用场景:如果在某一次操作中,频繁对字符串做修改拼接操作,不适合用String,因为每次修改拼接会形成一个新的字符串对象, 如果只是做遍历,String非常合适

四、String,StringBuffer和StringBuilder
  1. StringBuffer和StringBuilder的区别: StringBuffer线程安全,效率低,StringBuilder线程不安全,但是效率高

  2. String和StringBuffer或者StringBuilder的区别: String为不可变字符串,适合做遍历,不适合频繁拼接修改 StringBuffer或者String和StringBuffer或者StringBuilder的区别可变

  3. 可变性分析

  • 现象

    StringBuffer(StringBuilder)为可变字符串,每次修改拼接不会产生新的StringBuffer(StringBuilder)对象,在原有字符串的基础上做更改,底层有可能产生新的char类型的数组

  • 如果做到可变

    底层的的结构为char [] value,没有用final修饰,可以被多次赋值,所以没有必要再创建新的StringBuffer类型的对象

  • 如果缓冲区满了,会怎么样

    为什么要带缓冲区:为了减少频繁扩容的频率,缓冲区放满的时候要进行扩容,扩容的公value.length*2+2.

  • 应用场景

    适合做频繁拼接修改的场景

    String:对形参的任何操作不会影响实参 StringBuffer:对形参的操作可能会影响实参,前提是形参在操作之前没有指向新的对象。

  1. StringBuffer常用API

    StringBuffer str=new StringBuffer();//缓冲区的默认长度为16
    StringBuffer str=new StringBuffer(5);//缓冲区的默认长度就是5
    StringBuffer str=new StringBuffer("abcde");//缓冲区的默认长度为字符串的长度+16
    System.out.println("字符串内容的长度"+str.length());
    System.out.println("缓冲区长度(本质就是底层字符数组的长度)"+str.capacity());
    StringBuffer sb=new StringBuffer("abcde");
    sb.setCharAt(0, 'A');
    sb.append(true);
    sb.append(1);
    sb.insert(1, "hello");//指定位置插入
    sb.reverse();//翻转字符串
    //将StringBuffer装换为String
    String str=sb.toString();

  2. StringBuffer|StringBuilder和String之间的相互转换

    String转换为StringBuffer|StringBuilde

    String str = "abcde";
    StringBuffer sb = new StringBuffer(str);//构造方法参数为要转换的字符串

    StringBuffer转换为String

    StringBuffer sb = new StringBuffer("abcde");
    String str = sb.toString();

五、三种字符串对照

相同点:都能表示字符串,底层实现都是char类型的数组

不同点:

  1. String类型为不可变字符串,底层的value属性用final修饰过,只能被赋值一次,只能指向一个字符数组。做修改追加的操作的时候,会形成新的字符串(String)对象,所以不太适合频繁做修改,适合遍历

  2. StringBuffer和StringBuilder,可变字符串,底层value属性没有用final修饰过,可以被多次赋值,可以在不同时间指向多个字符数组,修改追加等操作的时候,不能形成的新的StringBuffer|StirngBuilder类型的对象,适合做修改,

  3. StringBuffer线程安全,StringBuilder线程不安全

六、什么样的字符串在字符串常量池中

减少频繁创建销毁对象的频率,提高了单个对象的利用率

什么样的字符串会放在常量池中

  1. 字符串的字面量

  2. 用+连接的结果,但是前提是+两边都是字面量或者是常量(final)

文章来源:https://blog.csdn.net/Fxdll/article/details/135612518
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。