java不变字串

请观察下述代码:
 

//: Stringer.java

public class Stringer {
  static String upcase(String s) {
    return s.toUpperCase();
  }
  public static void main(String[] args) {
    String q = new String("howdy");
    System.out.println(q); // howdy
    String qq = upcase(q);
    System.out.println(qq); // HOWDY
    System.out.println(q); // howdy
  }
} ///:~

q传递进入upcase()时,它实际是q的句柄的一个副本。该句柄连接的对象实际只在一个统一的物理位置处。句柄四处传递的时候,它的句柄会得到复制。
若观察对upcase()的定义,会发现传递进入的句柄有一个名字s,而且该名字只有在upcase()执行期间才会存在。upcase()完成后,本地句柄s便会消失,而upcase()返回结果——还是原来那个字串,只是所有字符都变成了大写。当然,它返回的实际是结果的一个句柄。但它返回的句柄最终是为一个新对象的,同时原来的q并未发生变化。所有这些是如何发生的呢?

1. 隐式常数
若使用下述语句:
String s = "asdf";
String x = Stringer.upcase(s);
那么真的希望upcase()方法改变自变量或者参数吗?我们通常是不愿意的,因为作为提供给方法的一种信息,自变量一般是拿给代码的读者看的,而不是让他们修改。这是一个相当重要的保证,因为它使代码更易编写和理解。
为了在C++中实现这一保证,需要一个特殊关键字的帮助:const。利用这个关键字,程序员可以保证一个句柄(C++叫“指针”或者“引用”)不会被用来修改原始的对象。但这样一来,C++程序员需要用心记住在所有地方都使用const。这显然易使人混淆,也不容易记住。

2. 覆盖"+"和StringBuffer
利用前面提到的技术,String类的对象被设计成“不可变”。若查阅联机文档中关于String类的内容(本章稍后还要总结它),就会发现类中能够修改String的每个方法实际都创建和返回了一个崭新的String对象,新对象里包含了修改过的信息——原来的String是原封未动的。因此,Java里没有与C++的const对应的特性可用来让编译器支持对象的不可变能力。若想获得这一能力,可以自行设置,就象String那样。
由于String对象是不可变的,所以能够根据情况对一个特定的String进行多次别名处理。因为它是只读的,所以一个句柄不可能会改变一些会影响其他句柄的东西。因此,只读对象可以很好地解决别名问题。
通过修改产生对象的一个崭新版本,似乎可以解决修改对象时的所有问题,就象String那样。但对某些操作来讲,这种方法的效率并不高。一个典型的例子便是为String对象覆盖的运算符“+”。“覆盖”意味着在与一个特定的类使用时,它的含义已发生了变化(用于String的“+”和“+=”是Java中能被覆盖的唯一运算符,Java不允许程序员覆盖其他任何运算符——注释④)。

④:C++允许程序员随意覆盖运算符。由于这通常是一个复杂的过程(参见《Thinking in C++》,Prentice-Hall于1995年出版),所以Java的设计者认定它是一种“糟糕”的特性,决定不在Java中采用。但具有讽剌意味的是,运算符的覆盖在Java中要比在C++中容易得多。

针对String对象使用时,“+”允许我们将不同的字串连接起来:
 

String s = "abc" + foo + "def" + Integer.toString(47);

可以想象出它“可能”是如何工作的:字串"abc"可以有一个方法append(),它新建了一个字串,其中包含"abc"以及foo的内容;这个新字串然后再创建另一个新字串,在其中添加"def";以此类推。
这一设想是行得通的,但它要求创建大量字串对象。尽管最终的目的只是获得包含了所有内容的一个新字串,但中间却要用到大量字串对象,而且要不断地进行垃圾收集。我怀疑Java的设计者是否先试过种方法(这是软件开发的一个教训——除非自己试试代码,并让某些东西运行起来,否则不可能真正了解系统)。我还怀疑他们是否早就发现这样做获得的性能是不能接受的。
解决的方法是象前面介绍的那样制作一个可变的同志类。对字串来说,这个同志类叫作StringBuffer,编译器可以自动创建一个StringBuffer,以便计算特定的表达式,特别是面向String对象应用覆盖过的运算符+和+=时。下面这个例子可以解决这个问题:
 

//: ImmutableStrings.java
// Demonstrating StringBuffer

public class ImmutableStrings {
  public static void main(String[] args) {
    String foo = "foo";
    String s = "abc" + foo +
      "def" + Integer.toString(47);
    System.out.println(s);
    // The "equivalent" using StringBuffer:
    StringBuffer sb =
      new StringBuffer("abc"); // Creates String!
    sb.append(foo);
    sb.append("def"); // Creates String!
    sb.append(Integer.toString(47));
    System.out.println(sb);
  }
} ///:~

