扯扯Java中的String类

java.lang.String 类可能是大家日常用的最多的类

String 类定义【源码】

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {

}

String 是一个用 final 声明的常量类,不能被任何类所继承,而且一旦一个String对象被创建,包含在这个对象中的字符序列是不可改变的,包括该类后续的所有方法都是不能修改该对象的,直至该对象被销毁,这是我们需要特别注意的(该类的一些方法看似改变了字符串,其实内部都是创建一个新的字符串)接着实现了 Serializable接口,这是一个序列化标志接口,还实现了 Comparable 接口,用于比较两个字符串的大小(按顺序比较单个字符的ASCII码),最后实现了 CharSequence 接口,表示是一个有序字符的集合;

字段属性【源码】

/**用来存储字符串  */
private final char value[];

/** 缓存字符串的哈希码 */
private int hash; // Default to 0

/** 实现序列化的标识 */
private static final long serialVersionUID = -6849794470754667710L;

从源码中我们可以看出一个 String 字符串实际上是一个 char 数组。

构造方法【源码】

 age:

String str1 = "abc";//注意这种字面量声明的区别,后面会详细介绍
String str2 = new String("abc");
String str3 = new String(new char[]{'a','b','c'});

 String中常用方法:

a:equals(Object anObject) 方法  (较的是组成字符串的每一个字符是否相同-即内容)

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String aString = (String)anObject;
        if (coder() == aString.coder()) {
            return isLatin1() ? StringLatin1.equals(value, aString.value)
                : StringUTF16.equals(value, aString.value);
        }
    }
    return false;
}

 String 类重写了 equals 方法,比较的是组成字符串的每一个字符是否相同,如果都相同则返回true,否则返回false。【这里需要注意与之对应的对比方法有  ==  这里对比的是内存地址是否相等】还要注意一点的是:【在object中,equals()是用来比较内存地址的,但是String重写了equals()方法,所以这里有区别】

下面介绍一下String类中的一个本地方法:

intern() 方法

public native String intern();

当调用intern方法时,如果池中已经包含一个与该String内容相同【equals(Object)为true】的字符串,则返回该字符串。否则,将此String对象添加到池中,并返回此对象的引用。这句话什么意思呢?就是说调用一个String对象的intern()方法,如果常量池中有该对象了,直接返回该字符串的引用(存在堆中就返回堆中,存在池中就返回池中);如果没有,则将该对象添加到池中,并返回池中的引用。

String str1 = "hello";//字面量 只会在常量池中创建对象
String str2 = str1.intern();
System.out.println(str1==str2);//true

String str3 = new String("world");//new 关键字只会在堆中创建对象
String str4 = str3.intern();
System.out.println(str3 == str4);//false

String str5 = str1 + str2;//变量拼接的字符串,会在常量池中和堆中都创建对象
String str6 = str5.intern();//这里由于池中已经有对象了,直接返回的是对象本身,也就是堆中的对象
System.out.println(str5 == str6);//true

String str7 = "hello1" + "world1";//常量拼接的字符串,只会在常量池中创建对象
String str8 = str7.intern();
System.out.println(str7 == str8);//true
public static void main(String[] args) {
    String A = "abc";
    String B = "abc";
    String C = new String("abc");
    System.out.println(A==B);          //true
    System.out.println(A.equals(B));   //true
    System.out.println(A==C);          //false
    System.out.println(A.equals(C));   //true
}

 String A= “abc”,会先到常量池中检查是否有“abc”的存在,发现是没有的,于是在常量池中创建“abc”对象,并将常量池中的引用赋值给A;第二个字面量 String B= “abc”,在常量池中检测到该对象了,直接将引用赋值给B;第三个是通过new关键字创建的对象,常量池中有了该对象了,不用在常量池中创建,然后在堆中创建该对象后,将堆中对象的引用赋值给C,再将该对象指向常量池。String重写了equals()方法所以这里是用来比较内容的A.equals(C)返回true;注意:看上图红色的箭头,通过 new 关键字创建的字符串对象,如果常量池中存在了,会将堆中创建的对象指向常量池的引用。

String str1 = "hello";
String str2 = "helloworld";
String str3 = str1+"world";//编译器不能确定为常量(会在堆区创建一个String对象)
String str4 = "hello"+"world";//编译器确定为常量,直接到常量池中引用

System.out.println(str2==str3);//fasle
System.out.println(str2==str4);//true
System.out.println(str3==str4);//fasle

str3 由于含有变量str1,编译器不能确定是常量,会在堆区中创建一个String对象。而str4是两个常量相加,直接引用常量池中的对象即可。

 OK,聊到这里我们就来说说开发中常考虑的字符串拼接吧~

String 被new时是要创建对象的,+ 号拼接同理也会创建对象,所以程序中尽量不要使用 + 拼接,应该尽量使用StringBuffer或者StringBuilder。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值