java中的String类的一点认识

这是学习中用到的一些基础知识

String 是经常会用到的一个类,学习的过程中发现的东西进行的汇总。

1. 初始化方面:

  String类是一个比较特别的类,初始化的时候有种简化的特殊语法。

  1>String s = "abc";

  而按照正规的语法来说,应该是:

  2>String s = new String ("abc");

  建议使用1>的方式,原因在于这样比较节省内存空间,从其他网站上照抄下来的说法是,【只是按照面向对象的标准语法,在内存使用上存在比较大的浪费。例如         String s = new String(“abc”);实际上创建了两个String对象,一个是”abc”对象,存储在常量空间中,一个是使用new关键字为对象s申请的空间。】

  下面是简单的代码

  

1         String a = "abc";
2         String b = "abc";
3         System.out.println(a==b);

  打印的结果是True。这里的代码含义在于,创建了String类型的引用变量,a和b,a和b指向了值为"abc"的String类,至于是不是新建的String类型的对象,需要根据代码的前后文进行分析(因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象)。结果为True,代表这至少第二行代码没有重新创建一个String类型的对象,而是指向了存在的"abc"的对象,所以a 和 b 指向的是同一个对象,必然两者是相等的。

  再如下面的代码:

1         String d = new String("abc");
2         String e = new String("abc");
3         System.out.println(d==e);

  打印的结果是False,即 d, e两个String类型的引用是指向不同的对象,1,2行代码的处理逻辑是: 不管其字符串值是否相等,是否有必要创建新对象,都会创建新的对象。

  另外研究到这里的时候,发现代码1中,提出了一个设计模式的思想-享元模式,即复用内存中已经存在的对象,降低系统创建对象实例的性能消耗。至于更多的分析可能会随着学习逐步的深入

2. String的只读特性

  String是一个常量,在初始化的时候,一旦创建就不能再被改变,所以看起来是修改了String值的方法,其内部的逻辑并非如此。如下面的代码:

  

1 String a1 = "first";
2 System.out.println(a1 + ", second");

  打印之后是“first, second”,其实内部逻辑上来看,其实是生成了一个新的String对象,而不是在原有的String对象上追加内容。

  而java的内部处理方式上有说法是通过StringBuilder 这个类来实现字符串的拼接。所以大胆假设下,以上的代码等同于如下的实现方式:

1 StringBuilder stringBuilder = new StringBuilder();
2 stringBuilder.append(a1);
3 stringBuilder.append(", second");
4 System.out.println(stringBuilder.tostring());

  通过上面的代码可以看出,如果假设是成立的情况下,在进行字符串拼接的时候如果使用的“String + ”的方式进行的,而在java内部是通过StringBuilder的方式来实现的话,那会创建一个StringBuilder对象来处理,单个的情况下不会有太多额外消耗,但是如果在循环体中使用了“String +”的方式,会不断进入循环的时候不端创建StringBuilder对象,这样反倒是有增加内存开支的嫌疑。所以如果以上假设都成立的话,在使用到字符串拼接的时候,干脆使用StringBuilder 的方式不是更好么?省的转换成StringBuilder的方式后还得在每次循环中不断的创建StringBuilder对象。

3. equals 和 “==”的区别

简单的说,String的 equals()方法比较字符串对象中的字符, == 运算符比较的是两个对象是否引用同一实例,代码如下:

1         String s1 = "Hello";
2         String s2 = new String(s1);
3         System.out.println(s1.equals(s2)); //True 
4         System.out.println(s1==s2); //False

这个代码就比较简单了,看下面是equals的实现方法

public boolean equals(Object anObject) {
    if (this == anObject) { //判断是否同一对象
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;//String类型
        int n = count;
        //一个字符一个字符的比较
        if (n == anotherString.count) {
        char v1[] = value;
        char v2[] = anotherString.value;
        int i = offset;
        int j = anotherString.offset;
        while (n-- != 0) {
            if (v1[i++] != v2[j++])
            return false;
        }
        return true;
        }
    }
    return false;
    }    

从源码中看到了两个事情:

1. 如果equals对比的是两个对象的话,那equals 和  == 是同样的判断逻辑

2. 只有当判断出都是String类型的对象的时候,才会去对比每个字符是否相等。

看源码是个好习惯,要有耐心。

  

原文地址:https://www.cnblogs.com/kevinqinan/p/4481578.html