zoukankan      html  css  js  c++  java
  • [07] String字符串


    1、相同又不同的字符串

    String str1 = new String("String"); 
    String str2 = "String";
    String str3 = "String";
    System.out.println(str2 == str1); //false
    System.out.println(str2 == str3); //true

    如上,我们说String是引用数据类型,那么为什么这里有三个对象,str1和str2的结果是false,而str2和str3为true,表明它们俩最终指向的是同一对象呢?

    这要从字符串的创建方式来说明,使用new是每次创建一个新的对象,而用赋值的方式,实际上先搜寻常量池是否有可用,有则直接给予,否则新建。所以问题来了,什么是字符串常量池?

    字符串的分配,和其他的对象分配一样,耗费高昂的时间与空间代价,作为最基础的数据类型,大量频繁的创建字符串,极大程度地影响程序的性能,所以JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化:
    • 为字符串开辟一个字符串常量池,类似于缓存区
    • 创建字符串常量时,首先坚持字符串常量池是否存在该字符串
    • 存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中

    所以上面str2和str3实际上都是常量池中“String”的引用,自然完全相同,比对结果为true。

    有一道经典的面试题:
    String str = new String(“abc”) 创建多少个对象?
    //所以,如果常量池中没有"abc",则创建了2个对象,一个放在常量池,一个放在堆;否则创建一个对象和一个引用

    所以变化一下:
    String str1 = new String("A"+"B") ; 会创建多少个对象? 
    
    str1:
    字符串常量池:"A","B","AB" : 3个
    堆:new String("AB") :1个
    引用: str1 :1个
    总共 : 5个

    简单总结:
    • 单独使用""引号创建的字符串都是常量,编译期(保存在.class文件中)就已经确定存储到常量池中
    • 使用new String("")创建的对象会存储在堆中,是运行期新创建的
    • 使用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能确定,已经确定存储到常量池中
    • 使用包含变量的字符串连接符如"aa" + str1创建的对象是运行期才创建的,存储在堆中

    而之所以能实现这些,也是有基础的:
    • 字符串本质上是不可变的(所谓的字符串连接无非是新建字符串,更改指向,而不是修改原有),不用担心数据冲突进行共享
    • 运行时实例创建的全局字符串常量池中有一个表,总是为池中每个唯一的字符串对象维护一个引用,这就意味着它们一直引用着字符串常量池中的对象,所以,在常量池中的这些字符串不会被垃圾收集器回收

    更多参考:



    2、常用方法

    2.1 String常用方法

    返回长度
    length()   //返回字符串的长度
    转换(替换)字符
    toLowerCase()   //转换字符串为小写(仅针对字符串中的字母进行变化)
    toUpperCase()  //转换字符串为大写(仅针对字符串中的字母进行变化)
    repalce(char oldChar, char newChar)  // 将字符串中所有oldChar字符替换为newChar字符 字符串函数替换后需要赋值给新的字符串,旧字符串不会改变也不会重新指向新字符串
    repalceFirst(String regex, String replacement)  // 用字符串replacement的内容替换当前字符串中遇到的第一个和字符串regex一致的子串,并返回新的字符串(字符串长度可以不同,不会顶替掉未要求替换的字符)
    repalceAll(String regex, String replacement)  // 用字符串replacement的内容替换当前字符串中遇所有和字符串regex一致的子串,并返回新的字符串(字符串长度可以不同,不会顶替掉未要求替换的字符)
    valueOf(Object obj)   //将某个对象的实例转换成字符串 return:if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned. (而对于基本数据类型,如int 1,则会转成"1")
    提取字符
    charAt(int index)   //返回字符串的第index个位置的字符
    substring(int beginindex)   //返回从beginindex位置(包括该位置)开始到结尾的所有字符
    substring(int beginindex, int endindex)  //返回从beginindex位置(包括)开始到endindex(不包括)的所有字符
    比较字符
    compareTo(String anotherString)  //字符串比较,返回值为前者减后者的二者差(两个字符串同时从左往右比对,差值为首个不同字符的ASCII码的差值,数字字符为ASCII码相减)两个字符串完全相同输出为0
    equals(Object anObject)   //比较两个字符串的内容是否相同(大小写敏感),是则返回true,否则返回false
    equalsIgnoreCase(String anotherString)   //比较两个字符串的内容是否相同(忽略大小写),是则返回true,否则返回false
    regionMatches(int toffset, String other, int ooffset, int len)  //比较本串从toffset(包含)开始的len个字符和other串从ooffset开始的len个字符是否一致,返回值为boolean型
    starstWith(String prefix)   //比较字符串是否以prefix开始,返回值为boolean型
    endsWith(String suffix)   //比较字符串是否以suffix结束,返回值为boolean型
    matches(String reg)   //某字符串是否匹配reg正则表达式
    查找字符位置
    indexOf(int ch)   //返回某个字符在本字符串中第一次出现的位置,没有找到就输出-1
    indexOf(String str)   //返回某个字符串在本字符串中第一次出现的位置,没有找到就输出-1
    indexOf(int ch, int fromIndex)  //返回某个字符在字符串中从fromindex位置开始查找的第一次出现的位置,没有找到就输出-1
    indexOf(String str, int fromIndex)  //返回某个字符串在字符串中从fromindex位置开始查找的第一次出现的位置,没有找到就输出-1
    lastIndexOf(int ch) //返回某个字符在本字符串中最后一次出现的位置,没有找到就输出-1   
    lastIndexOf(String str) //返回某个字符串在本字符串中最后一次出现的位置,没有找到就输出-1
    lastIndexOf(int ch, int fromIndex)  //返回某个字符在字符串中到fromindex位置开始查找的最后一次出现的位置,没有找到就输出-1
    lastIndexOf(String str, int fromIndex)  //返回某个字符串在字符串中到fromindex位置开始查找的最后一次出现的位置,没有找到就输出-1
    contains(CharSequence s)  //是否包含某个字符
    连接字符串
    concat(String str)   //将参数中的字符串str连接到原字符串的后面
    去掉空格
    trim()  //去掉字符串开头和结尾的空格并返回新字符串,注意,中间的空格不会去掉

    2.2 String的format

    另外,String还有一个静态方法format,用于创建格式化的字符串,常用 format (String format, Object... args),指定字符串格式和参数,生成格式化后的新的字符串。

    如示例:
    public static void main(String[] args) {  
        String str=null;  
        str=String.format("Hi,%s", "王力");  
        System.out.println(str);  
        str=String.format("Hi,%s:%s.%s", "王南","王力","王张");            
        System.out.println(str);                           
        System.out.printf("字母a的大写是:%c %n", 'A');  
        System.out.printf("3>7的结果是:%b %n", 3>7);  
        System.out.printf("100的一半是:%d %n", 100/2);  
        System.out.printf("100的16进制数是:%x %n", 100);  
        System.out.printf("100的8进制数是:%o %n", 100);  
        System.out.printf("50元的书打8.5折扣是:%f 元%n", 50*0.85);  
        System.out.printf("上面价格的16进制数是:%a %n", 50*0.85);  
        System.out.printf("上面价格的指数表示:%e %n", 50*0.85);  
        System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g %n", 50*0.85);  
        System.out.printf("上面的折扣是%d%% %n", 85);  
        System.out.printf("字母A的散列码是:%h %n", 'A');  
    } 

    输出:
    Hi,王力  
    Hi,王南:王力.王张  
    字母a的大写是:A   
    3>7的结果是:false   
    100的一半是:50   
    100的16进制数是:64   
    100的8进制数是:144   
    50元的书打8.5折扣是:42.500000 元  
    上面价格的16进制数是:0x1.54p5   
    上面价格的指数表示:4.250000e+01   
    上面价格的指数和浮点数结果的长度较短的是:42.5000   
    上面的折扣是85%   
    字母A的散列码是:41 

    转换符说明如下:
    转换符    说明    e.g.    
    %s    字符串类型    "mingrisoft    "
    %c    字符类型    'm'    
    %b    布尔类型    true    
    %d    整数类型(十进制)    99    
    %x    整数类型(十六进制)    FF    
    %o    整数类型(八进制)    77    
    %f    浮点类型    99.99    
    %a    浮点类型(十六进制)    FF.35AE    
    %e    指数类型    9.38e+5
    %g    通用浮点类型 
    %h    散列码    
    %%    百分比类型    
    %n    换行符    
    %tx    日期与时间类型


    2.3 String的spilt

    spilt可以将一个字符串分割为子字符串,然后将结果(子串的数组)作为字符串数组返回。

    stringObj.split( separator,[limit] )
    • separator 必填,分隔符,支持正则表达式
    • limit 可选,该值用来限制返回数组中元素的个数

    使用时注意以下几点:
    • 如果用“.”作为分隔的话,必须是如下写法:String.split("\."),这样才能正确的分隔开,不能用String.split(".");
    • 如果用“|”作为分隔的话,必须是如下写法:String.split("\|"),这样才能正确的分隔开,不能用String.split("|"); “.”和“|”都是转义字符,必须得加"\";
    • 如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“a=1 and b =2 or c=3”,把三个都分隔出来,可以用String.split("and|or");

    2.4 String和char[]

    字符串转换为字符数组:
    //将当前字符串中一部分复制到指定参数dst数组中去,并从dstBegin处开始存放
    void getChars(int srcBegni, int srcEnd, char[] dst, int dstBegin)
    
    //初始化一个字符数组,长度和字符串长度相等
    char[] toCharArray()

    字符数组转字符串,调用字符串的构造方法:
    String(char[] value)
    
    String(char[] value, int offset, int count)


    3、StringBuffer和StringBuilder

    字符串的本质是不可变的,但是如果我们需要频繁地用到字符串的变动更改,就要用到StringBuffer,称之为字符串缓冲对象。实际上,诸如str1+str2这样的操作,也是将两者转换为StringBuffer来进行操作的。

    常见构造函数为 new SringBuffer(String str)

    StringBuilder是一个和StringBuffer类似的字符缓冲区,与StringBuffer兼容,然而:
    • StringBuffer在一个时候只能让一个线程去访问它,线程安全
    • StringBuilder是非线程安全的,所以单线程的话,StringBuilder的速度更快


  • 相关阅读:
    SNMP、rrdtool
    mysqldump命令备份数据
    Ansible之playbook&&roles
    敏捷软件开发 原则、模式与实践 第9章的例子程序(C#版)
    iis websocket
    EDM 邮件营销 html&css编写建议和规范整理
    Microsoft .NET Framework
    线程上下文切换
    系统调用 用户态 内核态
    文件系统
  • 原文地址:https://www.cnblogs.com/deng-cc/p/7461706.html
Copyright © 2011-2022 走看看