zoukankan      html  css  js  c++  java
  • Java源码解析|String源码与常用方法

    String源码与常用方法

    1.栗子

    代码:

    public class JavaStringClass {
    	
    	public static void main(String[] args) {
    		String s ="hello";
    		s = "world"; //内存地址已经修改 原来地址上的值还是不变的,只是失去了引用等待垃圾回收
    		String s2 = "hello"; //从常量池中找到并引用
    		String s4 = new String("hello"); //new产生一个新的对象 不会从常量池中引用
    		String s6 = "hel" + "lo";
    		String s7 = new String("hel") + new String("lo");
    		System.out.println(s == s2); //引用相等
    		System.out.println(s2 == s4); //引用不相等
    		System.out.println(s2.equals(s4)); //值相等 分析equals方法源码
    		System.out.println(s2 == s6); //引用相等 使用相 常量相加 也是从常量池中找到引用
    		System.out.println(s2 == s7); //引用不相等
    		
    		//开头字母大写
    		System.out.println(s2.substring(0,1).toUpperCase() + s2.substring(1));
    		
    		System.out.println(s2);
    	}
    }
    
    

    输出:

    2.String的不变性

    2-1:字符串常量池

    String s ="hello";
    String s2 = "hello";
    System.out.println(s == s2); //true  说明引用相等(地址相等)
    

    `s与s2引用相等即地址相等,原因是:Java把字符串常量存入字符串常量池

    而 String s4 = new String("hello"); s4和 s2的值不相等,是因为new会产生一个新的对象,不会从字符串常量池中找引用

    2-2:String的不变性

    `主要是因为 String 和保存数据的 char 数组,都被 final 关键字所修饰,所以是不可变的

    如下图所示:被final关键字修饰的变量(这里是字符数组),值不可以改变

    所以当 String s ="hello"; s = “world”时,s的内存地址(s的引用对象)已经改变了,
    说明产生了新的字符串对象,已经不再指向字符串常量池的“hello”,而是指向了“world”。

    3.String重写equal方法,判断相等

    1.先判断 引用是否相等 this == 传入的参数anobject,地址引用相等说明指向同一个对象,那么值肯定也相等了
    2.再使用instanceof 判断类型是否与String类型相等
    3.最后逐个判断 底层字符数组中的每一个字符是否相等

    public boolean equals(Object anObject) {
        // 判断内存地址是否相同
        if (this == anObject) {
            return true;
        }
        // 待比较的对象是否是 String,如果不是 String,直接返回不相等
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            // 两个字符串的长度是否相等,不等则直接返回不相等
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                // 依次比较每个字符是否相等,若有一个不等,直接返回不相等
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    

    4.String常用的操作方法

    4-1:字符串截取:
    方法1:public String substring(int beginIndex, int endIndex) // beginIndex:开始位置,endIndex:结束位置;
    方法2:public String substring(int beginIndex) //beginIndex:开始位置一直到到字符串末尾结束位置
    截取原理:substring 方法的底层使用的是字符数组范围截取的方法 :Arrays.copyOfRange(字符数组,开始位置,结束位置)

    4-2:字符串大小写:
    小写方法:String.toLowerCase() //小写
    大写方法:String.toUpperCase()//大写

    上面两种常用方法的综合应用:将首字母小写
    有时候我们会通过 applicationContext.getBean(className); 这种方式得到 SpringBean,这时 className 必须是要满足首字母小写的

    name.substring(0, 1).toLowerCase() name.substring(1);
    

    4-3:字符串替换、删除

    public void testReplace(){
      String str ="hello word !!";
      log.info("替换之前 :{}",str);
      str = str.replace('l','d');
      log.info("替换所有字符 :{}",str);
      str = str.replaceAll("d","l");
      log.info("替换全部 :{}",str);
      str = str.replaceFirst("l","");
      log.info("替换第一个 l :{}",str);
    }
    //输出的结果是:
    替换之前 :hello word !!
    替换所有字符 :heddo word !!
    替换全部 :hello worl !!
    替换第一个 :helo worl !!
    

    4-4:字符串拆分

    String s ="boo:and:foo";
    // 我们对 s 进行了各种拆分,演示的代码和结果是:
    s.split(":") 结果:["boo","and","foo"]
    s.split(":",2) 结果:["boo","and:foo"]
    s.split(":",5) 结果:["boo","and","foo"]
    s.split(":",-2) 结果:["boo","and","foo"]
    s.split("o") 结果:["b","",":and:f"]
    s.split("o",2) 结果:["b","o:and:foo"]
    

    但是会拆分出空值

    String a =",a,,b,";
    a.split(",") 结果:["","a","","b"]
    

    使用google的Guava快速去除空值

    String a =",a, ,  b  c ,";
    // Splitter 是 Guava 提供的 API 
    List<String> list = Splitter.on(',')
        .trimResults()// 去掉空格
        .omitEmptyStrings()// 去掉空值
        .splitToList(a);
    log.info("Guava 去掉空格的分割方法:{}",JSON.toJSONString(list));
    // 打印出的结果为:
    ["a","b  c"]
    

    4-5:字符串合并

    合并我们使用 join 方法,此方法是静态的,我们可以直接使用。
    方法有两个入参,参数一是合并的分隔符,参数二是合并的数据源

    不足:join不能连续合并(不能链式合并),无法过滤Join对象是List时的null值

    解决办法:使用Guava 提供的 API,Joiner快速合并

    // 依次 join 多个字符串,Joiner 是 Guava 提供的 API
    Joiner joiner = Joiner.on(",").skipNulls();
    String result = joiner.join("hello",null,"china");
    log.info("依次 join 多个字符串:{}",result);
    
    List<String> list = Lists.newArrayList(new String[]{"hello","china",null});
    log.info("自动删除 list 中空值:{}",joiner.join(list));
    
    // 输出的结果为;
    依次 join 多个字符串:hello,china
    自动删除 list 中空值:hello,china
    
  • 相关阅读:
    第二章——链表
    第一章:基本概念
    第八章
    画图
    关于写代码时的心态问题
    checked用id选择器找不到怎么办
    this指向问题
    es6箭头函数
    微信小程序——获取步数
    小程序——数据缓存
  • 原文地址:https://www.cnblogs.com/fisherss/p/11626108.html
Copyright © 2011-2022 走看看