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是可改变的 
 

  StringBuilder 类是字符串生成器,新创建的StringBuilder对象初始化容量为16个字符,也可以自己制定初始化长度,可以动态的执行添加,删除,插入等操作;如果附加的字符超过了制定的长度,StringBuilder将自动增加长度来容纳被附加的字符。

String(出现JDK1.0时代)              不可变字符序列
 StringBuffer(出现JDK1.0时代)      线程安全的可变字符序列
 StringBuilder(出现JDK1.5时代)    非线程安全的可变字符序列

 public class Jerque{
public static void main(String[] args){
String str = "";
long startTime = System.currentTimeMillis();
for (long i = 0;i<1000000 ;i++ ) {
str = str +1;
}
long endTime = System.currentTimeMillis();
long time = endTime - startTime;
System.out.println("String消耗时间:"+time);
long startTime1 = System.currentTimeMillis();
StringBulilder stringBuilder = new StringBulilder();
for (long j = 0;j<1000000 ;j++ ) {
stringBuilder.append(j);
}
long endTime1 = System.currentTimeMillis();
time1 = endTime1- startTime1;
System.out.println("stringBuilder消耗时间是:"+time1);
}
}

时间分别为:162933       33

StringBuilder是一个可变的字符序列,提供与StringBuffer兼容的API,但不保证与之同步,

在字符串缓存被单个线程使用的要比StringBuffer快,但是StringBuilder在多线程中是不安全的,

这个时候就要用到StringBuffer来实现。

看看String类的部分源代码:

 public final class String{
private final char value[];
public String(String orginal){
把源字符串orginal切割为字符数组并赋值给value[]
}
}

StringBuffer的部分源代码:

 public final class StringBuffer extends AbstractStringBuilder{
char value[]; //继承父类AbstractStringBuilder的value[]
public StringBuffer(String str){
super(str.length()+16); //继承父类的构造器,并且创建大小为str.length()+16的数组
append(str); //将字符串切割为字符并加入到value[]中
}
}

String和StringBuffer中的value[]都用于存储字符序列

(1) String中的是常量(final)数组,只能被赋值一次。

(2) StringBuffer中的value[]就是一个很普通的数组,而且可以通过append()方法将新字符串加入value[]末尾。这样也就改变了value[]的内容和大小了。

本质上是指对象中的value[]字符数组可不可变,而不是对象引用可不可变。

下面说说线程安全问题(StringBuilder和StringBuffer)

  StringBuffer允许多线程进行字符操作。这是因为在源代码中StringBuffer的很多方法都被关键字synchronized 修饰,而StringBuilder没有。

    有多线程编程经验的程序员应该知道synchronized。这个关键字是为线程同步机制 设定的。

    synchronized的含义:
      每一个类对象都对应一把锁,当某个线程A调用类对象O中的synchronized方法M时,必须获得对象O的锁才能够执行M方法,否则线程A阻塞。一旦线程A开始执行M方法,将独占对象O       的锁。使得其它需要调用O对象的M方法的线程阻塞。只有线程A执行完毕,释放锁后。那些阻塞线程才有机会重新调用M方法。这就是解决线程同步问题的锁机制。 
     了解了synchronized的含义以后,大家可能都会有这个感觉。多线程编程中StringBuffer比StringBuilder要安全多了 ,事实确实如此。如果有多个线程需要对同一个字符串缓冲区进行      操作的时候,StringBuffer应该是不二选择。
      注意:是不是String也不安全呢?事实上不存在这个问题,String是不可变的。线程对于堆中指定的一个String对象只能读取,无法修改。试问:还有什么不安全的呢?

StringBuilder的常用方法:

1、StringBuilder append(String str)方法:将参数str指定的字符串追加到字符串上生成器中;

2、StringBuilder append(StringBuffer sb) :将参数sb指定的字符串缓存StringBuilder的值追加到字符串生成器中;

3、StringBuilder insert(int offset,String str):offset字符串添加的小标索引位置;str 添加的字符串;

4、StringBuilder delete(int start,int end):移除字符串生成器中的子字符串,从start开始,到end结束;

5、StringBuilder toString():将字符串生成器的值转换为字符串

将字符串转换为Unicode编码:

 public class CharacterUnicode{
public static void main(String[] args){
String text = "成都耕者信息技术有限公司";
char[] charArray = text.toCharArray();
StringBulilder builder = new StringBuilder();
for (char c: charArray) {
builder.append((int)c+" ");
}
System.out.println("成都耕者信息技术有限公司的Unicode编码是:");
System.out.println(builder.toString());
}
}

去掉字符串中中重复字符:

 public class SBDelete{
public static void main(String[] args){
String s = "命运如同命运";
StringBulilder sb = new stringBuilder(s);
System.out.println("原来的字符串上是:"+sb);
System.out.println("原文的字符串长度:"+sb.length());
for (int i = 0;i<sb.length() ;i++ ) {
for (int j = i+1;sb.length() ;j++ ) {
if (sb.charAt(i)==sb.charAt(j)) {
sb.deleteCharAt(j);
}
}
}
System.out.println("现在的字符串是:"+sb);
System.out.println("现在的字符串长度是:"+sb.length());
}
}

