Java基础18-String类【String类的特点&对象个数&常用方法】【超详细讲解】

Java基础-String类【超详细讲解】

String类的特点

String在java.lang.String包中

1:特点

(1)String类型不能被继承,因为由final修饰
(2)String类型的对象是不可变:换句话说,只要修改字符串,就会产生新对象

package com.rh.bean;

import org.junit.Test;

public class Shipin07 {
   @Test
	public static void main(String[] args) {
		// TODO Auto-generated method 
//		String s1="hello";
//		s1="word";
//		s1=s1+"java";

		String s="";
		change(s);
		System.out.println(s);
		
	}
	public static void change(String str) {
		str="hello";
	}

}

只要字符串改变,例如拼接,就会产生新对象

(3)String对象不可变的特性,使得我们可以把一些字符串存到常量池中。字符串有常量池。常量池中的对象是可以共享的。

@Test
	public void test02(){
		String s1 = "hello";
		String s2 = "hello";
		
		System.out.println(s1 == s2);
	}

返回true,这样可以节省些内存,常用的字符串可以保存起来,不用每次更新,也节省内存

**字符串常量池在哪里?**面试
以下存储情况为Oracle官方虚拟机HoySpot,不同虚拟机可能不同
常量的东西都存在方法区里。但字符串常量比较大,所以:
1:JDK1.6及以前:方法区
2:JDK1.7:挪到堆中,即在堆中单独划分了一块来存储字符串常量
3:JDK1.8:从堆中挪出,挪到一个“元空间meta space”,即类似 于方法区
补充:元空间meta space在内存中,甚至可以独立于java虚拟机,为了节省虚拟机的空间,因为字符串常量很多,且生命周期很长,会一直占用内存,所以挪出来

(4):String对象底层的存储
1:JDK1.9之前:底层是用char[]存储
在这里插入图片描述

2:JDK1.9之后:底层选用byte[]存储:因为byte数组更接近于二进制的处理
注意:
目前还是char[],所有的操作还是char数组来操作,目前使用的还是JDK1.8

(5)String对象怎么就不可变
1:底层char[]数组有final修饰,意味着这个数组不能扩容等,来达到存更多的字符(不能增加)
2:char[]数组是私有的,我们程序员无法直接操作这个char[]数组,而且String没有提供这样的方法来修改char[]数组的元素的值(不能修改)
String提供的所有的方法,对字符串的修改都是给你返回一个新的字符串对象

String对象的比较

字符串的比较
(1)==:比较对象的地址

  String s1="hello";
       String s2="hello";
       System.out.print(s1==s2);

在这里插入图片描述
注意:只有两个字符串的常量对象比较才会返回true,其他的都是false
例如:

     String s1=new String("hello");
       String s2="hello";
       System.out.print(s1==s2);

在这里插入图片描述

	String s1=new String("hello");
      String s2=new String("hello");
       System.out.print(s1==s2);

在这里插入图片描述
(2)equals:比较字符串的内容(严格区分大小写):因为String类型重写了Object的equals

	@Test
	public void test04(){
		String s1 = new String("hello");
		String s2 = new String("hello");
		System.out.println(s1.equals(s2));//true
		
		String s3 = "hello";
		System.out.println(s3.equals(s1));//true
		
		String s4 = "Hello";
		System.out.println(s3.equals(s4));//false
	}

(3)equalsIgnoreCase(String anotherString):比较字符串的内容(不区分大小写)

@Test
	public void test05(){
		String s1 = new String("hello");
		String s2 = new String("hello");
		System.out.println(s1.equalsIgnoreCase(s2));//true
		
		String s3 = "hello";
		System.out.println(s3.equalsIgnoreCase(s1));//true
		
		String s4 = "Hello";
		System.out.println(s3.equalsIgnoreCase(s4));//true
	}

(4)大小比较:严格区分大小写
String类型实现了Comparable接口,重写了compareTo(Object obj)方法,严格区分大小写
在这里插入图片描述

错误写法
/*	if(s1 > s2){//不能直接使用比较运算符
			
		}*/

应写为:

@Test
	public void test06(){
		String s1 = new String("hello");
		String s2 = new String("helloworld");
		
	/*	if(s1 > s2){//不能直接使用比较运算符
			
		}*/
		
		if(s1.compareTo(s2) > 0){
			System.out.println(s1 + ">" + s2);
		}else if(s1.compareTo(s2) < 0){
			System.out.println(s1 + "<" + s2);
		}else{
			System.out.println(s1 + "=" + s2);
		}
		
	}

