zoukankan      html  css  js  c++  java
  • java 字符串

    可以证明,字符串操作时家属及程序设计中最常见的行为

    String类代表字符串。Java程序中的所有字符串文字(例如"abc" )都被实现为此类的实例。

    一. 不变的字符串

    1. 字符串不变; 它们的值在创建后不能被更改。 字符串缓冲区支持可变字符串。 因为String对象是不可变的,它们可以被共享

    2. String对象是不可变的,每当把String对象作为方法的参数传递时,都会复制一份引用.该引用所指的对象其实一直待在单一的物理位置上,从未动过.

    3. 给String对象赋值本质上是改变该String对象引用的指向.

    package strings;
    //: strings/Immutable.java
    import static net.mindview.util.Print.*;
    
    public class Immutable {
      public static String upcase(String s) {
        return s.toUpperCase();//将所有字母改为大写
      }
      public static void main(String[] args) {
        String q = "howdy";
        print(q); // howdy
        String qq = upcase(q);
        print(qq); // HOWDY
        print(q); // howdy
      }
    } /* Output:
    howdy
    HOWDY
    howdy
    *///:~

    三.重载 " + " 与StringBuilder

     1. String对象是不可变的,你可以给一个String对象加任意多的别名.因为String对象具有只读特性,所以指向它的任何引用都不可能改变它的值,因此,也就不会对其它引用有什么影响

    2.不可变性会带来一定的效率问题,为String对象重载的"+"操作符就是一个例子.//此种方式每+一次就会多一个String对象

    3. String的"+"操作经过编译器优化后是利用的StringBuilder对字符串进行拼接,性能不如直接使用StringBuilder拼接字符串要好.  

    package strings;
    //: strings/WhitherStringBuilder.java
    
    public class WhitherStringBuilder {
      public String implicit(String[] fields) {
        String result = "";
        for(int i = 0; i < fields.length; i++)
          result += fields[i];
        return result;
      }
      public String explicit(String[] fields) {
        StringBuilder result = new StringBuilder();
        for(int i = 0; i < fields.length; i++)
          result.append(fields[i]);
        return result.toString();
      }
    } ///:~
    生成的字节码如下
    
    public class strings.WhitherStringBuilder { 
      public strings.WhitherStringBuilder();
        Code:
           0: aload_0    // 将this引用推送至栈顶,即压入栈                
           1: invokespecial #8 //调用<init>方法实例化对象// Method java/lang/Object."<init>":()V
           4: return
    
      public java.lang.String implicit(java.lang.String[]);
        Code:
           0: ldc           #16 //将编号为#16的字符串推送至栈顶 // String
           2: astore_2     //将栈顶引用类型值存入第三个本地变量
           3: iconst_0      //将int型0推送至栈顶
           4: istore_3      //将栈顶int型数值存入第四个本地变量
           5: goto          32  //无条件跳转到32行
           8: new           #18  //新建一个StringBuilder对象编号#18,并将其引用压入栈顶// class java/lang/StringBuilder
          11: dup           //复制栈顶数值(在这里时引用)并将复制数值压入栈顶
          12: aload_2      //将第三个本地引用推送至栈顶
          13: invokestatic  #20//调用静态方法(这里调用了valueOf())// Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
          16: invokespecial #26//调用超类构造方法,实例初始化方法,私有方法 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
          19: aload_1       //将第二个引用本地变量(即数组引用)压入栈顶
          20: iload_3       //将第四个int本地变量压入栈顶
          21: aaload        //将引用数组指定索引的值推送至栈顶(即二个本地引用变量所代表的数组的下标为第四个int本地变量的值)
          22: invokevirtual #29//调用实例化方法append// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          25: invokevirtual #33 //调用实例化方法toString将结果转换为String// Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          28: astore_2          //将栈顶引用类型值存入第三个本地变量
          29: iinc          3, 1 //将第4个int本地变量加1
          32: iload_3          //将第4个int本地变量推至栈顶
          33: aload_1          //将第二个引用类型本地办理推送至栈顶,第二个引用应该是改方法的参数的数组的引用
          34: arraylength      //获得数组的长度并压入栈顶 
          35: if_icmplt     8  //比较栈顶两int数值的大小如果小于0跳转到第8行
          38: aload_2          //将第二个本地引用类型的本地变量推送至栈顶
          39: areturn          //返回栈顶引用型本地变量,并退出方法
    
      public java.lang.String explicit(java.lang.String[]);
        Code:
           0: new           #18                 // class java/lang/StringBuilder
           3: dup
           4: invokespecial #45                 // Method java/lang/StringBuilder."<init>":()V
           7: astore_2
           8: iconst_0
           9: istore_3
          10: goto          24
          13: aload_2
          14: aload_1
          15: iload_3
          16: aaload
          17: invokevirtual #29                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          20: pop
          21: iinc          3, 1
          24: iload_3
          25: aload_1
          26: arraylength
          27: if_icmplt     13
          30: aload_2
          31: invokevirtual #33                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          34: areturn
    }

     四. 无意识的递归

    1.容器类都有toString()方法,它生成的结果可以表达容器类自身,以及容器所包含的对象.

    2.如果想打印对象的内存地址,在toString()方法中不能使用this关键字的返回字符串,要返回String对象,this关键字会调用toString()方法,从而会产生递归调用 this.toString()->this.toString()  ...             

    要想正确打印地址,必须调用Object.toString()方法

    package strings;
    //: strings/InfiniteRecursion.java
    // Accidental recursion.
    // {RunByHand}
    import java.util.*;
    
    public class InfiniteRecursion {
      public String toString() {
        //!return this.toString(); //这里会递归调用
    return super.toString(); //正确的方法时调用Object的toString()方法
    }
    public static void main(String[] args) { List<InfiniteRecursion> v = new ArrayList<InfiniteRecursion>(); for(int i = 0; i < 10; i++) v.add(new InfiniteRecursion()); System.out.println(v); } } ///:~

    六.String上的操作

    方法参数,重载版本应用
    构造器 重载版本:默认版本,String,StringBuilder,StringBuffer,char数组,byte数组 创建String对象
    length()   String中字符的个数
    charAt() Int索引 取得String中该索引位置上的char
    getChars(),getBytes() 要复制的部分的起点和终点的索引,复制的目标数组,目标数组的起始索引 复制char或byte到一个目标数组中
    toCharArray()   生成一个char[],包含String的所有字符
    equals(),equalsIgnoreCase() 与之进行比较的String 比较两个String的内容是否相同
    compareTo 与之进行比较的String 按词典顺序比较String的内容,比较结果为负数,零或正数.注意,大小写并不等价
    contains    
    contentEquals() 与之比较的CharSequence或StringBuffer 如果该String与参数的内容完全一致,则返回true
    equalsIgnoreCase 与之进行比较的String 忽略大小写,如果两个String的内容相同,则返回true
    regionMatcher() 该String的索引偏移量,另一个String及其索引偏移量,要比较的长度.重载版本增加了"忽略大小写"功能 返回boolean结果,以表明所比较区域是否相等
    startsWith() 可能的起始String.重载版本在参数中增加了偏移量 返回boolean结果,以表明String是否以此参数起始
    endsWith() 该String可能的后缀String 返回boolean结果,以表明此参数在String中的起始索引.lastIndexOf()是从后向前搜索
    indexOf(),lastIndexOf() 重载版本包括:char,char与起始索引,String,String与起始索引 如果该String并不包含此参数,就返回-1;否则返回此参数在String中起始的索引.lastIndexOf()是从后向前搜索
    substring(subSequence()) 重载版本:起始索引;起始索引+终点坐标 返回一个新的String,以包含参数指定的子字符串
    concat() 要连接的String 返回一个新的String对象,内容为起始Stirng连接上参数String
    replace() 要替换掉的字符,用来进行替换的新字符,也可以用一个CharSequence来转换另一个CharSequence 返回替换字符后的新String对象.如果没有替换发生,则返回原始的String对象
    toLowerCase,toUpperCase()   将字符的大小写改变后,返回一个新String对象.如果没有发生改变,则返回原始的String对象
    trim()   将String两端的空白字符删除后,返回一个新的String对象.如果没有改变发生,则返回原始的String对象
    valueOf() 重载版本:Object;char[];char[],偏移量,字符个数; boolean; char; int; long; float; double 返回一个表示参数内容的String
    intern()   为每个唯一的字符序列生成一个且仅生成一个String引用
  • 相关阅读:
    从壹开始前后端分离[.NetCore ] 38 ║自动初始化数据库(不定期更新)
    从壹开始前后端分离[.NetCore] 37 ║JWT实现权限与接口的动态分配——复杂策略授权
    从壹开始微服务 [ DDD ] 之十二 ║ 核心篇【下】:事件驱动EDA 详解
    从壹开始微服务 [ DDD ] 之八 ║剪不断理还乱的 值对象和Dto
    从壹开始微服务 [ DDD ] 之七 ║项目第一次实现 & CQRS初探
    CentOS7下的CDH 6.2.0 安装过程
    php获取客户端IP地址的方法
    IntelliJIdea 2016.2 使用 tomcat 8.5 调试spring的web项目时,bean被实例化两次导致timer和thread被启动了两遍的问题的解决
    Linux 系统 TCP优化
    Fedora 25-64位操作系统中安装配置Hyperledger Fabric过程
  • 原文地址:https://www.cnblogs.com/jiangfeilong/p/10308166.html
Copyright © 2011-2022 走看看