Java String类的基本用法


为了方便处理字符串操作,JDK提供了String类和StringBuffer类来封装字符串,并且都位于java.lang包中,因此使用时不需要显式引用就可以直接使用。本文对String类进行讲解。

一、String类

当我们提供用户注册界面的时候,常常会用到:复选框组件(JCheckBox)单选框组件(JRadioButton)Java中没有内置的字符串类型,而是提供了一个预定义类叫String。String类定义了大量操作字符串的方法,例如从字符串中提取字符或子串、检索字符或者子串等。欲让读者更好了解String类,本文给出了String类的部分源码,如下所示:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];

    /** The offset is the first index of the storage that is used. */
    private final int offset;

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;

    ........
}

由其源码可知:
1、String类是通过char数组保存字符串。
2、String类是用final修饰的,可说明String不可继承。其次其中字段value是char数组,也是用final修饰的,final修饰的字段创建后就不可变。因此,String对象一旦被创建就是固定不变的,String类对象有编辑字符串的功能,比如replace(),这些编辑功能是通过创建一个新的对象来实现的,而不是对原有对象进行修改,因此其任何改变都不会影响到原对象,但相关的其他改变操作都会生成新的对象。
备注1:String类的value属性用final修饰,代表value的引用地址不可变,但Array变量只是stack上的一个引用,数组的本体结构在堆,堆里Array中数据可变,即Array数组是可变的。例如:

final int[] value = {1,2,3};
value[0] = 4; //这时数组里的第一个元素1已变为4

二、字符串常量池

Java中的常量池分为两种形态:静态常量池和运行时常量池。静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含类、方法的信息,占用class文件绝大部分空间。运行时常量池,则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。
由于String字符串的不可变性,字符串常量池中不存在两个相同的字符串。可通过下例理解:

String s1 = "HelloWorld";
String s2 = "HelloWorld";
String s3 = new String("HelloWorld");

备注2:s1、s2和字面上的HelloWorld都是指向JVM字符串常量池中的"HelloWorld"对象,它们指向同一个对象。而new关键字一定会产生一个对象HelloWorld,但这个对象是存储在堆中。由于在Java中不存在两个完全一模一样的字符串对象,故堆中的HelloWorld是引用字符串常量池中HelloWorld。

三、String类对象的创建

String类对象用于表示一串连续的字符串,包含在一对双引号(英文格式)之间。其创建字符串的方式可归纳为三类:
1、直接指定。先在栈中创建一个String类的对象引用变量,然后查找其字符串是否已保存在常量池中,若没有则创建对象,其对象引用变量则指向对象的地址;若已存在则直接指向对象的地址。例如:

String s4 = "HelloWorld";
String s5 = "100"//一个内容为100的字符串,注意此处的100不是数值
String s6 = "";//一个内容为空的字符串

2、使用new关键字创建字符串。基于第1种创建方法,JVM在堆中新创建一个String对象,其值共享栈中已有的字符串。例如:

String s7 = new String("HelloWorld");

3、使用串联的方式生成新的字符串。例如:

String s8 = "Hello" + "World";

三、字符串的子串

在String类中可利用substring方法从一个较大的字符串中提取一个子串。例如:

String s9 = "HelloWorld";
String s10 = s9.substring(0,5);

substring方法的第一个参数是开始复制的位置,第二个参数是不想复制的数组的第一个位置,例如上述代码是复制0到4的字符,在substring中从0开始计数,复制5个字符,因此便创建了一个字符“Hello”组成的字符串。

四、字符串的拼接

Java语言中允许使用+号连接两个字符串。例如:

String s11 = "Hello";
String s12 = "World";
int s13 = 123;
String s14 = s11+s12 ;
String s15 = s11+s13 ;
String s16 = s11.concat(s12) ;

上述代码将"Hello"、"World"赋给变量s14,其中+号按照给定的次序将两个字符串连接起来,最后可得到“HelloWorld”;而s15中拼接时有字符串"Hello"和非字符串的值123进行拼接时,非字符串会被转换成字符串,可得到“Hello123”;public String concat(String str)可将参数中的字符串拼接到当前字符串的后面,如s16和s14所打印出来的结果一样。
用+号的拼接方法通常由于输出打印语句,例如:

System.out.println("the answer is "+s14);

五、检测字符串是否相等

1、利用“==”比较。
Java中字符串的值是不可改变的,由于在Java中不存在两个完全一模一样的字符串对象,所以可以用于比较。但笔者建议尽量不要使用该方法进行字符串比较,该方法可能会带来一些问题,请看以下两个例子:

public void example1(){
    String s1 = "HelloWorld";
    String s2 = "HelloWorld";
    System.out.println(s1 == s2);//可以判断s1跟s2是否指向同一个对象 
}
public void example2(){
    String s2 = "HelloWorld";
    String s3 = new String("HelloWorld");
    System.out.println(s2 == s3);//可以判断s2跟s3是否指向同一个对象 
}

执行上述代码,例1运行的结果为:true;例2运行的结果为:false。

例1分析:如本文“一、String类对象的创建”中所述,当执行String s1 = "HelloWorld"时,JVM首先会去字符串池中查找是否存在"HelloWorld"这个对象,如果不存在,则在字符串池中创建该对象,然后将池中"HelloWorld"这个对象的引用地址返回给字符串常量s1,这样s1会指向池中"HelloWorld"这个字符串对象;如果存在,则不创建任何对象,直接将池中"HelloWorld"这个对象的地址返回,赋给字符串常量。当创建字符串对象s2时,字符串池中已经存在"HelloWorld"这个对象,直接把对象"HelloWorld"的引用地址返回给s2,这样s2指向了池中"HelloWorld"这个对象,也就是说s1和s2指向了同一个对象,因此语句System.out.println(s1 == s2)输出:true。
备注3:运用串联方法创建的字符串也可用该方法判断

例2分析:采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有"HelloWorld"这个字符串对象。(后续运行操作和直接指定的字符串创建方式一样,这里便不做多余解释。)当执行String s3=new String(“HelloWorld”)时, 因为采用new关键字创建对象时,每次new出来的都是一个新的对象,也即是说引用s2和s3指向的是两个不同的对象,因此语句System.out.println(s2 == s3)输出:false

2、运用equals方法比较
(1)对于"==",如果作用于基本数据类型的变量(byte,short,char,int,long,float,double,boolean ),则直接比较其存储的"值"是否相等;如果作用于引用类型的变量(String),则比较的是所指向的对象的地址(即是否指向同一个对象)。
(2)equals方法是基类Object中的方法,因此对于所有的继承于Object的类都会有该方法。在Object类中,equals方法是用来比较两个对象的引用是否相等,即是否指向同一个对象。
(3)对于equals方法,注意:equals方法不能作用于基本数据类型的变量。如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;而String类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。其他的一些类诸如Double,Date,Integer等,都对equals方法进行了重写用来比较指向的对象所存储的内容是否相等。

关于两种方法的区别可见例3:

public void example3(){
    String s4 ="HelloWorld";
    String s5 ="HelloWorld";
    String s6 =new String("HelloWorld");
    System.out.println( s4 == s5); 
    System.out.println( s4 == s6); 
    System.out.println( s4.equals(s6)); 
}

执行以上代码,例3运行的结果为ture,false,ture。
例3的分析可以参考例1和例2的分析。
备注4:笔者建议在对字符串进行地址的判断时可运用方法1,若要对字符串的内容进行比较则运用方法2更为妥当。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值