在这里插入图片描述
依次比较对应位置的字符
hello和Hello,先[0]位置的h和H,h>H(ACSII码大32),直接认定为hello大于 Hello
hello和hella,先[0]、[1]、[2]、[3]比较,都一样,最后到[4] o>a,认定hello大于helloa
hello和helloword:前面都一样,长的大

补充:
对象的比较两种:
1:自然排序:
实现java.lang.Comparable接口,int compareTo(Object obj)

2:定制排序

(5)大小比较,不区分大小写
String 类型提供了一个方法compareToIgnoreCase,可以忽略大小写

@Test
	public void test07(){
		String s1 = new String("hello");
		String s2 = new String("Hello");
		
		if(s1.compareToIgnoreCase(s2) > 0){
			System.out.println(s1 + ">" + s2);
		}else if(s1.compareToIgnoreCase(s2) < 0){
			System.out.println(s1 + "<" + s2);
		}else{
			System.out.println(s1 + "=" + s2);
		}
		
	}

在这里插入图片描述
用处:

	@Test
	public void test08(){
		String[] arr = {"hello","chai","Java","Alice","Hi"};
		//排序
		//按照字母的顺序排列
		Arrays.sort(arr);//按照元素的自然顺序排序
		System.out.println(Arrays.toString(arr));
	}

在这里插入图片描述
不区分大小写写法

@SuppressWarnings("all")
	@Test
	public void test09(){
		String[] arr = {"hello","chai","Java","Alice","Hi"};
		//排序
		//按照字母的顺序排列,不区分大小写
		Arrays.sort(arr,new Comparator(){

			@Override
			public int compare(Object o1, Object o2) {
				String s1 = (String) o1;
				String s2 = (String) o2;
				return s1.compareToIgnoreCase(s2);
			}
			
		});//按照元素的自然顺序排序
		System.out.println(Arrays.toString(arr));
	}

在这里插入图片描述

以上都是针对字母的,若是汉字
若是自然排序

@Test
	public void test10(){
		String[] arr = {"柴林燕","张三","李四","崔志恒","甄玉禄"};
		Arrays.sort(arr);//按照自然顺序,按照每一个字符的Unicode编码值排序的
		System.out.println(Arrays.toString(arr));
	}

在这里插入图片描述
上图按Unicode编码排序,自然排序

若是要按拼音排序,用定制比较,所以

(6)按照每个国家的语言校队顺序
java.text.Collator,Collator类执行区分语言环境的String比较,使用此类可为自然语言文本构建搜索和排序例程。
Collator实现了Comparator接口
Collator是抽象类,不能直接创建对象,它有一个直接子类RuleBasedCollator
Collator内部提供了一个静态方法,可以获取一个它的子类对象
在这里插入图片描述

@Test
	public void test11(){
		String[] arr = {"柴林燕","张三","李四","崔志恒","甄玉禄"};
		//希望按照拼音顺序,字典顺序
		Arrays.sort(arr, Collator.getInstance());//默认语言环境,因为我现在的操作系统的平台是中文win
		System.out.println(Arrays.toString(arr));
	}

在这里插入图片描述
汉字有多音字,有时结果会不正确,大多数情况下是正确的,用的是哈希字典的排序规则,基本是按照拼音的顺序排序的

这里有个语言环境,上图为默认语言环境,因为我现在的操作系统的平台是中文的windows,所以默认按照,但若是平台是跨平台的效果,比如在国外的电脑上运行,还是想要中文的排序,可以写成如下:

