`

关于String的三篇文章~~~

阅读更多
http://hi.baidu.com/rely_me/blog/item/b894d17fca459f0d28388ad7.html

全面理解Java中的String数据类型

前几天参加了重庆南华中天的一个笔试和面试其中笔试有一道题目是关于String类的,下面我们谈谈String:

1. 首先String不属于8种基本数据类型,String是一个对象。

  因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

  2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;

  3. String str=”kvill”;
String str=new String (“kvill”);的区别:

  在这里,我们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。

  常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。

  看例1:


String s0=”kvill”;
String s1=”kvill”;
String s2=”kv” + “ill”;
System.out.println( s0==s1 );
System.out.println( s0==s2 );


  结果为:


true
true


  首先,我们要知道Java会确保一个字符串常量只有一个拷贝。

  因为例子中的s0和s1中的”kvill”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而”kv”和”ill”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中”kvill”的一个引用。

  所以我们得出s0==s1==s2;

  用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。

  看例2:


String s0=”kvill”;
String s1=new String(”kvill”);
String s2=”kv” + new String(“ill”);
System.out.println( s0==s1 );
System.out.println( s0==s2 );
System.out.println( s1==s2 );


  结果为:


false
false
false


  例2中s0还是常量池中”kvill”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”kvill”的引用,s2因为有后半部分new String(“ill”)所以也无法在编译期确定,所以也是一个新创建对象”kvill”的应用;明白了这些也就知道为何得出此结果了。

  4. String.intern():

  再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用,如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;看例3就清楚了

  例3:


String s0= “kvill”;
String s1=new String(”kvill”);
String s2=new String(“kvill”);
System.out.println( s0==s1 );
System.out.println( “**********” );
s1.intern();
s2=s2.intern(); //把常量池中“kvill”的引用赋给s2
System.out.println( s0==s1);
System.out.println( s0==s1.intern() );
System.out.println( s0==s2 );


  结果为:


false
**********
false //虽然执行了s1.intern(),但它的返回值没有赋给s1
true //说明s1.intern()返回的是常量池中”kvill”的引用
true


  最后我再破除一个错误的理解:

  有人说,“使用String.intern()方法则可以将一个String类的保存到一个全局String表中,如果具有相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,如果在表中没有相同值的字符串,则将自己的地址注册到表中“如果我把他说的这个全局的String表理解为常量池的话,他的最后一句话,“如果在表中没有相同值的字符串,则将自己的地址注册到表中”是错的:

  看例4:


String s1=new String("kvill");
String s2=s1.intern();
System.out.println( s1==s1.intern() );
System.out.println( s1+" "+s2 );
System.out.println( s2==s1.intern() );


  结果:


false
kvill kvill
true


  在这个类中我们没有声名一个”kvill”常量,所以常量池中一开始是没有”kvill”的,当我们调用s1.intern()后就在常量池中新添加了一个”kvill”常量,原来的不在常量池中的”kvill”仍然存在,也就不是“将自己的地址注册到常量池中”了。

  s1==s1.intern()为false说明原来的“kvill”仍然存在;

  s2现在为常量池中“kvill”的地址,所以有s2==s1.intern()为true。

  5. 关于equals()和==:

  这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。


6.关于String是不可变的

  大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+” “+”ans”;
就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原因了,因为StringBuffer是可改变的


http://hi.baidu.com/rague/blog/item/4170cbf333169f55342acc6c.html

JAVA中 string s = "a"+"b"+"c"; 存储单元分配

在java中有一个字符常量的池,

String s="helloworld";
//先在池中找有没有这个常量字符串,有的话,把字符串的引用s指向"helloworld"的首地址。如果没有就把"helloworld"字符串放入池中,在把他的地址返回给s引用。

String str1=new String("helloworld");
String str2=new String("helloworld");

如果用这种方式建立对象的话,str1与str2不相等,用new关键字,建立一个字符串对象的时候,会在内存的堆中给对象分配存储空间,返回这个对象的引用(即地址)。
那么对于str1与str2来说相当与建立了两个字符串的对象,也就是String类的实例。会在堆中分配两块存储区来存放这两个对象,它们的地址当然是不会相等的了。如果有如下语句:
if(str1==str2)
System.out.println("equal");
else
System.out.println("not equal");
输出:not equal

这里虽然是这两个对象的内容是相等的。但是这里的str1和str2里面的值是这两个对象的引用。所以当然是不等的了。那么要比较两个对象的内容怎么办呢:

在java中提供了一个方法,也是每一个对象都有的方法
boolean equals(Object anObject) 这个方法是继承java中的基类Object的。具体的资料你可以去查java的帮助文档;

那么对于下面的例子:
String str1="helloworld";
String str2="helloworld";
if(str1==str2)
System.out.println("equal");
else
System.out.println("not equal");
输出结果:equal

因为在定义str1是把"helloworld"这个字符串常量放进常量池中。并把它的引用返回个str1
在定义str2时,系统先在常量池中找看有没有"helloworld"这个常量,这时侯系统找到了,直接把它的引用返回个str2,所以实际上这时侯str1和str2都指向同一个字符串常量。所以他们的引用是相等的。

至于你说怎么分配存储空间,对象是在堆里面分配存储空间的。而变量则在栈中,字符串常量对象在池中。

对于你的问题可以这样测试:

class test
{
public static void main(String [] args)
{
String str1="a"+"b"+"c";
String str2="abc";
if(str1==str2)
System.out.println("equal");
else
System.out.println("not equal");
}
}

输出结果:equal

这说明:系统先把"a"+"b"+"c"连接起来变成"abc"放入常量池中了。所以才有后面的相等了。

所以str1的值实际上是"abc"

说到这里相信你对这个已经有一个大概的了解了吧。要不然在去查哈资料。。。


http://hi.baidu.com/wangmei58/blog/item/f46a4bf8768c860cd9f9fd97.html

Java中String和StringBuffer的区别

在我以前的了解中,String是一个final Class, StringBuffer不是。所以对于 String a = "yacht" ,String b = "yacht1" String c = a + b ; 存在一个对象拷贝构造和解析的消耗问题;对于一个StringBuffer来说,StringBuffer sb = new StringBuffer();sb.append("yacht") ; sb.append("yacht1"); 因为StringBuffer是一个可以实例化的类,而且它的内建机制是维护了一个capacity大小的字符数组,所以它的append操作不存在对象的消耗问题,所以我觉得如果存在String连接这种事情,StringBuffer来做会好很多。
          但事情并不是这么简单,看下面代码

       String a = "yacht1" + "yacht2" + "yacht3" + "yacht4";

       StringBuffer sb = new StringBuffer(); sb.append("yacht1") ; sb.append("yacht2"); sb.append("yacht3") ; sb.append("yacht4");     String a = sb.toString();

          如果按照我先前说的看法,红色的效率肯定比蓝色的低,但经过测试不是这样,为什么?这里,我们需要理解程序过程的两个时期,一个是编译时,一个是运行时,在编译时,编译器会对你的程序做出优化,所以红色的String a会被优化成yacht1yacht2yacht3yacht4,而蓝色的StringBuffer只会在运行时才处理。所以效率是不一样的。

          如果代码是这样的:

       String a ; for(int i = 0; i< 100000;i++){ a += String.valueOf(i) ;}

       StringBuffer sb = new StringBuffer(); for(int i = 0; i< 100000;i++){ sb.append(i) ;} String a = sb.toString();

       如果是这种情况的话,红色的效率就大大不如蓝色,区别在哪里,就在于运行时和编译时的优化问题上!

          我在想,我们要做一个好的writer,不仅要知道怎么用,还要知道怎么用好,这需要内功的修练,花拳绣腿是招架不住的!
分享到:
评论

相关推荐

    String StringBuffer和StringBuilder区别之源码解析

    在这篇文章中,我们将从源码角度对String、StringBuffer和StringBuilder进行深入分析,了解它们之间的区别。 String类 String类是Java中最基本的字符串类,它是final类,意思是它不能被继承。String类的字符串是不...

    小心String的陷阱——深入剖析Java中String的处理机制

    文章由天津工业大学软件工程专业的翁龙辉撰写,旨在深入剖析`String`在Java中的独特行为及其潜在的陷阱。下面我们将详细探讨这些陷阱及其背后的原理。 ### String的不可变性 `String`在Java中被设计为不可变对象,...

    android用base64实现文件与string相互转换

    本篇文章将详细介绍如何在Android中使用Base64来实现文件与String之间的相互转换。 一、Base64编码原理 Base64是一种基于64个字符的编码方法,这些字符包括大小写字母、数字以及"+"和"/",还有一个用于填充的字符"=...

    Android图片Bitmap和字符串String之间的相互转换

    本篇文章将深入探讨如何在Android中进行Bitmap与String之间的转换,以及这些转换在实际应用中的场景。 首先,我们要理解Bitmap与String转换的原理。Bitmap是Android系统中用来表示图像的类,它包含了图像的所有像素...

    Java中的String池

    本篇文章将详细解释Java中的String池概念及其重要性,并通过一个示例代码深入理解String池的工作机制。 #### String池的基本概念 Java中的String池是一个特殊的数据结构,它存储了所有被程序引用的字符串字面量...

    convert string to integer

    在本篇文章中,我们将深入探讨如何在不同的编程语言中实现`convert string to integer`的功能,以帮助开发者更好地理解和应用这个概念。 首先,让我们以 Ruby 为例,这可能与提供的压缩包文件 `string_to_integer....

    C#_string_byte数组转换解析

    本篇文章将详细解析C#中如何进行这两种数据类型的转换,并讨论转换过程中需要注意的事项。 首先,我们来看最基础的转换方法: 1. **字符串(string)转为字节数组(byte[])**: 这个过程涉及到字符编码,C#中可以...

    c++string类源码

    本篇文章将深入解析`std::string`类的一些关键知识点,特别是根据标题描述提及的拷贝构造函数、深拷贝与浅拷贝、追加函数、赋值函数以及字符串比较和重载运算符。 1. **拷贝构造函数**: 拷贝构造函数是一种特殊的...

    String index out of 4解决方法

    本篇文章将详细介绍如何解决“String index out of 4”的问题,并提供一些实用的解决方案。 #### 一、理解异常原因 在深入探讨解决方案之前,首先需要了解为什么会发生这种异常。`StringIndexOutOfBoundsException...

    matlab开发-cell2string

    本篇文章将详细探讨`cell2string`函数的使用方法、原理以及相关的编程技巧。 `cell2string`函数的基本语法是: ```matlab str = cell2string(var) ``` 在这个表达式中,`var`是一个Cell数组,而`str`是转换后的字符...

    String类方法使用例子

    本篇文章将详细讲解`String`类的一些常用方法,并通过具体的例子来展示它们的用法。 1. **创建String对象** - `new String()`: 通过构造函数创建字符串,如 `String str = new String("Hello");` - 字符串字面量...

    java String类常用方法练习小结

    本篇文章将深入探讨`String`类的一些常用方法,并通过实际例子帮助你更好地理解和运用这些方法。 ### 1. 字符串排序 在**字符串练习一**中,我们展示了如何使用`compareTo`方法对字符串数组进行排序。`compareTo`...

    string 处理类

    本篇文章将深入探讨`String`类在处理字符串时的关键知识点,包括子串、字符串截断和合并。 一、子串(Substring) 在`String`类中,`substring()`方法用于获取字符串中的子串。它接受两个参数,分别表示子串的起始...

    用string拆分字符串

    本篇文章将深入探讨如何在各种编程语言中利用`string`来拆分字符串。 1. **Python中的字符串拆分** 在Python中,我们可以使用`split()`函数来拆分字符串。默认情况下,`split()`会根据空格拆分字符串,但也可以...

    string 类实现,构造函数、析构函数、操作符重载等

    在本篇文章中,我们将深入探讨一个自定义`String`类的实现细节,该类包含了构造函数、析构函数以及各种常用的操作符重载方法。通过具体的代码示例,我们可以更好地理解这些功能如何在C++中被实现。 #### 一、String...

    java 原始数组类型的String形式

    本篇文章将深入探讨如何将Java的原始数组类型转换为String形式,以及这个过程中的关键知识点。 首先,我们来看一下如何将整型数组(int[])转换为String。Java提供了一些内置的方法来帮助我们完成这个任务。最常用...

    C++ 标准库string replace成员的几个用法

    本篇文章将详细讲解 `std::string` 的 `replace` 成员函数的几个常见用法。 1. **替换指定长度的子串** ```cpp var.replace(3, 5, dest); ``` 这个例子中,`replace` 函数接受三个参数:起始位置、要替换的长度...

    《深入学习c++string》2.1版

    在本篇文章中,我们将深入探讨`std::string`的使用,涵盖其成员函数、构造、重载运算符以及与其他库如Boost和C字符串的结合使用。 1. C++ string 简介 C++的`std::string`是一个类模板,提供了动态可变长度的字符...

    StringFormat的使用(扩展:网络地址)

    本篇文章将深入探讨`StringFormat`的使用,并延伸到如何定义全局变量来存储网络地址。 1. `StringFormat`的基本使用 `StringFormat`的主要方法是`format()`,它可以接受一个格式字符串和多个参数,将参数按照指定的...

    CString,string,char*之间的转换

    随笔 - 764 文章 - 3 评论 - 196 CString,string,char*之间的转换(转) 这三种类型各有各的优点,比如CString比较灵活,是基于MFC常用的类型,安全性也最高,但可移植性最差。string是使用STL时必不可少的类型,...

Global site tag (gtag.js) - Google Analytics