java数据类型浅析之字符串(二)

Java字符串.png

关于作者的更多博客请访问

云里云外开源社区

一;不可变字符串String 两种创建方式

第一种

String handle = new String([string_content]);
Handle句柄,[]表示可写可不写。

我先分析一下这段代码
1、new String;指的是在堆空间中创建一个String类型对象
2、末尾的([string_content]);调用String类的构造方法初始化值为"string_content"(值随意)
3、String handle;在栈中声明一个String类的,名为"handle"的句柄,注意它不是对象(对象引用)(String类型的句柄只能指向String类型的对象)
4、"="将对象引用指向在堆内存中创建的String类型的对象

基本含义理解后大家再回看这幅图
内存图解.png
例 、创建对象形式
String s= new String(“china”);
先去常量池中找是否有China
若无;则在池中创建一个"china"对象,再去堆中创建一个常量池中的此对象的拷贝对象,再去栈中开辟名为“s”的空间,存放此对象的链接地址。(此时的S,就是句柄)
若有;去堆中创建一个常量池中的此对象的拷贝对象,再去栈中开辟名为“s”的空间,存放此对象的链接地址。

问题1,这段代码String s= new String(“china”);究竟创建了几个String对象?它们分别是?

答案;1或2个,分别是(常量池中的China)和堆中的China,若常量池已有China,则为1
我们继续
String y= new String(“china”);
这个显然是成立的,不会报错,这样我们就得出。一个对象可以有多个(N个)对象的引用
String y= new String(“ShanXi”);
这样对象的引用就会重新指向"ShanXi"。
//y句柄改变了指向,指向了常量池中的ShanXi,而china则会成为虚拟机的垃圾回收机制的对象,在未来的某时被吸收
String y;?在这里声明了一个对象的引用,但并没有明确指向,但编译器不会报错。
综上所述,一个对象的引用可以指向1或0个对象。一个对象可以有N个对象的引用
所以也可以这样表示
String y;
y = new String(“china”);

第二种、直接赋值

2、String d= “china”;
先去常量池中找是否有China
若无;则在池中创建一个"china"对象,再去栈中开辟名为“d”的空间,存放此对象的链接地址。
若有;去栈中开辟名为“d”的空间,存放此对象的链接地址。

问题2,这里创建了几个对象呢?

所以第二种方式可能创造0或1个对象

第三个问题
String s = “a” + “b” + “c” + “d” + “e”; 创建了几个对象呢?

代码被编译器在编译时优化后,相当于直接定义了一个”abcde”的字符串,所以,上面的代码应该只创建了一个String对象

重要方法intern();

返回字符串对象的规范化表示形式。
用人话说就是获取对象在常量池中的值,当然它还有更深层次的用法,我也不太会….
利用这个方法可以很好理解字符串特别是常量池的概念

Stringhandle3=newString("TYUT");
Stringhandle4=newString("YunDing");
System.out.println(handle3.intern());
System.out.println(handle4.intern());

答案:
TYUT
YunDing

二、可变字符串StringBuffer

由于我对这个接触很少,就总结一下构造方法,其他的方法大家可以自行百度

StringBuffer的构造方法:

StringBuffer():无参构造的形式,初始容量为16
StringBuffer(int capacity):指定容量构造一个字符串缓冲区
StringBuffer(String str):构造一个字符串缓冲区,将指定的字符串内容作为其初始化内容,长度为16加上str的长度
例、

StringBuffera=newStringBuffer("abc");
StringBufferb=newStringBuffer();
System.out.println(a.capacity()); 
System.out.println(b.capacity());

结果分别是19和16

三、(字符串的)比较方法

这一篇先说字符串的,后面再到其他数据类型的比较
两种比较方式“ == ”和equals()
• “==”;分为比较基本数据类型和引用数据类型
基本数据类型比较的是值;引用数据类型比较的是内存地址

• equals();这个方法是Object类中的方法,Object是java默认提供的一个类,如果一个类没有明确指定继承关系,那么它将继承Object,也就是可以使用它规定的方法。
(1)不能比较基本数据类型。
(2)equals()在Object类中是比较对象的内存地址。

public boolean equals(Object obj){
	return(this==obj);
}

而在String类中已经将equals()重写,比较的是对象的值(常量池中的值)

public boolean equals(Object anObject){
	if(this == anObject){
	return true;
	}
	if(anObject instanceof String){
	String aString = (String) anObject;
	if(!COMPACT_STRINGS||this.coder==aString.coder){
	return StringLatin1.equals(value,aString.value);
	}
	}
	return false;
}

如果理解了之前的内容,只要你不记混这两种比较方式,那你应该理解了字符串的比较。给大家一些例子,可以尝试做一下,后面是输出结果供对照

//先比较newString();产生的
//内容相同,结果第一个false,第二个显然true
String handle = newString("ShanXi");
String handle2 = newString("ShanXi");;
System.out.println("handle和handle2相等吗?"+(handle==handle2));
System.out.println("handle和handle2相等吗?"+(handle.equals(handle2)));
 
//内容不同,结果显然均为false
String handle3 = newString("TYUT");
String handle4 = newString("YunDing");
System.out.println("handle3和handle4相等吗?"+(handle3==handle4));
System.out.println("handle3和handle4相等吗?"+(handle3.equals(handle4)));
 
//再比较直接赋值型
//内容不同,结果显然均为false
String handle5 = "java";
String handle6 = "python";
System.out.println("handle5和handle6相等吗?"+(handle5==handle6));
System.out.println("handle5和handle6相等吗?"+(handle5.equals(handle6)));
//内容相同,结果显然均为true,因为两者都指向同一个内存地址,位于常量池
String handle7 = "java";
String handle8 = "java";
System.out.println("handle7和handle8相等吗?"+(handle7==handle8));
System.out.println("handle7和handle8相等吗?"+(handle7.equals(handle8)));
 
//混合比较
//内容相同,第一个返回false,因为handle9的地址是在堆中,handle8是在常量池中。第二个返回true
String handle9 = newString("java");
System.out.println("handle9和handle8相等吗?"+(handle9==handle8));
System.out.println("handle9和handle8相等吗?"+(handle9.equals(handle8)));
//intern()返回字符串对象的规范化表示形式。通俗一点说,就是返回对应这个字符串内容的那个pool里的对象
System.out.println("handle9和handle8相等吗?"+(handle9.equals(handle8.intern())));
 
//内容不同
String handle10 = newString("js");
System.out.println("handle10和handle8相等吗?"+(handle10==handle8));
System.out.println("handle10和handle8相等吗?"+(handle10.equals(handle8)));

• 输出结果如下:

handle和handle2相等吗?false
handle和handle2相等吗?true

handle3和handle4相等吗?false
handle3和handle4相等吗?false

handle5和handle6相等吗?false
handle5和handle6相等吗?false

handle7和handle8相等吗?true
handle7和handle8相等吗?true

handle9和handle8相等吗?false
handle9和handle8相等吗?true
handle9和handle8相等吗?true

handle10和handle8相等吗?false
handle10和handle8相等吗?false
最后附上参考链接
字符串常量池
字符串拼接内部实现
字符串创建对象面试问题
StringBuffer相关资料

发布了5 篇原创文章 · 获赞 3 · 访问量 159

猜你喜欢

转载自blog.csdn.net/L1142456160/article/details/104979940
今日推荐