前言
加油!
我将发布一系列Java学习日记,帮助读者学习和巩固Java技术,希望各位多多支持,这是我Java系列第一篇,决定从String类开始讲起,结合开发经验和CSDN上的java相关课程,写成文章。
Java笔试题中很可能出现关于String类的考点。
一.String类的实例化方式
String并不是一个基本数据类型,实际上是一个类,但是这个类在设计的过程之中加入了Java自己的特殊支持,所以对于这个类的对象实例化的方式就有两种形式:
public class javatest1 {
public static void main(String args[]){
//直接赋值:String 对象="内容"
String str1="Hello";
//构造方法:public String(String s)
String str2=new String("Hello");
System.out.println(str1);
System.out.println(str2);
}
}
二.字符串的比较
(1)两种比较方式
比较有两种方式,一种是==,另一种是equals(),简单来说一个比较内存地址,一个比较内容。
public class javatest1 {
public static void main(String args[]){
String stra="RMB";
String strb=new String("RMB");
String strc=strb;
//==是java本身提供的关系运算符,可以进行数值比较,如果用在String上表示对象内存地址数值比较
System.out.println(stra==strb);
System.out.println(strb==strc);
System.out.println(strc==stra);
//equals()是String类自己定义的方法,用于进行字符串内容的比较
System.out.println(stra.equals(strb));
System.out.println(strb.equals(strc));
System.out.println(strc.equals(stra));
}
}
结果为
false
true
false
true
true
true
我们会发现一个问题,即strb和stra地址是不一样的,在定义stra和strb时,实际上是开辟了两个新的堆内存,stra和strb在栈内存中分别指向这两个新的堆内存,所以==比较是false。
(2)对象池(object pool)
但是,如果三个字符串对象直接赋值,我们会发现即便是地址也是相同,这就涉及到了对象池的概念,代码如下:
public class javatest1 {
public static void main(String args[]){
String sta="RMB";
String stb="RMB";
String stc="RMB";
System.out.println(sta==stb);
System.out.println(stb==stc);
System.out.println(stc==sta);
System.out.println(sta.equals(stb));
System.out.println(stb.equals(stc));
System.out.println(stc.equals(sta));
}
}
在java设计中为了方便用户的代码编写开发,针对于几个特殊的类使用了共享设计的思路,String属于其中一员。
这种设计思路是java自己的支持,而且只针对于直接赋值的情况,在使用直接赋值实例化String类对象的操作中,字符串的内容定义之后实际上会自动将其保存在一个对象池中,而后如果现在有其他的字符串对象也采用了直接赋值的形式,并且内容与之前的字符串内容完全相同,那么不会开辟新的堆内存空间,而是通过对象池找到已有的堆内存空间地址,直接引用即可,所以就会造成若干个字符串直接赋值之后,当内容相同时,地址是完全相同的,所以“==”的结果也是相同的,这就是所谓的共享设计模式。
三.String匿名对象
(1)String类的匿名对象
任何编程语言都不会提供字符串这一数据类型,字符串的描述在很多语言之中都使用字符数组表示。而在java的设计之初为了解决这样的问题,专门提供了一个String类来进行描述,但随着发展,为了让程序变得更加易于开发,所以在java里面也提供双引号声明的数据,而这些数据在java中并不是普通的变量,而是属于String类的匿名对象。
那么,啥叫匿名对象呀?不废话我们直接上代码。
class Person{
String name;
int age;
}
public class javatest1 {
public static void main(String args[]){
//创建一个普通对象
Person p = new Person();
//创建一个匿名对象
new Person();
//匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量。
}
}
具体到字符串中来看:
public class javatest1 {
public static void main(String args[]){
String str="RMB";
System.out.println("RMB".equals(str));
}
}
通过"RMB"竟然就可以直接调用equals方法,也因此,字符串确实是String类的匿名对象。
因此我们可以很幽默的理解一下
String str="RMB";
这个代码的本质是为一个字符串的匿名对象(也就是“RMB”)起了一个名字(这个宝宝叫作str,并给了家庭地址)。
(2)开发中的习惯
我们现在来到具体开发中看一下,如果你的开发有这样一种需求:用户输入一些指令,而后根据输入指令判断要执行操作。此时存在两种做法:
做法一:利用String变量调用equals()方法,废话少说,上代码!
public class javatest1 {
public static void main(String args[]){
String input="run";//假设为输入数据
if(input.equals("run")){
System.out.println("**************系统开始运转*********");
}
}
}
但是,但是,但是,既然input的内容是由用户输入的,那么就有可能不输入。如果不输入内容就有可能为null,则null调用equals方法就有可能出现错误(NullPointerException)。
做法二:
直接上代码:
public class javatest1 {
public static void main(String args[]){
String input=null;//假设为输入数据
if("run".equals(input)){
System.out.println("**************系统开始运转*********");
}
}
}
没错,发现了吧,“run”和input换了位置。首先字符串的匿名对象永远不可能是null,并且在equals方法里面支持有null的验证,也就是说“”下肯定不为空,那就可以调用equals方法,并且equals方法又可以和null比较,会返回false,因此这样不会报错。
因此,要记住
字符串常量=String类的匿名对象
比较字符串内容是否相同时,将常量写在前面
总结
各位自己尝试做一下,发在评论区打卡(如果可以的话哈哈哈),关于对象池和构造方法,下一节会讲的更深,敬请期待~~~~