• String不可变性


    今天分析一下String,String有很多实用的特性,比如说“不可变性”,是工程师精心设计的艺术品。用final就是拒绝继承,防止内部属性或方法被破坏。

    一,什么是不可变?

    String不可变很简单,如图,给一个已有字符串“abcd”,第二次赋值为“abcde”,不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。

    二,String为什么不可变?

    翻看IDK源码,String类前几行是这样写的:

    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
    
        /** Cache the hash code for the string */
        private int hash; // Default to 0

    首先String是被final修饰,这说明String不可被继承。下面String的主要字段value是个char[]数组,并且被final修饰。final修饰的字段创建后就不可改变。但是value是引用类型,用final修饰,只能说明value的引用地址不可变,但是挡不住char[]数组本身可变的事实。注意黑体的这段话,正如分析final关键字时所说,对于基本类型,final使数值恒定不变;而用于对象引用,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法再把它改为指向另一个对象。然而,对象其自身却是可以被修改的。

    final int[] value={2,3,4};
    value[2]=100;  //这时候数组里已经是{2,3,100}

    所以String不可变,关键是因为SUN公司的工程师,在后面所有String的方法里很小心的没有去动Array里的元素,没有暴露内部成员字段。private final char value[]这一句里,private的私有访问权限的作用比final都大。而且工程师还很小心地把整个String类设成final禁止继承,避免被其他人继承后破坏。所以String不可变的关键在底层的实现,而不是一个final。

    三,不可变的好处

      1,字符串常量池的需要。

      字符串常量池在方法区是一块特殊的存储区域。当字符串已经在常量池中,此时创造字符串时,直接返回已存在字符串的引用,而不是重新创造一个String对象。

    String string1 = "abcd";
    String string2 = "abcd";

      2,快速获取哈希码。

      String的哈希码在java中经常被使用。例如,在HashMap或者HashSet中。不可变确保了哈希码总是相同的。那就意味着每次在使用时不需要重新计算哈希码,这样更高效。

    private int hash;

      3,不可变对象是线程安全的。

      因为不可变对象并不能被改变,因此它们能放心地在多线程中使用,这就使得不必另外做同步。

     四,比较(String),toString()和String.valueOf()的区别

      1,(String),这是标准的类型转换,将其他类型转成String类型。使用这种方法时,需要注意的是类型必须能转成String类型,因此最好用instanceof做个类型检查,以判断是否可以转换。否则容易抛出CalssCastException异常。

      2,toString(),在这种使用方法中,因为java.lang.Object类里已有public方法.toString(),所以对任何严格意义上的java对象都可以调用此方法。但在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常,也可以在子类中重写toString()方法。

      3,String.valueOf(),此方法不会报空指针异常,弥补了toString()的不足。但是需要注意,null返回的是字符串“null”。

        public static String valueOf(Object obj) {
            return (obj == null) ? "null" : obj.toString();
        }

    参考:https://www.zhihu.com/question/31345592

    身体是革命的本钱,爱跑步,爱生活!
  • 相关阅读:
    MYSQL利用merge存储引擎来实现分表
    IoC原理及实现
    prometheus + grafana安装部署(centos6.8)
    PHP Laravel定时任务Schedule
    排序算法杂谈(三) —— 归并排序的非递归实现
    排序算法杂谈(二) —— 冒泡排序的递归实现
    排序算法杂谈(一) —— 量化数组的有序程度
    排序算法(七) —— 快速排序
    排序算法(六) —— 归并排序
    排序算法(五) —— 堆排序
  • 原文地址:https://www.cnblogs.com/caozx/p/8562482.html
Copyright © 2020-2023  润新知