zoukankan      html  css  js  c++  java
  • Java源码阅读计划(1) String<I>

    Java源码阅读计划(1) String类

    1.1不变性

    HashMapkey建议使用不可变类,比容String这种,这里的不可变类指的色类中的一个值一旦初始化,将无法改变,如果修改,那就将会还是新的一个类。接下来我简单的演示一下:

            String s = "hello";
            s = "world";
    

    非常简单的例子,我们看看第一行s的地址

    再看看第二行s的地址

    我们打开rt.jar,再打开java底下的lang包,找到String类,

    在这里我们看到了两个final,
    1.首先是类上的finalString无法被继承,也就是说所有String中的方法无法被继承覆写
    2.接着是保存字符串的char数组,同样的被final修饰,也就是说value数组一旦被初始化,它的内存地址是无法被修改的,value的权限是private,外部访问不到,String也没开放修改值的方法,所以我们可以认为value一旦被赋值,内存地址是无法被修改的。
    这就是String不变性的原因,当我们想设计一个不变性类的时候,可以模仿这种样式。

    所以大多数String的方法,都必须有返回值的。

    1.2相等判断

    String类中,有两个判断相等的方法equals()equalsIgnoreCase(),接下来我详细的讲讲这两个方法。
    equals()相信大家并不陌生,Java学习之初,就有一个equals()==的区别这一个知识点,这区别今后再立一个专题来谈谈。

        public boolean equals(Object anObject) {
            if (this == anObject) {
                return true;
            }
            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;
        }
    

    equals()的方法设计的很巧妙,依照String的底层结构进行设计,先进行对象判断,接下先用长度,然后再一个一个字符进行比较,对方法性能有优化。
    接着再看看equalsIgnoreCase(),这个方法是忽略大小写的相等比较

        public boolean equalsIgnoreCase(String anotherString) {
            return (this == anotherString) ? true
                    : (anotherString != null)
                    && (anotherString.value.length == value.length)
                    && regionMatches(true, 0, anotherString, 0, value.length);
        }
    

    又是一个巧妙设计,利用&&的短路判断有性能的优化,接下来看看regionMatches()方法,

        public boolean regionMatches(boolean ignoreCase, int toffset,
                String other, int ooffset, int len) {
            char ta[] = value;
            int to = toffset;
            char pa[] = other.value;
            int po = ooffset;
            if ((ooffset < 0) || (toffset < 0)
                    || (toffset > (long)value.length - len)
                    || (ooffset > (long)other.value.length - len)) {
                return false;
            }
            while (len-- > 0) {
                char c1 = ta[to++];
                char c2 = pa[po++];
                if (c1 == c2) {
                    continue;
                }
                if (ignoreCase) {
                    char u1 = Character.toUpperCase(c1);
                    char u2 = Character.toUpperCase(c2);
                    if (u1 == u2) {
                        continue;
                    }
                    if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                        continue;
                    }
                }
                return false;
            }
            return true;
        }
    

    逻辑很易懂,这里虽然统一使用了大写作为比较标准,可之后又使用小写再进行判断,这是Java为了针对Georgian(格鲁吉亚)字母表奇怪的大小写转换规则而专门又增加了一步判断,就是转换成小写再比较一次。

    1.3替换

    替换也是平常常用的一个功能,有replace()替换所有选定字符,有relaceAll() 替换字符串所有匹配给定的正则表达式的子字符串,还有replaceFirst()等,在特定位置替换的方法。
    先讲讲replace()Java中的replace()有两种重载形式,一种是单字符,另外一种是字符串,

    public String replace(char oldChar, char newChar) {
            if (oldChar != newChar) {
                int len = value.length;
                int i = -1;
                char[] val = value; /* avoid getfield opcode */
    
                while (++i < len) {
                    if (val[i] == oldChar) {
                        break;
                    }
                }
                if (i < len) {
                    char buf[] = new char[len];
                    for (int j = 0; j < i; j++) {
                        buf[j] = val[j];
                    }
                    while (i < len) {
                        char c = val[i];
                        buf[i] = (c == oldChar) ? newChar : c;
                        i++;
                    }
                    return new String(buf, true);
                }
            }
            return this;
        }
    

    这段比较容易懂,

        public String replace(CharSequence target, CharSequence replacement) {
            return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
                    this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
        }
    

    另外一个方法,CharSequence是一个接口,与String不同,它是可读可写序列,至于下面的,QAQ等我看完Pattern类之后在进行详细分析。
    接下来说说replaceAll(),该方法替换字符串所有匹配给定的正则表达式的子字符串,

       public String replaceAll(String regex, String replacement) {
            return Pattern.compile(regex).matcher(this).replaceAll(replacement);
        }
    

    TODO:这个详解等Pattern类看完一起处理。
    至于repalceFirst()也同样等Pattern解决完一起来

        public String replaceFirst(String regex, String replacement) {
            return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
        }
    
    
  • 相关阅读:
    Android 基于人脸识别 SDK使用总结
    基于虹软人脸识别Demo android人脸识别
    Android Arcface 2.0人脸识别注册失败问题
    C#人脸识别之人脸特征值的提取及识别
    Arcface demo
    人脸识别基于Android
    基于Android 虹软人脸、人证对比,活体检测
    虹软AI 人脸识别SDK接入 — 性能优化篇(多线程)
    Android 安卓人脸识别(百度人脸识别)快速集成采坑
    [mysql 存储过程]MySQL存储过程详解 mysql 存储过程
  • 原文地址:https://www.cnblogs.com/figsprite/p/11743962.html
Copyright © 2011-2022 走看看