美文网首页java road
String-学习笔记(3)

String-学习笔记(3)

作者: HardWJJ | 来源:发表于2018-08-19 20:37 被阅读6次

    String对象的不变性说明

    代码:

    String s = "abcd";
    String s2 = s;
    
    String-Immutability-2.jpeg

    代码:

    s = s.concat("ef");字符串拼接
    
    string-immutability-650x279.jpeg

    一旦一个string对象在堆中被创建出来,它就无法被修改,无论是什么方法都返回一个新的字符串对象(如果需要不断修改字符串,那么应该使用StringBulider或者StringBuffer,否则每次拼接都会创建新的对象,最后对导致创建出很多无用对象)

    常量池中的String

    字符串常量池是方法区中一部分区域,当一个字符串常量被创建的时候,会先到常量池中找,如果找到则返回该字符串的引用。
    代码:

    String string1 = "abcd";
    String string2 = "abcd";
    
    QQ20160302-3.png

    所以,如果字符串可变的话,string2的修改将会直接影响string1

    缓存Hashcode

    java中经常使用的哈希码,例如在HashMap中,字符串作为Key值时,字符串的不变性可以保证其hashcode永远保持一致,在使用一个字符串的hashcode的时候不用每次重新计算一次。

    安全性

    String被广泛的使用在其他Java类中充当参数。比如网络连接、打开文件等操作。如果字符串可变,那么类似操作可能导致安全问题。可变的字符串也可能导致反射的安全问题,因为反射调用的参数也是字符串。

    如何创建字符串

    在Java中,有两种方式可以创建字符串:

    String x = "abc";
    String y = new String("abc");
    
    双引号创建:
    String a = "abcd";
    String b = "abcd";
    System.out.println("a == b : "+(a == b)); // true
    System.out.println("a.equals(b) : "+(a.equals(b))); // true
    

    因为a与b都是"abcd",所以都返回字符串常量池的地址

    构造函数创建:
    String c = new String("abcd");
    String d = new String("abcd");
    System.out.println("c == d : "+(c == d)); // false
    System.out.println("c.equals(d) : "+(c.equals(d))); // true
    

    c与d的地址不同是因为他们分别指向堆中的不同对象

    运行时字符串驻留:
    String c = new String("abcd").intern();
    String d = new String("abcd").intern();
    System.out.println("c == d : "+(c == d)); // true
    System.out.println("c.equals(d) : "+(c.equals(d))); // true 
    

    上面的代码由于"abcd"在类加载时就已经从.class文件中获取到放入常量池中,所以上面的c和d读取的都是类加载时的地址(在String-学习笔记(2)中有提过),所以它们相等,并且这样直接返回引用会省去很多new操作的耗时
    所以,所以只使用一个字符串,可以使用双引号方式,如果需要在堆中创建一个对象可以使用构造函数的方式

    switch对字符串的支持

    java7之后switch开始支持string,其实switch对string的支持最终也是转为int简单类型进行比较
    代码:

      String str = "Hard";
            switch (str) {
                case "Hard":
                    System.out.println("Hard");
                    break;
                case "WJJ":
                    System.out.println("WJJ");
                    break;
                default:
                    break;
    }
    

    反编译后:

       String str;
            String string = str = "Hard";
            int n = -1;
            switch (string.hashCode()) {
                case 2241803: {
                    if (!string.equals("Hard")) break;
                    n = 0;
                    break;
                }
                case 85975: {
                    if (!string.equals("WJJ")) break;
                    n = 1;
                }
            }
            switch (n) {
                case 0: {
                    System.out.println("Hard");
                    break;
                }
                case 1: {
                    System.out.println("WJJ");
                    break;
                }
            }
    

    可以看出switch支持string其实也就是通过hashcode+equals方法来实现的,进行hashcode之后还要进行equals时因为由于hash冲突hash值相同只是第一步,equals相等才表示两个String值相等,另外,如果是两个字面量进行equals的话,比较是非常快速的,因为都是取常量池中的引用进行比较,所以switch中只支持整型int,能支持string只是为了方便程序员,编译后还是通过整型比较

    参考资料

    相关文章

      网友评论

        本文标题:String-学习笔记(3)

        本文链接:https://www.haomeiwen.com/subject/awaciftx.html