字符串及其延伸

一、字符串常量池

字符串常量池的存放位置

  • jdk6.0 字符串常量池是在方法区中

  • jdk7.0 从方法区中移除,字符串常量池存放到堆空间中

  • jdk8.0及之后 虚拟机规范中声明了元空间,字符串常量池存放到元空间中

    备注:元空间是指本地内存除了为jvm开辟空间之外的额外本地内存

字符串常量池的概念

字符串常量池是java一项技术,从字面意思理解就是把经常用的数据存放到某一个内存当中,本质意义是避免频繁的数据创建与销毁,实现数据共享,提供系统性能。

public class Test{
	public static void main(String[] args){
		String a = "123";
		String b = "123";
		System.out.println(a==b);
	}
}
//输出结果 true

上面代码,在内存中是干了什么?

 

因为a和b指向同一个对象,所以a==b是true,那么看下述代码执行结果:

public class Test{
	public static void main(String[] args){
		String a = new String("123");
		String b = "123";
		System.out.println(a==b);
	}
}
//输出结果 false

执行结果是false,内存中又干了啥?  

 当我们用new 关键字创建字符串对象时,会先在堆中开辟内存空间,然后,在该内存中存放我们在字符串常量池中的数据地址

二、字符串拼接

public class Test{
	public static void main(String[] args){
		String a = "123";
		String b = "456";
		String c = "123456";
		String d  = a+b;
		System.out.println(c==d);
	}
}

字符串+字符串(拼接)底层是靠StringBuilder的append和toString方法实现。

toString方法源码如下:

可以看到new ,所以输出false,但是如下代码又是什么结果呢?

public class Test{
	public static void main(String[] args){
		String a = "123"+"456";
		String c = "123456";
		System.out.println(a==c);
	}
}
//输出true

之所以为true,是因为jvm编译阶段编译器优化后把字符串常量直接合并成“123456”

三、子串

String类的substring()从一个字符串中提取一个子串:

public class Test{
	public static void main(String[] args){
		String a = "Hello World!";
		String b = a.substring(0,7);
		System.out.println(b);
	}
}
//输出 Hello W

备注:substring方法第二参数不写,截取到结尾

四、空串和Null串

空串是一个对象,有自己串长度(0)和内容(空),可以用以下代码来检测:

public class Test{
	public static void main(String[] args){
		String a = "";
		if(a.length()==0 || a.equals(""))
			System.out.println("是空串");
		}
}

String变量还可以存放一个特殊值,名为null,即Null串

五、== 和equals的区别

  • 基本数据类型,也原始数据类型:

    他们之间比较,应用双等号(==),比较是他们的值

  • 引用数据类型

    当他们用(==)进行比较时,比较的是他们的内存中的存放地址,所以,除非是同一个new出来的对象,他们比较的结果是true,否则就是false。Object类中定义一个equals方法,该方法是比较的内存地址,但是有些子类覆盖了该方法,目的是提高字符串等值比较的场景,提高实际使用价值,比如String等equals方法:

    • 首先比较地址,如果地址相同,就返回true

    • 如果字符串地址不相同,name首先会判断要比较的参数类型是否是String,如果是,再比较两者的长度,如果长度相同,再对位比较每一个字符值是否相同,如果相同,则返回true

 

六、String常见的一些方法(api)

  • 获取String 的长度length()

    String a = "12345"
	int len = a.length();
	System.out.println(len);
5

用charAt()获取String中的指定索引位置的代码单元(值 | 字符)

String a = "12345"
	char.res = a.charAt(2);
	System.out.println(res);
3

用codePointAt()获取指定索引位置的代码点(编号)

String a = "abcd"
	int rescode = a.codePointAt(0);
	System.out.println(rescode);
a
  • substring()截取子串

  • equals()判断字符串是否相等

  • contains()判断是否包含目标串

  • indexof()获取目标串第一次出现位置的的索引值

  • endswith()判断是否是指定字符串结尾

返回的值是true或false

startswith()判断是否是指定字符串开头

  • concat()做字符串连接

String a = "123"
String b = "456"
String index = a.concat(b)
System.out.println(index)
//123456

toLowerCase()返回一个新的字符串,新字符串是把所有大写字母变成小写

String a = "ABC"
String index = a.toLowerCase()
System.out.println(index)
//abc
  • toUpperCase()返回一个新的字符串,新字符串是把所有小写字母变成大写

  • split()按照指定分隔符拆分字符串成字符串数组

  • trim()返回一个新字符串,该字符串是删除原始字符串开头和结尾的空格

七、可变字符串

StringBuffer 线程安全 适合多线程 慢

StringBuilder 线程不安全 适合单线程 快

StringBuffer 与 StringBuilder的方法一致,以StringBuilder 为例,列出一些常用方法(api)

 

  • delectCharAt(0) 指定位置删除

  • setCharAt(0,'r')指定位置修改

  • reverse()反转打印

测试下StringBuilder与String,在字符串拼接方面的性能,代码如下:

 

public class StringDemo {
	public static void main(String[] args) {
		String str ="";
		long start  = System.currentTimeMillis();
		for(int i=0;i<100000;i++) {
			str+="第"+i+"元素";
		}
		long end = System.currentTimeMillis();
		System.out.println("String需要的时间是"+(end-start)+"ms");
		
	

		StringBuilder str1 = new StringBuilder("");
		long start1  = System.currentTimeMillis();
		for(int i=0;i<100000;i++) {
			str1.append("第"+i+"元素");
		}
		long end1 = System.currentTimeMillis();
		System.out.println("StringBuilder需要的时间是"+(end1-start1)+"ms");
	}

}

总结:

如果不频繁修改字符串时,建议使用String

如果在单线程下,需要频繁修改字符串时,建议使用StringBuilder

如果在多线程下,需要频繁修改字符串时,建议使用StringBuffer

悲观锁:悲观思想,即认为写多,遇到并发写的可能性很高,每次去拿数据的时候都认为被人修改,所以,会在一个线程使用共享数据之后,不再让其他任何现成使用该共享数据

悲观锁:乐观思想,即认为读多,遇到并发写的可能性很低,每次去拿数据的时候都认为不会被人修改,所以,不会锁住共享资源,而是使用版本号机制来保证线程安全(在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,如果两次版本号一致,则写入,否则放弃写入)

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值