为什么在Java中String被设计js 把链接变成不可点变

[转载]为什么Java的string类要设成immutable(不可变的)
String和StringBuffer都是final类,他们生成的对象在堆中都是不可变的,在他们内部都是靠属性char数组实现的,
那为什么StringBuffer可以在对象中追加字符串呢?呵呵,因为String中的char数组是finall的,也就是常量,是不可改变
的,而StringBuffer继承自抽象类AbstractStringBuilder,他的内部实现靠他的父类完
成,AbstractStringBuilder内的char数组是变量,可以用append追加
StringBuffer和StringBuilder都实现了AbstractStringBuilder抽象类,此抽象类实现Appendable接口因此可追加
(在JDK 6.0 API中StringBuilder和Stringbuff写着都继承自Object
而且在他的API中找不到AbstractStringBuilder类)
首先,必须强调一点:String
Pool不是在堆区,也不是在栈区,而是存在于方法区(Method Area)
Pool是常量池(Constant& Pool)中的一块。
我们知道,常量就是不可以再改变的值,给它建一个池子很明显是为了加快程序运行的速度;在一个程序中,常量和变量是相对存在的;变量因为可变性所以一般存在于栈中,而常量去作为一个特殊群体被存在在常量池中。
常量池(constant
pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。--- (很明显在方法区)
它包括了关于类、方法、接口等中的常量,也包括字符串常量(这个就是Sring
Pool啦)。
在编译好的class文件中,有个区域称为Constant
Pool,它是一个由数组组成的表,类型为cp_info
constant_pool[],用来存储程序中使用的各种常量,包括Class/String/Integer等各种基本Java数据类型。
================
上面这些,简单理解:一个Class类,它里面有常量的存在,比如
int a=10;String
b="123450";它们在JVM看来就是常量(当然在方法中可能被修改啦),在Class被加载时,JVM特意都把它放在一个数组中维护起来,并且把该数组放在方法区中,起名叫常量池。
常量池存在于方法区,它包含各种类型的常量(8个基本数据类型,包装类型等)
我们把常量池中的String
Pool中的常量作为对象来看待 --- 因为String就是对象,String类型的常量自然也是对象啦!
String str1
= new String("Hello");
它创建了2个对象,一个是堆中的String对象,一个是String
Pool中的String对象。
要理解Java中String的运作方式,必须明确一点:String是一个非可变类(immutable)。什么是非可变类呢?简单说来,非可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变。Java为什么要把String设计为非可变类呢?你可以问问
james Gosling
:)。但是非可变类确实有着自身的优势,如状态单一,对象简单,便于维护。其次,该类对象对象本质上是线程安全的,不要求同步。此外用户可以共享非可变对象,甚至可以共享它们的内部信息。(详见
《Effective java》item
13)。String类在java中被大量运用,甚至在class文件中都有其身影,因此将其设计为简单轻便的非可变类是比较合适的。
一、创建。
好了,知道String是非可变类以后,我们可以进一步了解String的构造方式了。创建一个Stirng对象,主要就有以下两种方式:
虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。对于第一种,jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的String
Pool中通过String的 equals
方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至String
Pool中。注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到String
里面的,除非程序调用
String的intern方法。看下面的例子:
&& 再看下面的例子:
为什么jvm可以这样处理String对象呢?就是因为String的非可变性。既然所引用的对象一旦创建就永不更改,那么多个引用共用一个对象时互不影响。
二、串接(Concatenation)。
java程序员应该都知道滥用String的串接操作符是会影响程序的性能的。性能问题从何而来呢?归根结底就是String类的非可变性。既然String对象都是非可变的,也就是对象一旦创建了就不能够改变其内在状态了,但是串接操作明显是要增长字符串的,也就是要改变String的内部状态,两者出现了矛盾。怎么办呢?要维护String的非可变性,只好在串接完成后新建一个String
对象来表示新产生的字符串了。也就是说,每一次执行串接操作都会导致新对象的产生,如果串接操作执行很频繁,就会导致大量对象的创建,性能问题也就随之而来了。
为了解决这个问题,jdk为String类提供了一个可变的配套类,StringBuffer。使用StringBuffer对象,由于该类是可变的,串接时仅仅时改变了内部数据结构,而不会创建新的对象,因此性能上有很大的提高。针对单线程,jdk
5.0还提供了StringBuilder类,在单线程环境下,由于不用考虑同步问题,使用该类使性能得到进一步的提高。
三、String的长度
我们可以使用串接操作符得到一个长度更长的字符串,那么,String对象最多能容纳多少字符呢?查看String的源代码我们可以得知类String中是使用域
count 来记录对象字符的数量,而count&的类型为 int,因此,我们可以推测最长的长度为
2^32,也就是4G。
不过,我们在编写源代码的时候,如果使用 Sting str =
"aaaa";的形式定义一个字符串,那么双引号里面的ASCII字符最多只能有 65534 个。为什么呢?因为在class文件的规范中,
CONSTANT_Utf8_info表中使用一个16位的无符号整数来记录字符串的长度的,最多能表示 65536个字节,而java
class 文件是使用一种变体UTF-8格式来存放字符的,null值使用两个字节来表示,因此只剩下 65536- 2 =
65534个字节。也正是变体UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么双引号中字符的数量会更少(一个中文字符占用三个字节)。如果超出这个数量,在编译的时候编译器会报错。
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Java基础——为什么Java中的String设计成不可变的?
为什么中的String设计成不可变的? 这是一个老生常谈的问题了。在java中将String设计成不可变的原因有很多,然而一个好的答案取决于很好的理解java中的存储、同步、数据结构等等。一下是一些我总结的答案:
1、字符串池的需求
字符串池是方法区(Method Area)中的一块特殊的存储区域。当一个字符串已经被创建并且该字符串在 池 中,该字符串的引用会立即返回给变量,而不是重新创建一个字符串再将引用返回给变量。例如,以下代码只在堆中创建一个字符串对象:
String string1 =
String string2 =
他们看上去如下图:
如果字符串不是不可变的,那么改变一个引用(如: string2)的字符串将会导致另一个引用(如: string1)出现脏数据。
2、允许字符串缓存哈希码
在java中常常会用到字符串的哈希码,例如: HashMap 。String的不变性保证哈希码始终一,因此,他可以不用担心变化的出现。 这种方法意味着不必每次使用时都重新计算一次哈希码&&这样,效率会高很多。
在String类中,有如下代码:
//this is used to cache hash code.
String广泛的用于java 类中的参数,如:网络连接(Network connetion),打开文件(opening files )等等。如果String不是不可变的,网络连接、文件将会被改变&&这将会导致一系列的安全威胁。操作的方法本以为连接上了一台机器,但实际上却不是。由于反射中的参数都是字符串,同样,也会引起一系列的安全问题。下面给一个代码例子:
boolean connect(string s){
if (!isSecure(s)) {
throw new SecurityException();
//here will cause problem, if s is changed before this by using other references.
causeProblem(s);
总的来说Java String 设计成不可变的,考虑了设计、效率、安全等因素。事实上这也适用于其他Java面试中许多&为什么&的问题。在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
public final class String implements java.io.Serializable, Comparable&String&, CharSequence
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
String本身比较特殊,除了普通类的语法外,还有特殊的语法可以操作他,如果允许开发者继续封装,则会造成编译器无法识别并编译与String相关的语法(比如字符串赋值,字符串合并等)。与此相似的还有enum枚举的定义。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:
在 SegmentFault,学习技能、解决问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。Java中的String字符串为什么不可变_百度知道
Java中的String字符串为什么不可变
我有更好的答案
/zhidao/wh%3D600%2C800/sign=3feeb8a4f2f2b211e47b8d48faba7b093efbd3572c10dfcf7astring字符串可以变
采纳率:88%
来自团队:
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 word变成不可编辑 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信