public class TestString02 {
	@Test
	public void test12(){
		String[] arr = {"柴林燕","张三","李四","崔志恒","甄玉禄"};
		//希望按照拼音顺序,字典顺序
		Arrays.sort(arr, Collator.getInstance(Locale.CHINA));//Locale.CHINA指定语言环境
		System.out.println(Arrays.toString(arr));
	}

可以指定语言环境
补充:在这里插入图片描述
如图:Locale里有很多国家

String对象个数、拼接结果等

面试题:
1:对象个数
(1)String str=new String(“hello”);几个对象–》2个字符串个

@Test
	public void test01(){
		String str = "hello";//一个字符串对象
	}
@Test
	public void test02(){
		String str = new String("hello");//两个字符串对象
		//一个在常量池中:hello
		//另一个在堆中,String的对象
		//堆中的这个字符串对象char[]的value数组,指向常量池中"hello"的char[]的value
	}

看源码:
在这里插入图片描述
在这里插入图片描述
value 就是chas[]数组,original就是hello
表示当前对象的value等于hello的value
不分那么细,就说常量池在方法区也没错
内存图:
【
(2)String str=new String(“hello”)
String str=new String(“hello”)
几个对象–》三个对象
常量池的hello共享的,new String分别指向一个对象

@Test
	public void test03(){
		String str1 = new String("hello");
		String str2 = new String("hello");
		
		//这两行代码,几个对象?3个
	}

2:拼接的结果是在堆还是常量池中?
因为只有常量池才是共享,==比较才为true

(1)常量+常量在常量池
(2)常量+变量在堆
(3)变量+变量在堆
(4)xx.intern(),在常量池

@Test
	public void test04(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = s1 + "world";//s4字符串内容也helloworld,s1是变量,"world"常量,变量 + 常量的结果在堆中
		String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是变量,变量 + 变量的结果在堆中
		String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
		
		System.out.println(s3 == s4);//false
		System.out.println(s3 == s5);//false
		System.out.println(s3 == s6);//true
	}

在这里插入图片描述

@Test
	public void test05(){
		final String s1 = "hello";
		final String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = s1 + "world";//s4字符串内容也helloworld,s1是常量,"world"常量,常量+ 常量 结果在常量池中
		String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是常量,常量+ 常量 结果在常量池中
		String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果
		
		System.out.println(s3 == s4);//true
		System.out.println(s3 == s5);//true
		System.out.println(s3 == s6);//true
	}

在这里插入图片描述

@Test
	public void test06(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = "helloworld";
		
		String s4 = (s1 + "world").intern();//把拼接的结果放到常量池中
		String s5 = (s1 + s2).intern();
		
		System.out.println(s3 == s4);//true
		System.out.println(s3 == s5);//true
	}

在这里插入图片描述

3:空字符串:三种
第一种:" "
第二种:new String()
第三种:new String(" ")

(1):

String s1 ;//局部变量未初始化,访问不了,无法使用,若是成员变量,默认值为null,可以访问
System.out.println(s1);报错,访问不了,无法使用

(2)

String s2=null;//初始化为null
System.out.println(s2.length());//编译能过,运行空指针异常

null没办法调用方法这些

(3)

	String s3="";//空字符串常量对象
	String s4=new String();//空字符串对象
	String s5=new String("");//两个对象,一个常量池中的,一个堆中的

这三个都是字符串对象,都是空字符串

	String s3="";//空字符串常量对象
	String s4=new String();//空字符串对象
	String s5=new String("");//两个对象,一个常量池中的,一个堆中的
	
