string 订阅
string是C++、java、VB等编程语言中的字符串,字符串是一个特殊的对象,属于引用类型。 在java、C#中,String类对象创建后,字符串一旦初始化就不能更改,因为string类中所有字符串都是常量,数据是无法更改,由于string对象的不可变,所以可以共享。对String类的任何改变,都是返回一个新的String类对象。 C++标准库中string类以类型的形式对字符串进行封装,且包含了字符序列的处理操作。 [1-2] 展开全文
string是C++、java、VB等编程语言中的字符串,字符串是一个特殊的对象,属于引用类型。 在java、C#中,String类对象创建后,字符串一旦初始化就不能更改,因为string类中所有字符串都是常量,数据是无法更改,由于string对象的不可变,所以可以共享。对String类的任何改变,都是返回一个新的String类对象。 C++标准库中string类以类型的形式对字符串进行封装,且包含了字符序列的处理操作。 [1-2]
信息
属    性
编程语言
外文名
String
所属领域
计算机
中文名
字符串
string基本信息
String就是C++、java、VB等编程语言中的字符串,用双引号引起来的几个字符,如"Abc","一天".
收起全文
精华内容
下载资源
问答
  • TypeError: not all arguments converted during string formatting 举例 例如: >>> strs=(1,2,3,4) #创建一个集合 >>> ...

    前言

    在学习python中难免犯下一些幼稚的错误,为了方便后来人的学习与自己的进步,整理了在学习过程中犯下的错误,写下此篇文档。

    目录

    问题

    TypeError: not all arguments converted during string formatting

    举例

    例如:

     strs=(1,2,3,4)  #创建一个集合
     strs
     (1, 2, 3,4)
     >>> print 'strs= %s ' % strs
     Traceback (most recent call last):
       File "<pyshell#43>", line 1, in <module>
         print 'strs= %s ' % str
     TypeError: not all arguments converted during string formatting
    

    原因:1 % 操作符只能直接用于字符串(‘123’),列表([1,2,3])、元组,因此需要一一匹配操作符。

    解决方法

     print 'strs= %s' % (strs,)
    strs= (1, 2, 3,4)
    也可以用:
    print 'strs= %s,%s,%s,%s' % sstr
    strs= 1,2,3,4 
    

    #简单解释
    说明前后%和后面的参数数量不对应,比如

    File "<pyshell#37>", line 1, in <module>
    print '%f meters is the same as &f km' % (meters, kilometers)
    TypeError: not all arguments converted during string formatting
    

    后面有miles和kilometer两个参数,前面只有一个%f,还有一个打印错的&, 前后不一致; 如果改成

    print '%f miles is the same as %f km' % (miles, kilometers)
    

    就可以了

    补充

    如果还有不会的,可以关注下面的公众号,博主会在24小时内回复。
    在这里插入图片描述

    展开全文
  • String、StringBuffer与StringBuilder之间区别

    万次阅读 多人点赞 2019-05-08 18:25:33
    String StringBuffer StringBuilder String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间 StringBuffer是可变类,和线程安全的字符串...

     

    String     StringBuffer     StringBuilder
    String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间  StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量  可变类,速度更快
    不可变     可变    可变
       线程安全     线程不安全
       多线程操作字符串    单线程操作字符串

    一、Java String 类——String字符串常量

        简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,这样不仅效率低下,而且大量浪费有限的内存空间,所以经常改变内容的字符串最好不要用 String 。因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

    我们来看一下这张对String操作时内存变化的图:

          我们可以看到,初始String值为“hello”,然后在这个字符串后面加上新的字符串“world”,这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了“hello world”字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对经常性的字符串相关的操作,就需要使用Java提供的其他两个操作字符串的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。

    二、StringBuffer 和 StringBuilder 类——StringBuffer、StringBuilder字符串变量

    StringBuffer 字符串变量(线程安全)
    StringBuilder 字符串变量(非线程安
     

    对字符串进行修改的时候,特别是字符串对象经常改变的情况下,需要使用 StringBuffer 和 StringBuilder 类。

    和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象

    StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

    由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

    三者的继承结构

    三者的区别

    (1)字符修改上的区别(主要,见上面分析)

    (2)初始化上的区别,String可以空赋值,后者不行,报错

    ①String

    String s = null;   

    String s = “abc”;   

    ②StringBuffer

    StringBuffer s = null; //结果警告:Null pointer access: The variable result can only be null at this location

    StringBuffer s = new StringBuffer();//StringBuffer对象是一个空的对象

    StringBuffer s = new StringBuffer(“abc”);//创建带有内容的StringBuffer对象,对象的内容就是字符串”

    小结:(1)如果要操作少量的数据用 String;

    (2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;

    (3)单线程操作字符串缓冲区下操作大量数据 StringBuilder

     

        而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:
     String S1 = "This is only a" + " simple" + " test";
     StringBuffer Sb = new StringBuffer("This is only a").append(" simple").append(" test");
     你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个
     String S1 = “This is only a” + “ simple” + “test”; 其实就是:
     String S1 = “This is only a simple test”;  

    所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:
    String S2 = “This is only a”;
    String S3 = “ simple”;
    String S4 = “ test”;
    String S1 = S2 +S3 + S4;
    这时候 JVM 会规规矩矩的按照原来的方式去做


    在大部分情况下 StringBuffer > String
    StringBuffer
    Java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
    可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
    StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
    例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
    在大部分情况下 StringBuilder > StringBuffer

    java.lang.StringBuilder
    java.lang.StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。

    作者:每次上网冲杯Java时,都能看到关于String无休无止的争论。还是觉得有必要让这个讨厌又很可爱的String美眉,赤裸裸的站在我们这些Java色狼面前了。嘿嘿....

    众所周知,String是由字符组成的串,在程序中使用频率很高。Java中的String是一个类,而并非基本数据类型。 不过她却不是普通的类哦!!!

     

    【镜头1】 String对象的创建 
          1、关于类对象的创建,很普通的一种方式就是利用构造器,String类也不例外:String s=new String("Hello world"); 问题是参数"Hello world"是什么东西,也是字符串对象吗?莫非用字符串对象创建一个字符串对象?

          2、当然,String类对象还有一种大家都很喜欢的创建方式:String s="Hello world"; 但是有点怪呀,怎么与基本数据类型的赋值操作(int i=1)很像呀?

          在开始解释这些问题之前,我们先引入一些必要的知识:

    ★ Java class文件结构 和常量池 
          我们都知道,Java程序要运行,首先需要编译器将源代码文件编译成字节码文件(也就是.class文件)。然后在由JVM解释执行。
          class文件是8位字节的二进制流 。这些二进制流的涵义由一些紧凑的有意义的项组成。比如class字节流中最开始的4个字节组成的项叫做魔数 (magic),其意义在于分辨class文件(值为0xCAFEBABE)与非class文件。class字节流大致结构如下图左侧。

                                    

          其中,在class文件中有一个非常重要的项——常量池 。这个常量池专门放置源代码中的符号信息(并且不同的符号信息放置在不同标志的常量表中)。如上图右侧是HelloWorld代码中的常量表(HelloWorld代码如下),其中有四个不同类型的常量表(四个不同的常量池入口)。关于常量池的具体细节,请参照我的博客《Class文件内容及常量池 》

    Java代码  

    public class HelloWorld{  
        void hello(){  
            System.out.println("Hello world");  
        }  
    }  

          通过上图可见,代码中的"Hello world"字符串字面值被编译之后,可以清楚的看到存放在了class常量池中的字符串常量表中(上图右侧红框区域)。

     

    ★ JVM运行class文件

          源代码编译成class文件之后,JVM就要运行这个class文件。它首先会用类装载器加载进class文件。然后需要创建许多内存数据结构来存放class文件中的字节数据。比如class文件对应的类信息数据、常量池结构、方法中的二进制指令序列、类方法与字段的描述信息等等。当然,在运行的时候,还需要为方法创建栈帧等。这么多的内存结构当然需要管理,JVM会把这些东西都组织到几个“运行时数据区 ”中。这里面就有我们经常说的“方法区 ”、“堆 ”、“Java栈 ”等。详细请参见我的博客《Java 虚拟机体系结构 》 。

          上面我们提到了,在Java源代码中的每一个字面值字符串,都会在编译成class文件阶段,形成标志号 为8(CONSTANT_String_info)的常量表 。 当JVM加载 class文件的时候,会为对应的常量池建立一个内存数据结构,并存放在方法区中。同时JVM会自动为CONSTANT_String_info常量表中 的字符串常量字面值 在堆中 创建 新的String对象(intern字符串 对象,又叫拘留字符串对象)。然后把CONSTANT_String_info常量表的入口地址转变成这个堆中String对象的直接地址(常量池解 析)。 

          这里很关键的就是这个拘留字符串对象 。源代码中所有相同字面值的字符串常量只可能建立唯一一个拘留字符串对象。 实际上JVM是通过一个记录了拘留字符串引用的内部数据结构来维持这一特性的。在Java程序中,可以调用String的intern()方法来使得一个常规字符串对象成为拘留字符串对象。我们会在后面介绍这个方法的。

     

    ★ 操作码助忆符指令 
          有了上面阐述的两个知识前提,下面我们将根据二进制指令来区别两种字符串对象的创建方式:  

          (1) String s=new String("Hello world");编译成class文件后的指令(在myeclipse中查看):

    Class字节码指令集代码

     

    0  new java.lang.String [15]  //在堆中分配一个String类对象的空间,并将该对象的地址堆入操作数栈。  
    3  dup //复制操作数栈顶数据,并压入操作数栈。该指令使得操作数栈中有两个String对象的引用值。  
    4  ldc <String "Hello world"> [17] //将常量池中的字符串常量"Hello world"指向的堆中拘留String对象的地址压入操作数栈  
    6  invokespecial java.lang.String(java.lang.String) [19] //调用String的初始化方法,弹出操作数栈栈顶的两个对象地址,用拘留String对象的值初始化new指令创建的String对象,然后将这个对象的引用压入操作数栈  
    9  astore_1 [s] // 弹出操作数栈顶数据存放在局部变量区的第一个位置上。此时存放的是new指令创建出的,已经被初始化的String对象的地址 (此时的栈顶值弹出存入局部变量中去)。  

    注意:
    【这里有个dup指令。其作用就是复制之前分配的Java.lang.String空间的引用并压入栈顶。那么这里为什么需要这样么做呢?因为invokespecial指令通过[15]这个常量池入口寻找到了java.lang.String()构造方法,构造方法虽然找到了。但是必须还得知道是谁的构造方法,所以要将之前分配的空间的应用压入栈顶让invokespecial命令应用才知道原来这个构造方法是刚才创建的那个引用的,调用完成之后将栈顶的值弹出。之后调用astore_1将此时的栈顶值弹出存入局部变量中去。】     


     事实上,在运行这段指令之前,JVM就已经为"Hello world"在堆中创建了一个拘留字符串( 值得注意的是:如果源程序中还有一个"Hello world"字符串常量,那么他们都对应了同一个堆中的拘留字符串)。然后用这个拘留字符串的值来初始化堆中用new指令创建出来的新的String对象,局部变量s实际上存储的是new出来的堆对象地址。 大家注意了,此时在JVM管理的堆中,有两个相同字符串值的String对象:一个是拘留字符串对象,一个是new新建的字符串对象。如果还有一条创建语句String s1=new String("Hello world");堆中有几个值为"Hello world"的字符串呢? 答案是3个,大家好好想想为什么吧!

     

          (2)将String s="Hello world";编译成class文件后的指令:

    Class字节码指令集代码  

    0  ldc <String "Hello world"> [15]//将常量池中的字符串常量"Hello world"指向的堆中拘留String对象的地址压入操作数栈  
    2  astore_1 [str] // 弹出操作数栈顶数据存放在局部变量区的第一个位置上。此时存放的是拘留字符串对象在堆中的地址  

         和上面的创建指令有很大的不同,局部变量s存储的是早已创建好的拘留字符串的堆地址(没有new 的对象了)。 大家好好想想,如果还有一条穿件语句String s1="Hello word";此时堆中有几个值为"Hello world"的字符串呢?答案是1个。那么局部变量s与s1存储的地址是否相同呢?  呵呵, 这个你应该知道了吧。

     

    ★ 镜头总结: String类型脱光了其实也很普通。真正让她神秘的原因就在于CONSTANT_String_info常量表 拘留字符串对象 的存在。现在我们可以解决江湖上的许多纷争了。

       纷争1】关于字符串相等关系的争论

    Java代码 

    //代码1  
    String sa=new String("Hello world");            
    String sb=new String("Hello world");      
    System.out.println(sa==sb);  // false       
    //代码2    
    String sc="Hello world";    
    String sd="Hello world";  
    System.out.println(sc==sd);  // true   

           代码1中局部变量sa,sb中存储的是JVM在堆中new出来的两个String对象的内存地址。虽然这两个String对象的值(char[]存放的字符序列)都是"Hello world"。 因此"=="比较的是两个不同的堆地址。代码2中局部变量sc,sd中存储的也是地址,但却都是常量池中"Hello world"指向的堆的唯一的那个拘留字符串对象的地址 。自然相等了。

      【纷争2】 字符串“+”操作的内幕

    Java代码  

    //代码1  
    String sa = "ab";                                          
    String sb = "cd";                                       
    String sab=sa+sb;                                      
    String s="abcd";  
    System.out.println(sab==s); // false  
    //代码2  
    String sc="ab"+"cd";  
    String sd="abcd";  
    System.out.println(sc==sd); //true  

        代码1中局部变量sa,sb存储的是堆中两个拘留字符串对象的地址。而当执行sa+sb时,JVM首先会在堆中创建一个StringBuilder类,同时用sa指向的拘留字符串对象完成初始化,然后调用append方法完成对sb所指向的拘留字符串的合并操作,接着调用StringBuilder的toString()方法在堆中创建一个String对象,最后将刚生成的String对象的堆地址存放在局部变量sab中。而局部变量s存储的是常量池中"abcd"所对应的拘留字符串对象的地址。 sab与s地址当然不一样了。这里要注意了,代码1的堆中实际上有五个字符串对象:三个拘留字符串对象、一个String对象和一个StringBuilder对象。
          代码2中"ab"+"cd"会直接在编译期就合并成常量"abcd", 因此相同字面值常量"abcd"所对应的是同一个拘留字符串对象,自然地址也就相同。

     

    【镜头二】  String三姐妹(String,StringBuffer,StringBuilder) 
            String扒的差不多了。但他还有两个妹妹StringBuffer,StringBuilder长的也不错哦!我们也要下手了:
                               String(大姐,出生于JDK1.0时代)          不可变字符序列
                               StringBuffer(二姐,出生于JDK1.0时代)    线程安全的可变字符序列
                               StringBuilder(小妹,出生于JDK1.5时代)   非线程安全的可变字符序列 

     

    ★StringBuffer与String的可变性问题。 
             我们先看看这两个类的部分源代码:

    Java代码  

    //String   
    public final class String  
    {  
            private final char value[];  
      
             public String(String original) {  
                  // 把原字符串original切分成字符数组并赋给value[];  
             }  
    }  
      
    //StringBuffer   
    public final class StringBuffer extends AbstractStringBuilder  
    {  
             char value[]; //继承了父类AbstractStringBuilder中的value[]  
             public StringBuffer(String str) {  
                     super(str.length() + 16); //继承父类的构造器,并创建一个大小为str.length()+16的value[]数组  
                     append(str); //将str切分成字符序列并加入到value[]中  
            }  
    }  

         很显然,String和StringBuffer中的value[]都用于存储字符序列。但是,
          (1) String中的是常量(final)数组,只能被赋值一次。 
          比如:new String("abc")使得value[]={'a','b','c'}(查看jdk String 就是这么实现的),之后这个String对象中的value[]再也不能改变了。这也正是大家常说的,String是不可变的原因 。    
          注意:这个对初学者来说有个误区,有人说String str1=new String("abc"); str1=new String("cba");不是改变了字符串str1吗?那么你有必要先搞懂对象引用和对象本身的区别。这里我简单的说明一下,对象本身指的是存放在堆空间中的该对象的实例数据(非静态非常量字段)。而对象引用指的是堆中对象本身所存放的地址,一般方法区和Java栈中存储的都是对象引用,而非对象本身的数据。


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

          比如:new StringBuffer("abc")使得value[]={'a','b','c','',''...}(注意构造的长度是str.length()+16)。如果再将这个对象append("abc"),那么这个对象中的value[]={'a','b','c','a','b','c',''....}。这也就是为什么大家说 StringBuffer是可变字符串 的涵义了。从这一点也可以看出,StringBuffer中的value[]完全可以作为字符串的缓冲区功能。其累加性能是很不错的,在后面我们会进行比较。

         总结,讨论String和StringBuffer可不可变。本质上是指对象中的value[]字符数组可不可变,而不是对象引用可不可变。 

     

    ★StringBuffer与StringBuilder的线程安全性问题 
          StringBuffer和StringBuilder可以算是双胞胎了,这两者的方法没有很大区别。但在线程安全性方面,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对象只能读取,无法修改。试问:还有什么不安全的呢? 

     

    ★String和StringBuffer的效率问题(这可是个热门话题呀!) 
          首先说明一点:StringBuffer和StringBuilder可谓双胞胎,StringBuilder是1.5新引入的,其前身就是StringBuffer。StringBuilder的效率比StringBuffer稍高,如果不考虑线程安全,StringBuilder应该是首选。另外,JVM运行程序主要的时间耗费是在创建对象和回收对象上。
          我们用下面的代码运行1W次字符串的连接操作,测试String,StringBuffer所运行的时间。

    Java代码  

    //测试代码  
    public class RunTime{  
        public static void main(String[] args){  
               ● 测试代码位置1  
              long beginTime=System.currentTimeMillis();  
              for(int i=0;i<10000;i++){  
                     ● 测试代码位置2  
              }  
              long endTime=System.currentTimeMillis();  
              System.out.println(endTime-beginTime);     
        }  
    }  

    (1) String常量与String变量的"+"操作比较 
            ▲测试①代码:     (测试代码位置1)  String str="";
                                      (测试代码位置2)  str="Heart"+"Raid";
                [耗时:  0ms]
                 
           ▲测试②代码        (测试代码位置1)  String s1="Heart";
                                                               String s2="Raid";
                                                               String str="";
                                      (测试代码位置2)  str=s1+s2;
                [耗时:  15—16ms]
          结论:String常量的“+连接”  稍优于  String变量的“+连接”。 
          原因:测试①的"Heart"+"Raid"在编译阶段就已经连接起来,形成了一个字符串常量"HeartRaid",并指向堆中的拘留字符串对象。运行时只需要将"HeartRaid"指向的拘留字符串对象地址取出1W次,存放在局部变量str中。这确实不需要什么时间。 
                   测试②中局部变量s1和s2存放的是两个不同的拘留字符串对象的地址。然后会通过下面三个步骤完成“+连接”:
                                    1、StringBuilder temp=new StringBuilder(s1),
                                    2、temp.append(s2);
                                    3、str=temp.toString();
                   我们发现,虽然在中间的时候也用到了append()方法,但是在开始和结束的时候分别创建了StringBuilder和String对象。可想而知:调用1W次,是不是就创建了1W次这两种对象呢?不划算。

         但是,String变量的"+连接"操作比String常量的"+连接"操作使用的更加广泛。 这一点是不言而喻的。
        

    (2)String对象的"累+"连接操作与StringBuffer对象的append()累和连接操作比较。 
              ▲测试①代码:     (代码位置1)  String s1="Heart";
                                                           String s="";
                                        (代码位置2)  s=s+s1;
                 [耗时:  4200—4500ms]
                 
              ▲测试②代码        (代码位置1)  String s1="Heart";
                                                           StringBuffer sb=new StringBuffer();
                                        (代码位置2) sb.append(s1);
                 [耗时:  0ms(当循环100000次的时候,耗时大概16—31ms)]
             结论:大量字符串累加时,StringBuffer的append()效率远好于String对象的"累+"连接 
             原因:测试① 中的s=s+s1,JVM会利用首先创建一个StringBuilder,并利用append方法完成s和s1所指向的字符串对象值的合并操作,接着调用StringBuilder的 toString()方法在堆中创建一个新的String对象,其值为刚才字符串的合并结果。而局部变量s指向了新创建的String对象。

                      因为String对象中的value[]是不能改变的,每一次合并后字符串值都需要创建一个新的String对象来存放。循环1W次自然需要创建1W个String对象和1W个StringBuilder对象,效率低就可想而知了。


                      测试②中sb.append(s1);只需要将自己的value[]数组不停的扩大来存放s1即可。循环过程中无需在堆中创建任何新的对象。效率高就不足为奇了。        

     

    ★ 镜头总结:

        (1) 在编译阶段就能够确定的字符串常量,完全没有必要创建String或StringBuffer对象。直接使用字符串常量的"+"连接操作效率最高。

        (2) StringBuffer对象的append效率要高于String对象的"+"连接操作。

        (3) 不停的创建对象是程序低效的一个重要原因。那么相同的字符串值能否在堆中只创建一个String对象那。显然拘留字符串能够做到这一点,除了程序中的字符串常量会被JVM自动创建拘留字符串之外,调用String的intern()方法也能做到这一点。当调用intern()时,如果常量池中已经有了当前String的值,那么返回这个常量指向拘留对象的地址。如果没有,则将String值加入常量池中,并创建一个新的拘留字符串对象。

    全)

     

    参照:

    https://www.cnblogs.com/goody9807/p/6516374.html

    https://blog.csdn.net/u011702479/article/details/82262823

    https://blog.csdn.net/weixin_41101173/article/details/79677982

    展开全文
  • Java object转string

    万次阅读 多人点赞 2017-12-29 17:22:39
    public static createString(Object object ){ rerutn object!=null?object.toString():""; }

    public static createString(Object object ){

    rerutn  object!=null?object.toString():"";

    }

     

    展开全文
  • String、StringBuffer和StringBuilder的区别

    万次阅读 多人点赞 2019-06-16 10:31:19
    String、StringBuffer和StringBuilder的区别: 文章目录StringStringBufferStringBuilderStringBuffer是如何实现线程安全的呢?Java9的改进 String   String类是不可变类,即一旦一个String对象被创建以后,包含在...

    String、StringBuffer和StringBuilder的区别:

    String

      String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

      这个是String类的解释,之前小咸儿看到这个情况,不能理解上述的解释,如下

    String a = "123";
    a = "456";
    // 打印出来的a为456
    System.out.println(a)
    

      看到这里,小咸儿不明白了,这不是明明已经对他进行修改了吗?为什么还说他是一个不可变类呢?

      经过小咸儿和小伙伴们的学习,明白String类不可变在哪里体现出来的,接下来就看一张上述a对象的内存存储空间图
    在这里插入图片描述

      可以看出来,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。

    StringBuffer

      StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。

    StringBuffer b = new StringBuffer("123");
    b.append("456");
    // b打印结果为:123456
    System.out.println(b);
    

      在看一下b对象的内存空间图:
    在这里插入图片描述

      所以说StringBuffer对象是一个字符序列可变的字符串,它没有重新生成一个对象,而且在原来的对象中可以连接新的字符串。

    StringBuilder

      StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

    StringBuffer是如何实现线程安全的呢?

    StringBuffer类中实现的方法:

    在这里插入图片描述

    StringBuilder类中实现的方法:

    在这里插入图片描述

      由此可见,StringBuffer类中的方法都添加了synchronized关键字,也就是给这个方法添加了一个锁,用来保证线程安全。

    Java9的改进

      Java9改进了字符串(包括String、StringBuffer、StringBuilder)的实现。在Java9以前字符串采用char[]数组来保存字符,因此字符串的每个字符占2字节;而Java9的字符串采用byte[]数组再加一个encoding-flag字段来保存字符,因此字符串的每个字符只占1字节。所以Java9的字符串更加节省空间,字符串的功能方法也没有受到影响。

    展开全文
  • String.format()的详细用法

    万次阅读 多人点赞 2018-09-03 11:38:55
    问题 ...地区 上海 为可变的string数据  年龄 21 为可变的int数据  性别 男 为可变的string数据  遇到这种情况你们是怎么样解决的呢?把这段字符串保存在常量类里吗?不!我们应该遵循Google的开发...
  • 简化 java.lang.String 源码

    万次阅读 2020-09-25 14:09:17
    public final class String implements java.io.Serializable, Comparable<String>, CharSequence, Constable, ConstantDesc { @java.io.Serial private static final long serialVersion
  • String,StringBuffer与StringBuilder的区别

    万次阅读 多人点赞 2018-08-31 22:22:12
    一、Java String 类——String字符串常量 字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。 需要注意的是,String的值是不可变的,这就导致每次对String的...
  • String数组的创建

    万次阅读 2018-10-06 10:29:05
    string数组的定义有三种写法: String[] arr = new String[10]; //创建一个长度为10的String 类型数组。 String arr[] = new String[10]; String arr[] = {"张三","李四"}; 前面两种写法是一样的,可以...
  • Java 如何将String转化为Int

    万次阅读 多人点赞 2018-03-28 10:02:16
    在 Java 中要将 String 类型转化为 int 类型时,需要使用 Integer 类中的 parseInt() 方法或者 valueOf() 方法进行转换. 例1: 1 2 3 4 5 6String str = "123"; try {  int a = ...
  • 深入理解Java String

    万次阅读 多人点赞 2018-06-28 21:15:55
    在Java语言了中,所有类似“ABC”的字面值,都是String类的实例;String类位于java.lang包下,是Java语言的核心类,提供了字符串的比较、查找、截取、大小写转换等操作;Java语言为“+”连接符(字符串连接符)以及...
  • stringstream常见用法介绍

    万次阅读 多人点赞 2018-09-10 23:20:54
    本文主要介绍 C++ 中 stringstream 类的常见用法。 1 概述 <sstream> 定义了三个类:istringstream、ostringstream 和 stringstream,分别用来进行流的输入、输出和输入输出操作。本文以 stringstream 为主...
  • String类中split()方法的使用

    万次阅读 多人点赞 2018-09-25 16:24:45
    String类中split()方法的使用 今天在在使用split方法时,发现split()方法很怪异的现象,查询了官方文档和各种资料,总结如下 官方文档是这么介绍的: 大致意思就是 在给定的正则表达式来分割该字符串.此方法...
  • map格式和string格式转化为json格式

    万次阅读 2018-08-16 16:53:04
    1.Map转化为json ...String, Object> data; JSONObject dataJson = new JSONObject(data);//map转化为json String cano= dataJson.get("CarNO"); 2.String转化为json eg1 String results= saveorUp...
  • C++中的String的常用函数用法总结

    万次阅读 多人点赞 2018-08-27 09:15:36
    string的构造函数的形式: string str:生成空字符串 string s(str):生成字符串为str的复制品 string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值 ...
  • stringstringstream用法

    万次阅读 多人点赞 2017-09-23 10:04:03
    stringstringstream用法总结
  • ValueError: could not convert string to float 出错的地方为: month_diff = int(float(date_consumed[-6:-4])) - int(float(date_received[-6:-4])),这一句包含在函数get_time_diff中 我的目的是提取两个时间...
  • C++中的string类用法简介

    万次阅读 多人点赞 2019-08-21 17:21:17
    本文主要介绍C++中的string类的常见用法。 1. 概述 string是C++标准库的一个重要的部分,主要用于字符串处理。可以使用输入输出流方式直接进行string操作,也可以通过文件等手段进行string操作。同时,C++的算法库...
  • List转换成String字符串三种方式

    万次阅读 2019-08-15 11:58:34
    List转换成String字符串思路分析: 1.List转化成String[],再通过String[]数组遍历拼接成String字符串; 2.List转化成String存到StringBuffer中,再通过StringButter中的append()方法拼接成String字符串; 注意:...
  • String转化为String数组

    万次阅读 2018-09-25 16:52:42
    今天做项目遇到个问题,前台传给我一个String数组,但是我这儿接收的时候都是是String类型,那么就需要将String转为String数组 public class test { public static void main(String[] args) { String pcArray ...
  • required string parameter 'XXX'is not present 的几种情况 情况一:原因是由于头文件类型不对,可以在MediaType中选择合适的类型,例如GET和POST 情况二:jquery提交delete时,不支持@RequestParam,只支持@...
  • Java:String和Date、Timestamp之间的转换

    万次阅读 2017-01-15 21:36:33
    一、String与Date(java.util.Date)互转 // 1.1、String -> Date @org.junit.Test public void testStringToDate() throws ParseException { String dateStr = "2010-05-04 12:34:23"; //注意f
  • JVM系列之:String.intern和stringTable

    万次阅读 2020-07-26 11:25:57
    文章目录简介intern简介intern和字符串字面量常量分析intern返回的String对象分析实际的问题G1中的去重功能总结 简介 StringTable是什么?它和String.intern有什么关系呢?在字符串对象的创建过程中,StringTable有...
  • java String 转int,int转String

    万次阅读 2018-07-11 10:17:03
    说明: int和String之间的互转代码:在安卓中将String值转换成int有两种方法:1. int i = Integer.parseInt(String); 2. int i = Integer.valueOf(String).IntValue(); 将int转换成String:1.String str = String....
  • golang 中string和int类型相互转换

    万次阅读 多人点赞 2018-03-14 10:26:56
    总结了golang中字符串...string转成int: int, err := strconv.Atoi(string) string转成int64: int64, err := strconv.ParseInt(string, 10, 64) int转成stringstring := strconv.Itoa(int) int64转成string
  • TypeError: string indices must be integers

    万次阅读 2019-09-29 16:01:40
    Python3报错:TypeError: string indices must be integers 问题如下图所示: 原因在于for循环中的i代表String类型变量,而List中的i代表Int类型变量,二者冲突,导致出错。 ...
  • C++ string的用法和例子

    万次阅读 多人点赞 2016-08-24 15:31:19
    同时C++的算法库对string也有着很好的支持,而且string还和c语言的字符串之间有着良好的接口。虽然也有一些弊端,但是瑕不掩瑜。 其中使用的代码多数都是来自cpp官网,因为例子非常全。 声明和初始化方法: 想...
  • C++ 数值与 string 的相互转换

    万次阅读 多人点赞 2016-03-18 22:11:54
    使用函数模板将基本数据类型(整型、字符型、实型、布尔型)转换成string。//ostringstream对象用来进行格式化的输出,常用于将各种类型转换为string类型 //ostringstream只支持&amp;lt;&amp;lt;操作符 ...
  • 在项目中用到以下2中类型的转换(确保统一使用utf-8格式): ... String str = new String(bytes, StandardCharsets.UTF_8); } 二、String转byte[] String str = "string"; str.getBy...
  • String 转Array ,Array转String

    万次阅读 2019-07-13 20:32:22
    String s; char [] arr = s.toCharArray();//将String 转array String.valueOf(arr);//将array转String: https://www.runoob.com/java/number-valueof.html
  • java.lang.String 记录

    万次阅读 2020-06-24 11:47:34
    获取到操作系统的换行符 String newLine0 = System.lineSeparator(); String newLine1 = System.getProperty("line.separator");

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,809,705
精华内容 723,882
关键字:

string