首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么Java里面String类是不可变的

在Java里面String类型是不可变对象,这一点毫无疑问,那么为什么Java语言的设计者要把String类型设计成不可变对象呢?这是一个值得思考的问题。...在Java里面final关键字就是用来辅助创建不可变对象的,但需要注意的是,对于基本类型被final修饰后,就彻底变成了不可变对象,而引用类型被final修饰后,仅仅是指针的内存地址不能改变,如果想要变成彻底的不可变类型...ok,下面我们来分析下为什么String是不可变的? 通过String源码可以看到,String类型的底层是由final修饰的char数组存储。...此外,由于字符串的不可变性,从而可以让其hashCode也被缓存,在Java里面哈希类数据结构如HashMap, HashTable, HashSet其key用的最多的基本都是String类型,如此一来...(三)同步 由于String类型的不可变性,使得String对象可以安全的在多个线程之间传递和访问,也就是说你在多线程中是不能改变字符串本身的值,而是在堆里面新创建一个字符串然后操作。

72640

Java中的String为什么是不可变的?

什么是不可变对象? 众所周知, 在Java中, String类是不可变的。那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。...区分对象和对象的引用 对于Java初学者, 对于String是不可变对象总是存有疑惑。...为什么String对象是不可变的? 要理解String的不可变性,首先看一下String类中都有哪些成员变量。...从上文可知String的成员变量是private final 的,也就是初始化之后不可改变。那么在这几个成员中, value比较特殊,因为他是一个引用变量,而不是真正的对象。...但是一般我们不这么做。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。

