String中会遇见的几个问题

String的简介

Java中的String类是一个经常使用的,String 类代表字符串。这个字符串属于常量,它们的值在创建之后就不能更改这一点可以从String的成员变量源码中看出。

/** String的属性值 */  
    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. */
    /**String中元素的个数**/
    private final int count;

    /** Cache the hash code for the string */
   /**String类型的hash值**/
    private int hash; // Default to 0

    /** use serialVersionUID from JDK 1.0.2 for interoperability */
    private static final long serialVersionUID = -6849794470754667710L;
    /**
     * Class String is special cased within the Serialization Stream         Protocol.
     *
     * A String instance is written into an ObjectOutputStream according to
     * <a href="{@docRoot}/../platform/serialization/spec/output.html">
     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
     */

  private static final ObjectStreamField[] serialPersistentFields =
        new ObjectStreamField[0];

从这里面还可以看出String底层使用字符数组来进行维护,而且值的类型为final所有无法修改。而且存储String数据也不一定从数组的第0个元素开始的,而是从offset所指的元素开始。

String的几个问题

一、关于字符串常量池
字符串常量池这个问题涉及到一个设计模式,叫“享元模式”,即 共享元素模式 :
  也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素
  Java中String部分就是根据享元模式设计的,而那个存储元素的地方就叫做“字符串常量池 - String Pool”

String x1 = "hello";
String x2 = new String("hello");

这两句话的执行过程天差地别**,第一句话**会先在字符常量池中查找有没有已经创建过相同的对象,如果有直接使用,一个没有则创建对象。

第二句话的过程就相对复杂一些,首先**"hello"就会先执行第一句话的过程,然后因为又使用了new**这个关键字又在Java Heap中创建了1个对象,然后调用接收String参数的构造器进行了初始化,最终x2的引用这个String对象。也就是说如果只有
String x2 = new String(“hello”);
这一句话就会创建出两个String对象

二、关于字符串的比较
对于字符串的比较,使用" == "还是"equals"呢?
" == "是直接比较的两个对象的堆内存地址,如果相等,则说明这两个引用实际是指向同一个对象地址的。

“equals” 如果是一个没有重写过的equals,这直接调用Object的equals,此时和" == "没有任何的区别,但String类重写了这个方法会对字符串的内容进行比对

String x1 = "hello";
String x2 = new String("hello");
System.out.println(x1 == x2);//false
System.out.println(x1.equals(x2));//true

以上两个不属于同一个对象,但它们的字符串内容相同,面对两个不同的比较方法就有了这两种结果。

三、关于字符串的"+"运算

String x1 = "hello world";
String x2 = "hello " + "world";
String x3 = "hello ";
String x4 = "world";
String x5 = x3 + x4;
System.out.println(x1 == x2);//true
System.out.println(x5 == x1);//false

从上面的这个代码可以看出,针对字符串常量和变量"+"的运行过程并把相同 :
当为常量时,"hello “和"world"这种在编译时可以确定的叫做常量,常量在进行”+"操作时,会首先在字符串常量池中进行寻找,如果能找到拼接后字符串,编译期间就会进行优化变成String x2 = “hello world”;所以x1 == x2
当为变量时,由于不是已知字面量,是一个不可预料的部分,编译器不会优化,必须等到运行时才可以确定结果。此时的"+"操作会将String转为StringBuilder进行append操作,在通过toString返回一个String,通过return返回的String自然就和前面的String不是同一个对象了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值