创建字串s时,编译器做的工作大致等价于后面使用sb的代码——创建一个StringBuffer,并用append()将新字符直接加入StringBuffer对象(而不是每次都产生新对象)。尽管这样做更有效,但不值得每次都创建象"abc"和"def"这样的引号字串,编译器会把它们都转换成String对象。所以尽管StringBuffer提供了更高的效率,但会产生比我们希望的多得多的对象。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
, string
, 对象
, stringbuffer
, 句柄
, 顺序串c++
, 一个
复杂字串
java截取字符串、java 字符串转日期、java 字符串转数字、java 字符串比较、java解析json字符串,以便于您获取更多的相关知识。

时间: 2024-10-05 20:53:01

java不变字串的相关文章

关于java问题-切割字串的問題(java)

问题描述 切割字串的問題(java) 我想要做一個切token的程式, 請問要怎麼用java切割字串? 如果我想跟hash要怎麼做? 解决方案 用string.split函式.你可以指定分割符或者用正则表达式来分割."跟hash"不知道你说的是什么意思.http://www.cnblogs.com/mingforyou/archive/2013/09/03/3299569.html 解决方案二: 难道是港澳台的同胞么?繁体字. 问题没有描述太清楚 解决方案三: 字串问题

java MD5算法返回数字型字串

算法   常有人问及MD5算法为何有些程序片断返回完全数字型结果而有些返回数字与字母的混合字串. 其实两种返回结果只是因为加密结果的不同显示形式,Blog中已经有.Net的实现,在此附加JAVA实现,供参考. JAVA的标准类库理论上功能也很强大,但由于虚拟机/运行时的实现太多,加之版本差异,有些代码在不同环境下运行会出现奇怪的异常结果,尤其以涉及字符集的操作为甚. package com.bee.framework.common; import java.security.MessageDig

io流-JAVA怎么从特定【行】开始读字串?

问题描述 JAVA怎么从特定[行]开始读字串? 就是JAVA随机读,不是按byte定位,按行数定位,最好还能获取该文件所有的行数,然后多线程split读取 解决方案 按行,你首先就要先找到对应的行,然后完成读Java 对文件的操作,你可以采用最基本的:一个字节一个字节读,然后判回车换行符,完成一行的读取.循环以上步骤,直到读到你想要行的数据. 解决方案二: 随机读写可以通过java.io.RandomAccessFile类.但是 你要按 行 读取,能不能 先做下预处理 记录下行. 解决方案三:

string-java字符串中求字串的个数。求大神指点。谢谢

问题描述 java字符串中求字串的个数.求大神指点.谢谢 package z_1; public class Z_4 { /* * 计算某个字符串在另一个字符串中出现的次数 */ public static void main(String[] args) { // TODO Auto-generated method stub String s="kkaaskkadidkkddspqlkk"; getCount(s,"kk"); sop(getCount(s,&q

java-求字符串中相同最长的字串

问题描述 求字符串中相同最长的字串 用java程序写 题目:输入一行字母组成的字符串,找出其中出现的相同且 长度最长的字符串,输出它及其首字符的位置. 如yyabrdabjcabreg,则输出为abr,3.异常情况输出-1 解决方案 /** * 思路:"abdab" 拆分情况:1.ab abd abda abdab 2.bd bda bdab 3 da dab 4 ab 5 b * * @param str * @return */ public static String find(

【算法趣题】产生随机DNA序列(字串)

[题目说明]写一段程序(不限语言),能够按要求产生随机DNA序列(字串). DNA序列由A.T.C.G四种碱基(字符)组成.现要求按A 10%, T 20%, C 30%, G 40% 的比例产生长度为100个碱基的DNA序列. 注意要随机程度好,且符合比例要求. 我先抛砖引玉了:(大家最好先别看我的程序,否则可能会影响你自己的思路) 以下是HTML网页特效代码,点击运行按钮可查看效果: [Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]

Unicode控件的字串参数问题

控件|问题 写Unicode控件时发现的传字串参数的问题:问题描述:   Unicode的OCX,属性参数Text,类型:BSTR.   控件的源码(VC中)   afx_msg void SetText(LPCTSTR lpszText)    VB调用1:   Dim strTest As String    strTest = Text1.Text       'Text1文本框为空    If Not IsNull(strTest) Then       TestOCX2221.stri

关于jet db的连接字串,以及加密后的字串

加密 关于jet db的连接字串,以及加密后的字串   问题: 关于jet db的连接字串,以及加密后的字串ADO连接MDB文件的字串如何写?加密以后如何写?  回答: access数据库加密分3种以下以access xp为例 1.工具 -> 安全-> 加密/解密数据库,打开时无需任何更改 2.工具 -> 安全-> 设置数据库密码,打开密码为 1 打开时需要使用"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\1.mdb;U

返回字串的拼音首字母

拼音 //////////////////////////////////////////////////////////////file://函数名:gf_getfirstletter(string)file://功能:返回字串的拼音首字母,支持混合字符串(可以包含非汉字)file://参数:as_inputstringfile://返回值:stringfile://created 大同 张和平 dtzhp@yeah.net///////////////////////////////////