Java——String类使用详解(实例化、字符串比较、匿名对象、两种实例化方法的区别)

时间:2022-07-25
本文章向大家介绍Java——String类使用详解(实例化、字符串比较、匿名对象、两种实例化方法的区别),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1、String类的两种实例化方式

String类不是一个基本数据类型,它是一个类,这个类设计过程种加入了Java的特殊支持,其实例化形式有两种形式:

  • 直接赋值: String 对象 = “内容”;
  • 构造方法:public String (String s);

以上两种方式均可用,但是具体还是有一些区别。

2、字符串比较

对于int类型数据,两个直接赋值的变量使用“ ==”可以进行想等判断,但是对于String类型数据却不能这样直接比较,见如下范例:

String stra = "hello";
String strb = new String("hello");
String strc = strb; //引用传递
System.out.println(stra==strb);  //false
System.out.println(strb==strc);  //true
System.out.println(stra==strc);  //false

以上三个字符串内容一致,但是使用==比较,发现有的比较结果却是false。实际上这里的比较 实际上比较的是两个对象(任意的引用类型)的堆内存的地址数值,属于数值内容的比较,并非堆内存种保存内容的比较。

若要对两个字符串进行比较,可以使用String类中的一个方法:public boolean equals(String str)。

String stra = "hello";
String strb = new String("hello");
String strc = strb; //引用传递
System.out.println(stra.equals(strb));  //true
System.out.println(strb.equals(strc));  //true
System.out.println(stra.equals(strc));  //true

【经典问题】String 比较中 == 与equals的区别?

  • "=="是关系运算符,可以进行数值比较,如果用在String上,表示对象内存地址数值比较,不能比较内容。
  • equals是String类自己定义的方法,用于进行字符串内容的比较。

3、String匿名对象

任何编程语言都不会提供字符串数据类型,字符串在很多语言中使用字符数组,Java中为解决这个问题,提供了String类,Java里面也提供双引号声明的数据,这些数据不是普通的变量,而是属于String类的匿名对象。

【举例】:验证匿名对象

String str = "hello";
System.out.printlin("hello".equals(str)); //true

开发中,在比较字符串内容是否相同时,一般将常量写在前面,这样避免equals前面的字符串内容为null,equals方法本身具有null判断的功能。

4、String类两种实例化的区别

由第一节中 的内容可知,对于String示例化方式有两种,到底该使用哪种,两种的区别是什么?

1)分析String类对象直接示例化的形式

【直接赋值】使用 的是最多的:

String str = "hello";
System.out.println(str);

开辟一块堆内存空间,且一块栈内存直接指向该堆内存空间。

【继续观察直接赋值】

String stra = "hello";
String strb = "hello";
String strc = "nihao"; 
System.out.println(stra==strb);  //true
System.out.println(strb==strc);  //false
System.out.println(stra==strc);  //false

很奇怪,是不是和前面分析的不太一样,其实还是一样的,只不过有一点需要注意,stra和strb指向的内容是相同的,不会重复开辟堆内存空间。这里涉及到对象池的概念。

关于对象池(Object Pool):Java设计过程中,为方便用户开发,针对几个特殊的类使用了共享设计的思路,String就属于其中一个类,这种设计思路是Java自己的支持,只针对于直接赋值的情况。

在使用直接赋值实例化String类对象操作中,字符串内容定义后实际上会自动保存在一个对象池之中,而后,若有其他 的字符串对象也采用直接赋值的形式,且内容与之前的完全相同,则不会开辟新的堆内存空间,而是通过对象池,找到已有的堆内存空间地址,直接引用,所以会出现如上范例的结果。

1)利用构造方法实例化对象

String str = new String("hello");
System.out.println(str);

由以上内存分析可以发现,通过构造方法进行实例化对象操作,最终会产生两块堆内存,其中一块是垃圾空间。

【举例】:没有入池的问题

String stra = new String("hello"); //构造方法
String strb = "hello"; //直接赋值
System.out.println(str);//false

使用构造方法进行String类对象实例化,产生的对象不会保存在对象池中,此对象无法重用。若用户需要让这个对象入池,只能通过手工入池方法完成:

手工入池:public String intern().

String stra = new String("hello").intern; //构造方法
String strb = "hello"; //直接赋值
System.out.println(str);//此处结果为true

【经典问题】:String类两种对象的实例化区别是什么?

  • 直接赋值(String str ="字符串"):仅开辟一块堆内存空间,且对象可以自动入池以共其他对象重复使用;
  • 构造方法(String str = new String("字符串")):开辟两块堆内存空间,且有一块会成为垃圾,产生的对象不会自动入池,需要使用intern()方法手动入池。

5、字符串声明后不可改变

【举例】:

String str = "Hello ";
str += "World ";
str = str+ "!!!";
System.out.println(str); //Hello World !!!

 进行内存分析可以发现,以上程序操作都是String类对象的引用发生改变,而字符串的内容实质上根本没有发生改变,这样操作形成了很多垃圾空间,因此,在开发中,一定禁止循环修改String。后续会讲到StringBuffer和StringBuilder,可以用于循环修改。

6、结论

  • 1)String开发中都使用直接赋值,并且不要频繁修改,因为会产生垃圾空间;
  • 2)字符串内容比较时用equals()方法。