String/ StringBuilder/ StringBuffer的更多相关文章

  1. 探秘Java中的String、StringBuilder以及StringBuffer

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...

  2. 探秘Java中String、StringBuilder以及StringBuffer

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...

  3. java中String、StringBuilder、StringBuffer三者的区别

    在Java项目开发中,字符串是最长使用的数据类型,而有关字符串的String.StringBuilder.StringBuffer三者又常常让人分不清楚什么时候该使用哪个. 特此整理一下. Strin ...

  4. Java中String、StringBuilder以及StringBuffer

    原文出处: 海子 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问到的地方,今天就来和大家一起学习一下String.StringBuilder和StringBuffe ...

  5. 解析Java中的String、StringBuilder、StringBuffer类(一)

    引言 String 类及其相关的StringBuilder.StringBuffer 类在 Java 中的使用相当的多,在各个公司的面试中也是必不可少的.因此,在本周,我打算花费一些时间来认真的研读一 ...

  6. 关于 String,StringBuilder,StringBuffer

    关于 String,StringBuilder,StringBuffer 的讨论,已有很多文章:在这里,我希望能刨根问底,更进一步的理解其中的原理. String String 是final类型,不可 ...

  7. String,StringBuilder,StringBuffer三者的区别

    参考   String,StringBuilder,StringBuffer三者的区别 这三个类之间的区别主要是在两个方面,即运行速度和线程安全这两方面. 1.运行速度 首先说运行速度,或者说是执行速 ...

  8. Java基础 -- String,StringBuilder,StringBuffer三者的区别

    结论 1-String,StringBuilder,StringBuffer 之间的区别主要是在两个方面,即运行速度和线程安全这两方面: 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:St ...

  9. String 、Stringbuilder和StringBuffer的区别

    JAVA平台提供了三个类:String.StringBuilder和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据.这个String类提供了数值不可改变的字符串.而这个S ...

  10. String、StringBuilder和StringBuffer的区别

    1         String.StringBuilder和StringBuffer的区别 String.StringBuilder.StringBuffer都可以用来保存字符串.如果是使用次数比较 ...

随机推荐

  1. Linux里AWK中split函数的用法

    跟java里的split函数的用法是很相像的,举例如下: The awk function split(s,a,sep) splits a string s into an awk array a u ...

  2. php添加或升级扩展模块步骤

    php添加或升级扩展模块步骤: 1).下载对应扩展的稳定版源码包2).进入到解压后的源码包执行: sudo /usr/local/php/bin/phpize //对应安装到哪个php版本 sudo ...

  3. 316python 基础之计算机基础、Python简介、变量、注释、基础数据类型初识、if、while、语句

    一.计算机基础. cpu:相当于人的大脑,运算与控制中心. 速度 飞机 内存:4G,8G,16G....暂时存储,供给cpu数据. 速度 高铁.成本高,断电即消失. 硬盘:相当于你电脑的数据库,存储着 ...

  4. _CRT_SECURE_NO_WARNINGS

    在新版编程器的编译过程中我们常常会遇到一些过时或者不安全的函数 举一个简单的例子: 很多带"_s"后缀的函数是为了让原版函数更安全,传入一个和参数有关的大小值,避免引用到不存在的元 ...

  5. 《机器学习实战》学习笔记第十一章 —— Apriori算法

    主要内容: 一.关联分析 二.Apriori原理 三.使用Apriori算法生成频繁项集 四.从频繁项集中生成关联规则 一.关联分析 1.关联分析是一种在大规模数据集中寻找有趣关系的任务.这些关系可以 ...

  6. 【转】如何在html与delphi间交互代码

    [转]如何在html与delphi间交互代码 (2015-11-19 22:16:24) 转载▼ 标签: it 分类: uniGUI uniGUI总群中台中cmj朋友为我们总结了如下内容,对于利用de ...

  7. pugixml 1.9 manual解读(部分)

    Plain character data nodes (node_pcdata) represent plain text in XML. PCDATA nodes have a value, but ...

  8. php数据结构课程---2、链表(php中 是如何实现单链表的(也就是php中如何实现对象引用的))

    php数据结构课程---2.链表(php中 是如何实现单链表的(也就是php中如何实现对象引用的)) 一.总结 一句话总结: php是弱类型语言,变量即可表示数值,也可表示对象:链表节点的数据域的值就 ...

  9. 多线程、方便扩展的Windows服务程序框架

    多线程.方便扩展的Windows服务程序框架 吴剑 2012-06-02 转载请注明出处:http://www.cnblogs.com/wu-jian/ 前言 在项目应用中经常会碰到定时调度的工作,比 ...

  10. PHP把时间转换成几分钟前、几小时前、几天前的几个函数、类分享

    这篇文章主要介绍了php计算时间几分钟前.几小时前.几天前的几个函数.类分享,需要的朋友可以参考下一.函数实现实例1: <?php header("Content-type: text ...