70430
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    Java 中的 String 为什么是不可变的?

    什么是不可变对象? 众所周知, 在Java中, String类是不可变的。那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的。...区分对象和对象的引用 对于Java初学者, 对于String是不可变对象总是存有疑惑。...为什么String对象是不可变的? 要理解String的不可变性,首先看一下String类中都有哪些成员变量。...从上文可知String的成员变量是private final 的,也就是初始化之后不可改变。那么在这几个成员中, value比较特殊,因为他是一个引用变量,而不是真正的对象。...但是一般我们不这么做。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。

    1.8K01

    为什么String在Java中是不可变的

    String 在 Java 中是不可变的。 不可变类只是一个无法修改其实例的类。 创建实例时,将初始化实例中的所有信息,并且无法修改信息。 不可变类有许多优点。...本文总结了为什么 String 设计为不可变的。 这篇文章从内存,同步和数据结构的角度说明了不变性概念。 1. 字符串池 字符串池(String intern pool)是方法区域中的特殊存储区域。...创建字符串并且池中已存在该字符串时,将返回现有字符串的引用,而不是创建新对象。 以下代码将在堆中仅创建一个字符串对象。...如果字符串是可变的,则使用一个引用更改字符串将导致其他引用的错误。 2. 缓存的哈希码 字符串的哈希码经常在 Java 中使用。 例如,在 HashMap 或 HashSet 中。...字符串不是不可变的,连接或文件将被更改,这可能会导致严重的安全威胁。 该方法认为它连接到一台机器,但事实并非如此。 可变字符串也可能在 Reflection 中引起安全问题,因为参数是字符串。

    1.3K20

    java 为什么 String 在 java 中是不可变的?

    为什么 String 在 java 中是不可变的?String 在 java 中是不可变的,一个不可变类意味着它的实例在创建之后就不可修改,实例的所有属性在创建时初始化,之后无法对这些属性进行修改。...不可变类型有着许多的优点,这篇文章总结了 为什么 String 被设计成不可变的,文章将从内存、同步和数据结构的角度说明不变性概念。...1 字符串池的需要字符串池是存在于 Java方法区 的一个特殊内存区域,当需要创建的目标字符串在字符串池中已经存在,那么字符串池中的字符串引用就会返回并赋值给目标字符串,而不是创建一个新的对象。...如果 String 是可变的,那么它的 value 可以被改变,但这违反了 Set 的设计原则(Set 中的元素是不能重复的),当然,上面的例子仅仅为了表明意图,String 类中并不存在 value...总结,String 被设计为 final 的原因是 效率 和 安全,通常情况下这也是为什么不可变对象在许多设计中会成为首选的原因。

    8510

    Java开发人员最常犯的9个错误

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ?...4 HashTable与HashMap 从算法的角度来讲,HashTable是一种数据结构名称。但是在Java中,这种数据结构叫做HashMap。...但是对于每个不同的值都需要一个单独的对象,太多的对象会引起大量垃圾回收,因此在选择可变与不可变的时候,需要有一个平衡。 通常,可变对象用于避免产生大量的中间对象,一个经典的例子是大量字符串的拼接。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    43410

    Java开发人员最常犯的10个错误

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ?...更多详细信息,可以查看ArrayList.iterator()的源码。 从算法的角度来讲,HashTable是一种数据结构名称。但是在Java中,这种数据结构叫做HashMap。...但是对于每个不同的值都需要一个单独的对象,太多的对象会引起大量垃圾回收,因此在选择可变与不可变的时候,需要有一个平衡。 通常,可变对象用于避免产生大量的中间对象,一个经典的例子是大量字符串的拼接。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    33820

    scala 容器详细解释

    scala.collection.mutable 包的集合类则有一些操作可以修改集合。 scala.collection 包中的集合,既可以是可变的,也可以是不可变的。...scalaCollection.png Traverable Traversable(遍历)是容器(collection)类的最高级别特性,它唯一的抽象操作是foreach: def foreach[U...它们不添加任何新的操作,但都提供不同的性能特点:线性序列具有高效的 head 和 tail 操作,而索引序列具有高效的apply, length, 和 (如果可变) update操作。...例如,我们可以像下述代码那样在HashMap中混入SynchronizedMap。 具体不可变集实体类 List 列表List是一种有限的不可变序列式。...stream定义为惰性的计算 Verctor 对于只需要处理数据结构头结点的算法来说,List非常高效。

    1.3K10

    开发中常犯的几个错误

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。 HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    33620

    Java开发人员最常犯的10个错误,你犯过几个?

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    33640

    Java开发人员最常犯的10个错误

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    47520

    Java开发最常犯的10个错误,打死都不要犯!

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。 HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...但是对于每个不同的值都需要一个单独的对象,太多的对象会引起大量垃圾回收,因此在选择可变与不可变的时候,需要有一个平衡。推荐:Java 中的 String 真的是不可变的吗?...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说

    34020

    Java开发者最常犯的10个错误,看完别再犯了

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    40420

    Java 程序员排行前 10 的错误,你会不会解决?

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    29320

    Java 程序员排行前 10 的错误,你有没有中?

    你也许知道使用迭代器是在循环里删除元素的正确方式,或许你也知道foreach循环跟迭代器很类似,但事实情况却不是这样,如下代码: ArrayList list = new ArrayList...但是在Java中,这种数据结构叫做HashMap。HashTable与HashMap的一个主要的区别是HashTable是同步的,所以,通常来说,你会使用HashMap,而不是Hashtable。...例如往一个方法传入一个可变对象,然后收集多种结果,而不需要写太多的语法。另一个例子是排序和过滤:当然,你可以写一个方法来接收原始的集合,并且返回一个排好序的集合,但是那样对于大的集合就太浪费了。...在Java中,如果一个类没有定义构造方法,编译器会默认插入一个无参数的构造方法;但是如果一个构造方法在父类中已定义,在这种情况,编译器是不会自动插入一个默认的无参构造方法,这正是以上demo的情况; 对于子类来说...,不管是无参构造方法还是有参构造方法,都会默认调用父类的无参构造方法;当编译器尝试在子类中往这两个构造方法插入super()方法时,因为父类没有一个默认的无参构造方法,所以编译器报错; 要修复这个错误,

    83910

    Java 开发人员经常犯的 10 大错误

    您可能知道使用迭代器是删除循环内部元素的正确方法,并且您知道Java中的foreach循环就像迭代器一样,但实际上并非如此。...4、Hashtable vs HashMap ------ 根据算法中的约定,Hashtable是数据结构的名称。但在Java中,数据结构的名称是HashMap。...例如,将可变对象传递给方法可以让您收集多个结果,而不会跳过太多语法箍。另一个例子是排序和过滤:当然,您可以创建一个获取原始集合的方法,并返回一个已排序的方法,但这对于较大的集合来说会变得非常浪费。...在Java中,如果类没有定义构造函数,编译器将默认为该类插入默认的无参数构造函数。如果构造函数是在Super类中定义的,在本例中是Super(String s),编译器将不会插入默认的无参数构造函数。...由于编译器尝试将super() 插入Sub类中的2个构造函数,但未定义Super的默认构造函数,因此编译器会报告错误消息。

    65330

    Java程序员最常犯的错误盘点之Top 10

    在迭代时移除List中的元素 首先,看一下在迭代过程中移除List中元素的代码: ? 这个示例代码的输出结果是: ? 这个示例代码中存在一个非常严重的错误。...你可能知道解决这个错误的方式之一是使用迭代器(iterator)。而且,你可能认为Java中的foreach语句与迭代器(iterator)是非常相似的,但实际情况并不是这样。...在Java中,对应哈希表的的类是HashMap而不是Hashtable。HashMap与Hashtable之间的最核心区别就是:HashMap是非同步的,Hashtable是同步的。 5....比如,传递一个可变的对象到方法内部,利用该对象可以收集多个结果,而不用在多个循环层次中跳进跳出。 9. 继承中的构造函数 ?...上图中出现的两个编译时错误是因为:父类中没有定义默认构造函数,而子类中又调用了父类的默认构造函数。在Java中,如果一个类不定义任何构造函数,编译期将自动插入一个默认构造函数到给类中。

    76440

    Q&A:Java

    语法形式 :从语法形式上看,成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及...String 为什么是不可变的? String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变。...equals 对于没有重写equals方法的类,equals方法和==作用类似;对于重写过equals方法的类,equals比较的是值。...foreach底层是怎么实现的 底层原理其实就是基于普通的 for 循环和迭代器。...对于数组,foreach 循环实际上还是用的普通的 for 循环 对于集合,foreach 循环实际上是用的iterator 迭代器迭代 foreach和for有什么区别?

    63120

    python学习总结

    Python中的列表就是一个迭代器,我们知道Python是使用C编写的,那么list的内部实现是怎样的呢?...对于可变对象,比如list,对list进行操作,list内部的内容是会变化的,而对于不可变对象,比如str,使用replace()方法,虽然可以更改值,但是变量的值并不会发生改变,为什么呢?...对于不可变对象,调用自身的任意方法,并不会改变对象自身的内容,这些方法会创建新的对象并返回,保证了不可变对象本身是永远不可变的。...对于不可变对象作为函数参数,相当于C系语言的值传递; 对于可变对象作为函数参数,相当于C系语言的引用传递。 高级特性 迭代器 Python中的迭代器是什么呢?...对于遍历支持随机访问的数据结构(tuple,list),迭代器相比于for循环并无优势,因为迭代器丢失了索引值。但对于无法随机访问的数据结构,迭代器是唯一的访问元素的方式。

    1.1K50

    第7章 集合类第7章 集合类

    Set 集 Set 集是最简单的一种集合,它的对象不按特定方式排序,只是简单的把对象加入集合中,就像往口袋里放一堆溜溜弹珠。 Set 集中没有重复对象。...如果我们从数据结构的本质上来看,其实List就是Key是Int类型下标的特殊的Map。而Set也是Key为Int,但是Value值不能重复的特殊Map。...Set 集合类图 Kotlin中的Map与List、Set一样,Map也分为只读Map和可变 MutableMap(可写入删除数据)。Map没有继承于Collection接口。其类图结构如下 ?...7.4 遍历集合中的元素 List、Set 类继承了Iterable接口,里面扩展了forEach函数来迭代遍历元素;同样的 Map 接口中也扩展了forEach函数来迭代遍历元素。...集合类持有的是对象,而怎样的放入正确的对象类型则是我们写代码过程中需要注意的。下一章节中我们将学习泛型。

    1.3K20
    领券