	System.out.println(s3.length());
	System.out.println(s4.length());
	System.out.println(s5.length());

在这里插入图片描述

如何判断空字符串?四种方式,推荐第三种
第一种方法:
在这里插入图片描述
有风险,若是test08方法里传入null,运行时会报空指针异常
应该为:先判断一下
在这里插入图片描述
输出null
第二种方法:
在这里插入图片描述
在这里插入图片描述
第三种方法:
在这里插入图片描述
在这里插入图片描述
和上一种写法相比,不用判断是否为空,推荐
因为“”.equals(str)中的" "是一个常量,常量一定为非空对象,顶多str为null,返回false而已,运行不会报空指针异常
规范:有常量和非常量比较的时候,将常量对象放在前面

第四种:
在这里插入图片描述
在这里插入图片描述
总结:怎么优化?第三种最好
在这里插入图片描述

String的常用方法(一)

在这里插入图片描述
方法系列一:
(1)int length():返回字符串的长度,返回的是字符的个数。因为String的内部(JDK1.9之前)用char[]实现,这个长度就是value数组的长度
(2)boolean isEmpty():是否是空字符串
(3)String toLowerCase():
String toUpperCase()

@Test
	public void test1(){
		String str = "hello";
		System.out.println(str.toUpperCase());
	}

在这里插入图片描述
只针对字母的大小写,将字符串中的大写字母(小写字母)转换为小写字母(大写字母),数字、汉字等没有

(4)String trim():去掉字符串的前后空白符
在这里插入图片描述
在这里插入图片描述
没去掉,原因:字符串任何修改都会产生新的对象,需要接收这个新对象
应该为:
在这里插入图片描述
在这里插入图片描述
另外定义一个变量接收也行,反正就是要先接收这个新对象才能使用新对象
用在什么地方?
经常当web页面向服务器端传输数据时,经常会对传输的数据trim()一下,因为用户可能在输入数据的时候,不小心在前面后面输入空格,用这个方法把它去掉,经常在判断的时候加入trim()

(5)String concat():拼接,等价于+

@Test
	public void test3(){
		String s1 = "hello";
		String s2 = "world";
		String s3 = s1 + s2;
		String s4 = s1.concat(s2);
		
		System.out.println(s3 == s4);//false
		System.out.println(s3.equals(s4));//true
	}

在这里插入图片描述

String的常用方法(二)

方法系列二:和char相关

1char[]   toCharArray()

在这里插入图片描述
在这里插入图片描述

(2)char charAt(index)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

(3)String(char[] arr)

将字符数组变为字符串
在这里插入图片描述
在这里插入图片描述

(4)String(char[] arr,int offset,int count)

将部分的字符数组变为字符串
在这里插入图片描述
在这里插入图片描述

String的常用方法(三):

方法系列三:和byte相关,或者说和编码与解码相关

**(1)

编码:byte[] getBytes():编码的方法,使用平台默认的字符编码进行编码的
    byte[] getBytes(编码方法):可以设置编码方法

编码:
对于ASCII码范围内(0~127)无论用什么编码方式,结果都是一样的,一个字符对应一个字节的编码值
对于其他的字符,编码结果不一定是几个字节,例如汉字
UTF-8:变长的,但是大多数汉字都是3个字节
GBK、GB2312:固定的两个字节
ISO8859-1:不支持中文,所有字符都编为1个字节

编码:
把字符–》字节的过程,编给计算机用的
解码:
把字节–》字符的过程,解给人看的

在这里插入图片描述
在这里插入图片描述
变成编码值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以0开头的,一个字节,以110开头的,两个字节构成一个字符,以1110开头的,三个字节构成一个字符,以此类推

GBK、GB2312编
在这里插入图片描述
在这里插入图片描述
一个汉字两个字节

**ISO8859-1编**

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ISO8859-1转不回来,因为之前编的时候截掉了一部分

不指定编码也不行
String string =new String(bytes);也一样转不回来

而GBK、utf-8可以
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)解码方法

new String(字节数组)
new String(字节数组,编码方式)

乱码情况两种原因:
1:编码与解码字符集不一致
在这里插入图片描述
在这里插入图片描述
解不回来
2:缺字节
在这里插入图片描述
会丢掉一些字节,汉字至少两个字节

String的常用方法(四)

方法系列(4)
(1)boolean startsWith(xx)
(2) boolean endsWith(xx)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

可以多个字
在这里插入图片描述
在这里插入图片描述

String的常用方法(五)

方法系列:和查找有关

1)是否包含
        boolean contains()

在这里插入图片描述
在这里插入图片描述

2int indexOf(xx)
            告诉是第几个位置,如果存在返回下标,如果不存在返回-1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
若是两个点,返回第一个点的位置

3int   lastIndexOf(xx):
        告诉最后一个xx是第几个位置,如果存在返回下标,如果不存在返回-1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

String的常用方法(六)

方法系列6:和截取相关

1)String substring(int beginIndex):从字符串的[beginIndex]截取到最后
2)  String substring(int beginIndex,int endIndex):
截取字符串的[beginIndex,endIndex)部分

在这里插入图片描述
在这里插入图片描述

String的常用方法(七)

方法系列7:匹配规则

e.g:判断一个字符串是否全是由数字组成,并且第一位不能是0,长度为9位

解决方法:可以转换为一个字符数组,一个一个的比较,但太麻烦,用matches方法简洁
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

matches(正则表达式)

正则表达式:用于检测文本的格式
校验某个字符串是否符合xx规则
例如:电话号码:甚至可以校验是不是移动号…
银行卡号
邮箱格式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

String的常用方法(八)

方法系列8:替换
(1)String replace(target,value)
(2) String replaceAll(String regex,String replacement)
(3)String replaceFirs(String regex,String replacement)
其中2和3支持正则
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

String的常用方法(九)

方法系列9:拆分
String [] split(xx)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
前面多了一个空字符串
解决方法:去掉位于前面和后面的数字
在这里插入图片描述
在这里插入图片描述
e.g:
有一个student类
在这里插入图片描述
在这里插入图片描述
拆分不对:因为|在正则中是有特殊意义,我这里要把它当成普通的|,用|,转一次为正则的转义,在java中\还要再转义一次,第一次转|,第二次转\,所以\|
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
面试中经常考|和.的转义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值