百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

String类解析 (三)方法解析

toyiye 2024-06-21 12:37 10 浏览 0 评论

本次不考虑已被标记为过时的方法

//String 的长度就是字符数组的长度
public int length() {
 return value.length;
}
//字符数组长度为0时表示空字符串
public boolean isEmpty() {
 return value.length == 0;
}
//返回String对象index位置上的元素
public char charAt(int index) {
 if ((index < 0) || (index >= value.length)) {
 throw new StringIndexOutOfBoundsException(index);
 }
 return value[index];
}
//返回String对象index位置上的元素的ASCII码
public int codePointAt(int index) {
 if ((index < 0) || (index >= value.length)) {
 throw new StringIndexOutOfBoundsException(index);
 }
 return Character.codePointAtImpl(value, index, value.length);
}
//返回String对象index位置上前一个元素的ASCII码
public int codePointBefore(int index) {
 int i = index - 1;
 if ((i < 0) || (i >= value.length)) {
 throw new StringIndexOutOfBoundsException(index);
 }
 return Character.codePointBeforeImpl(value, index, 0);
}
//返回字符数 非 Unicode 时和length没有区别 
//例如 String s = "/uD835/uDDA0";(即 'A' ) 
//此时 length()=2 ,codePointCount()= 1
public int codePointCount(int beginIndex, int endIndex) {
 if (beginIndex < 0 || endIndex > value.length || beginIndex > endIndex) {
 throw new IndexOutOfBoundsException();
 }
 return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
}
//相对unicode字符集 从index位置算起 偏移codePointOffset个位置,
//返回偏移后的位置,
//eg String s = "hello"; s.offsetByCodePoints(2,3)=5 
public int offsetByCodePoints(int index, int codePointOffset) {
 if (index < 0 || index > value.length) {
 throw new IndexOutOfBoundsException();
 }
 return Character.offsetByCodePointsImpl(value, 0, value.length,
 index, codePointOffset);
}

getChars


//dst 复制到那个数组
//dstBegin 从dst的dstBegin位置开始复制
//eg char c[] = new char[10];
// "abcdef".getChars(c,2);
//结果 c:空空abcdef空空
//此方法只能同包访问,不对外
void getChars(char dst[], int dstBegin) {
 System.arraycopy(value, 0, dst, dstBegin, value.length);
}
//和上面方法类似
//srcBegin 本字符串的开始位置
//srcEnd 本字符串的结束位置
public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
 if (srcBegin < 0) {
 throw new StringIndexOutOfBoundsException(srcBegin);
 }
 if (srcEnd > value.length) {
 throw new StringIndexOutOfBoundsException(srcEnd);
 }
 if (srcBegin > srcEnd) {
 throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
 }
 System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

getBytes


//按照字符集名称获取byte数组
public byte[] getBytes(String charsetName)
 throws UnsupportedEncodingException {
 if (charsetName == null) throw new NullPointerException();
 return StringCoding.encode(charsetName, value, 0, value.length);
}
//按照字符集类获取byte数组
public byte[] getBytes(Charset charset) {
 if (charset == null) throw new NullPointerException();
 return StringCoding.encode(charset, value, 0, value.length);
}
//按照当前平台默认字符集获取byte数组
public byte[] getBytes() {
 return StringCoding.encode(value, 0, value.length);
}

equals 比较类方法


//为重写Object类方法 故 参数没有设置为String类型的
public boolean equals(Object anObject) {
 if (this == anObject) { 
 return true; //比较引用 引用相同 则表示同一对象 
 }
 if (anObject instanceof String) { //判断是否为 String类型
 String anotherString = (String)anObject; //转换为String类型
 int n = value.length;
 if (n == anotherString.value.length) { //先判断字符串长度是否相等
 char v1[] = value;
 char v2[] = anotherString.value;
 int i = 0; //循环的游标
 while (n--!= 0) { //每次循环长度-1 直到为0
 if (v1[i] != v2[i]) //同位置一一比较
 return false; //发现不同返回false 循环结束
 i++;
 }
 return true; 
 }
 }
 return false;
}
//为比较StringBuffer提供
public boolean contentEquals(StringBuffer sb) {
 return contentEquals((CharSequence)sb);
}
//主要用于比较StringBuffer与StringBuilder String CharSequence
//String StringBuffer StringBuilder 都实现的CharSequence接口
public boolean contentEquals(CharSequence cs) {
 // Argument is a StringBuffer, StringBuilder
 if (cs instanceof AbstractStringBuilder) { 
 //AbstractStringBuilder 为 StringBuffer 及 StringBuilder的父类
 if (cs instanceof StringBuffer) { //如果属于StringBuffer 
 synchronized(cs) { //锁定比较对象 进入同步块 调用非同步比较方法
 return nonSyncContentEquals((AbstractStringBuilder)cs);
 }
 } else {
 //StringBuilder 直接调用非同步比较方法
 return nonSyncContentEquals((AbstractStringBuilder)cs);
 }
 }
 // Argument is a String
 if (cs instanceof String) { //如果是String类型调用equals
 return equals(cs);
 }
 // Argument is a generic CharSequence 
 //和equals类似 先比较长度 
 // 但由于CharSequence 为接口 当中并没有定义属性 
 //所以使用length方法及charAt方法获取长度及坐标字符
 char v1[] = value;
 int n = v1.length;
 if (n != cs.length()) {
 return false;
 }
 for (int i = 0; i < n; i++) {
 if (v1[i] != cs.charAt(i)) {
 return false;
 }
 }
 return true;
}
//和equals类似 不说明了 只是缺少一些判断
private boolean nonSyncContentEquals(AbstractStringBuilder sb) {
 char v1[] = value;
 char v2[] = sb.getValue();
 int n = v1.length;
 if (n != sb.length()) {
 return false;
 }
 for (int i = 0; i < n; i++) {
 if (v1[i] != v2[i]) {
 return false;
 }
 }
 return true;
}
//不区分大小写比较
public boolean equalsIgnoreCase(String anotherString) {
 //三目运算 
 return (this == anotherString) ? //true 判断引用
 : (anotherString != null) 
 && (anotherString.value.length == value.length) 判断长度
 && regionMatches(true, 0, anotherString, 0, value.length); 
 //调用 regionMatches 方法 进行比较
}
//该方法作用类似于equals方法 与之不同的是可以比较部分字符串
//toffset 当前字符串起始位置
//other 要比较的字符串
//ooffset 要比较字符串起始位置
//len 比较长度
public boolean regionMatches(int toffset, String other, int ooffset,
 int len) {
 char ta[] = value;
 int to = toffset;
 char pa[] = other.value;
 int po = ooffset;
 // Note: toffset, ooffset, or len might be near -1>>>1.
 // 对数据进行校验 
 if ((ooffset < 0) || (toffset < 0)
 || (toffset > (long)value.length - len)
 || (ooffset > (long)other.value.length - len)) {
 return false;
 }
 while (len-- > 0) {
 if (ta[to++] != pa[po++]) {
 return false;
 }
 }
 return true;
}
//和上面一个方法差不多 多了一个是否忽略大小写
//有些不理解为什么上面不直接设置false 然后调用此方法
//猜测可能是转换大小写比较耗时间吧(如果有知道的小伙伴可以私信或者留言联系我)
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;
 // Note: toffset, ooffset, or len might be near -1>>>1.
 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) {
 // If characters don't match but case may be ignored,
 // try converting both characters to uppercase.
 // If the results match, then the comparison scan should
 // continue.
 //如果字符不匹配但大小写可以忽略,
 //尝试将两个字符都转换成大写。
 //如果结果匹配,则继续进行比较扫描
 char u1 = Character.toUpperCase(c1);
 char u2 = Character.toUpperCase(c2);
 if (u1 == u2) {
 continue;
 }
 // Unfortunately, conversion to uppercase does not work properly
 // for the Georgian alphabet, which has strange rules about case
 // conversion. So we need to make one last check before
 // exiting.
 //不幸的是,转换成大写无法正常工作
 //对于格鲁吉亚字母,它有奇怪的大小写转换规则
 //所以我们需要在离开之前做最后一次检查
 if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
 continue;
 }
 }
 return false;
 }
 return true;
}

compareTo类方法

//因为String实现了Comparable接口,需要重写compareTo方法进行
//返回的int类型,正数为大,负数为小,是基于字符的ASSIC码比较的
//该方法是从高位到低位比较的,也可以简单的理解为安装首字母排序
public int compareTo(String anotherString) {
 int len1 = value.length;
 int len2 = anotherString.value.length;
 int lim = Math.min(len1, len2);//获得最小长度
 char v1[] = value;
 char v2[] = anotherString.value;
 int k = 0;
 while (k < lim) {
 //当前索引小于两个字符串中较短字符串的长度时,继续循环
 char c1 = v1[k];
 char c2 = v2[k];
 if (c1 != c2) {
 return c1 - c2;
 }
 k++;
 }
 //当前面字符串完全一致时 返回长度差
 return len1 - len2;
}
 //私有内部类,单例模式 
public static final Comparator<String> CASE_INSENSITIVE_ORDER
 = new CaseInsensitiveComparator();
//不区分大小写的比较
 //使用了恶汉单例模式 没有线程安全问题
private static class CaseInsensitiveComparator
 implements Comparator<String>, java.io.Serializable {
 // use serialVersionUID from JDK 1.2.2 for interoperability
 private static final long serialVersionUID = 8575799808933029326L;
 //和之前方法类似 比较时先比较大写然后比较小写
 public int compare(String s1, String s2) {
 int n1 = s1.length();
 int n2 = s2.length();
 int min = Math.min(n1, n2);
 for (int i = 0; i < min; i++) {
 char c1 = s1.charAt(i);
 char c2 = s2.charAt(i);
 if (c1 != c2) {
 c1 = Character.toUpperCase(c1);
 c2 = Character.toUpperCase(c2);
 if (c1 != c2) {
 c1 = Character.toLowerCase(c1);
 c2 = Character.toLowerCase(c2);
 if (c1 != c2) {
 // No overflow because of numeric promotion
 return c1 - c2;
 }
 }
 }
 }
 return n1 - n2;
 }
 /** Replaces the de-serialized object. */
 private Object readResolve() { 
 return CASE_INSENSITIVE_ORDER; 
 }
}
public int compareToIgnoreCase(String str) {
 return CASE_INSENSITIVE_ORDER.compare(this, str);
}

为什么String已经有一个compareTo方法了,还需要一个静态内部类再实现compare,首先两者的功能并不一样,compareTo 实现的仅仅是比较,而内部类实现的是忽略大小比较。这时我们会立刻想到方法的重载。 可是别忘了 compareTo 是从 Comparable 接口中重写的方法,排序比较时他只能识别compareTo (String str),所以我们只能使用Comparetor接口,使用时必须创建个其他类去实现Comparetor接口,并重写compare方法。所以出现了String当中的静态内部类,其实他就是一个比较器,而且使用了恶汉单例模式 没有线程安全问题,并且 compareToIgnoreCase 方法的实质也是调用的compare方法,使得代码得到了复用

startWith、endWith

//prefix 表示前缀 toffset 表示偏移l量 即从第几位开始
public boolean startsWith(String prefix, int toffset) {
 char ta[] = value; //获得当前对象的值
 int to = toffset; //获得需要判断的起始位置,偏移量
 char pa[] = prefix.value; //获得前缀字符串的值
 int po = 0;
 int pc = prefix.value.length;
 // Note: toffset might be near -1>>>1.
 if ((toffset < 0) || (toffset > value.length - pc)) { //偏移量不能小于0且能截取pc个长度
 return false; //不能则返回false
 }
 //从开始处逐个比较每一位置上的值
 while (--pc >= 0) { //循环pc次,既prefix的长度
 if (ta[to++] != pa[po++]) { //每次比较当前对象的字符串的字符是否跟prefix一样
 return false; //一样则pc--,to++,po++,有一个不同则返回false
 }
 }
 return true; //没有不一样则返回true,当前对象是以prefix在toffset位置做为开头
 }
public boolean startsWith(String prefix) {
 return startsWith(prefix, 0);
}
 public boolean endsWith(String suffix) {
 //suffix是需要判断是否为尾部的字符串。
 //倒数suffix.length 处查看是否以 suffix 字符串开始
 //value.length - suffix.value.length是suffix在当前对象的起始位置
 return startsWith(suffix, value.length - suffix.value.length); 
}

hashCode


public int hashCode() {
 int h = hash;
 if (h == 0 && value.length > 0) {
 char val[] = value;
 for (int i = 0; i < value.length; i++) {
 h = 31 * h + val[i];
 }
 hash = h;
 }
 return h;
}

为什么使用31而不选用其他数字呢 Effective Java 中是这样说的

之所以选择31,是因为它是个奇素数,如果乘数是偶数,并且乘法溢出的话,信息就会丢失,因为与2相乘等价于移位运算。使用素数的好处并不是很明显,但是习惯上都使用素数来计算散列结果。31有个很好的特性,就是用移位和减法来代替乘法,可以得到更好的性能:31*i==(i<<5)-i。现在的VM可以自动完成这种优化。在存储数据计算hash地址的时候,我们希望尽量减少有同样的hash地址,所谓“冲突”。当比较字符串是否相同时,会首先比较hashCode,如果相同再调用equals方法表具体内容,如果使用相同hash地址的数据过多,那么会增加调用equals方法次数,从而降低了查询效率!在hashMap中增加了“碰撞”的概率,使得map中某一条链表过长,会降低map的查询效率

indexOf

public int indexOf(int ch) {
 return indexOf(ch, 0);
}
//从 fromIndex 位置开始查找第一次出现 ch 的位置 
//存在返回目标位置,不存在返回-1
public int indexOf(int ch, int fromIndex) {
 //获取字符串长度 为什么使用final 
 //个人猜测 防止字符串引用改变 导致下次获取到的长度不同 因为一旦发生改变容易 出现数组下标异常
 //但是自己十分不自信 有懂的朋友麻烦私信告诉我
 final int max = value.length;
 //如果偏移量小于0,则代表偏移量为0,校正偏移量
 if (fromIndex < 0) {
 fromIndex = 0;
 } else if (fromIndex >= max) {
 // Note: fromIndex might be near -1>>>1.
 return -1;
 }
 //在Character类中 16进制数0x010000 为10进制中2的16次方即两个字节
 //但是因为int可以存放四个字节的数据 所以才有了下面的比较 过滤掉一些编码
 // public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x010000;
 if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
 //在这里处理大多数情况 (包括BPM 与 无效代码点)
 // handle most cases here (ch is a BMP code point or a
 // negative value (invalid code point))
 final char[] value = this.value;
 for (int i = fromIndex; i < max; i++) {
 if (value[i] == ch) {
 return i;
 }
 }
 return -1;
 } else {
 return indexOfSupplementary(ch, fromIndex);
 }
}
private int indexOfSupplementary(int ch, int fromIndex) {
 //确定指定的代码点是否是一个有效的Unicode代码点值
 if (Character.isValidCodePoint(ch)) {
 final char[] value = this.value;
 //获取字符的高位
 final char hi = Character.highSurrogate(ch);
 //获取字符的低位 简言之就是将 四个字节 拆开为两个两字节
 final char lo = Character.lowSurrogate(ch);
 final int max = value.length - 1;
 for (int i = fromIndex; i < max; i++) {
 if (value[i] == hi && value[i + 1] == lo) {
 return i;
 }
 }
 }
 return -1;
}
//方法逐级调用 都是返回要检测的字符位置
//默认都是将字符串转为 char[] 处理
public int indexOf(String str) {
 return indexOf(str, 0);
}
public int indexOf(String str, int fromIndex) {
 return indexOf(value, 0, value.length,
 str.value, 0, str.value.length, fromIndex);
}
//这是一个不对外公开的静态函数
//source就是原始字符串,sourceOffset就是原始字符串的偏移量,起始位置。
// sourceCount就是原始字符串的长度,target就是要查找的字符串。
// fromIndex就是从原始字符串的第fromIndex开始遍历
static int indexOf(char[] source, int sourceOffset, int sourceCount,
 String target, int fromIndex) {
 return indexOf(source, sourceOffset, sourceCount,
 target.value, 0, target.value.length,
 fromIndex);
}
//targetOffset 查找字符串开始w位置 和 targetCount 表示查找字符串长度
static int indexOf(char[] source, int sourceOffset, int sourceCount,
 char[] target, int targetOffset, int targetCount,
 int fromIndex) {
 if (fromIndex >= sourceCount) { //如果查找的起点大于当前对象的大小
 //如果目标字符串的长度为0,则代表目标字符串为"",""在任何字符串都会出现
 //配合fromIndex >= sourceCount,所以校正第一次出现在最尾部,仅仅是校正作用
 return (targetCount == 0 ? sourceCount : -1); 
 }
 if (fromIndex < 0) { //也是校正,如果起始点小于0,则返回0
 fromIndex = 0;
 }
 if (targetCount == 0) { //如果目标字符串长度为0,代表为"",则第一次出现在遍历起始点fromIndex
 return fromIndex;
 }
 char first = target[targetOffset]; //目标字符串的第一个字符
 int max = sourceOffset + (sourceCount - targetCount); //最大遍历次数
 for (int i = sourceOffset + fromIndex; i <= max; i++) {
 /* Look for first character. */
 //寻找目标字符串第一个字符的位置
 if (source[i] != first) {
 while (++i <= max && source[i] != first);
 }
 /* Found first character, now look at the rest of v2 */
 if (i <= max) {
 int j = i + 1; //原字符串的下一字符位置
 int end = j + targetCount - 1; //原字符结束位置
 //逐个比较目标字符串和次字符串
 //k 为目标字符串 要检索的位置 下一个位置
 for (int k = targetOffset + 1; j < end && source[j]
 == target[k]; j++, k++);
 //查找完整个字符串
 if (j == end) {
 /* Found whole string. */
 return i - sourceOffset;
 }
 }
 }
 return -1;
 }
//是否含有CharSequence这个子类元素,通常用于StrngBuffer,StringBuilder
public boolean contains(CharSequence s) {
 return indexOf(s.toString()) > -1;
}

lastIndexOf 与 indexOf类似 就不做详细讲解了

substring

// beginIndex 开始位置 endIndex 结束位置
// 本质是通过构造器实现的
// 每次使用后都会 new 新的String对象
publicString substring(int beginIndex) {
 if (beginIndex < 0) {
 throw new StringIndexOutOfBoundsException(beginIndex);
 }
 int subLen = value.length - beginIndex;
 if (subLen < 0) {
 throw new StringIndexOutOfBoundsException(subLen);
 }
 return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
public String substring(int beginIndex, int endIndex) {
 if (beginIndex < 0) {
 throw new StringIndexOutOfBoundsException(beginIndex);
 }
 if (endIndex > value.length) {
 throw new StringIndexOutOfBoundsException(endIndex);
 }
 int subLen = endIndex - beginIndex;
 if (subLen < 0) {
 throw new StringIndexOutOfBoundsException(subLen);
 }
 return ((beginIndex == 0) && (endIndex == value.length)) ? this
 : new String(value, beginIndex, subLen);
}

replace


//替换,将字符串中的oldChar字符全部替换成newChar
//从replace的算法中,我们可以发现,它不是从头开始遍历替换的,
//而是首先找到第一个要替换的字符,重新创建一个新的char[],
//一边复制原字符一边替换原字符串
//因为一开始为引用传递 直接修改会破坏String的不可变性
public String replace(char oldChar, char newChar) {
 if (oldChar != newChar) { //如果旧字符不等于新字符的情况下
 int len = value.length; //获得字符串长度
 int i = -1; //flag
 char[] val = value; /* avoid getfield opcode 避免getfield操作码*/
 // 此位置为引用传递 如果修改 val 原字符串也会修改
 while (++i < len) { //循环len次
 if (val[i] == oldChar) { //找到第一个旧字符,打断循环
 break;
 }
 }
 if (i < len) { //如果第一个旧字符的位置小于len
 char buf[] = new char[len]; // 新new一个字符数组,len个长度
 for (int j = 0; j < i; j++) {
 buf[j] = val[j]; // 把旧字符的前面的字符都复制到新字符数组上
 }
 while (i < len) { //从i位置开始遍历
 char c = val[i];
 buf[i] = (c == oldChar) ? newChar : c; //发生旧字符就替换,不想关的则直接复制
 i++;
 }
 return new String(buf, true); //通过新字符数组buf重构一个新String对象
 }
 }
 return this; //如果old = new ,直接返回自己
 }
//Pattern类和Matcher类 为Java正则表达式的处理 我没有了解过 不做说明了
//替换第一个旧字符
String replaceFirst(String regex, String replacement) {
 return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
 }
//当不是正规表达式时,与replace效果一样,都是全体换。如果字符串的正则表达式,则规矩表达式全体替换
public String replaceAll(String regex, String replacement) {
 return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
//可以用旧字符串去替换新字符串
public String replace(CharSequence target, CharSequence replacement) {
 return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
 this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
public boolean matches(String regex) {
 return Pattern.matches(regex, this); //实际使用的是Pattern.matches()方法
}

join

/**
 * join方法是JDK1.8加入的新函数,静态方法
 * 这个方法就是跟split有些对立的函数,不过join是静态方法
 * delimiter就是分割符,后面就是要追加的可变参数,比如str1,str2,str3
 * 
 * 例子:String.join(",",new String("a"),new String("b"),new String("c"))
 * output: "a,b,c"
 */ 
 public static String join(CharSequence delimiter, CharSequence... elements) {
 Objects.requireNonNull(delimiter); //就是检测是否为Null,是null,抛异常
 Objects.requireNonNull(elements); //不是就返回自己,即nothing happen
 // Number of elements not likely worth Arrays.stream overhead.
 StringJoiner joiner = new StringJoiner(delimiter); //嗯,有兴趣自己看StringJoiner类源码啦
 for (CharSequence cs: elements) {
 joiner.add(cs); //既用分割符delimiter将所有可变参数的字符串分割,合并成一个字符串
 }
 return joiner.toString();
 }
 
 /**
 * 功能是一样的,不过传入的参数不同
 * 这里第二个参数一般就是装着CharSequence子类的集合
 * 比如String.join(",",lists) 
 * list可以是一个Collection接口实现类,所含元素的基类必须是CharSequence类型
 * 比如String,StringBuilder,StringBuffer等
 */ 
 public static String join(CharSequence delimiter,
 Iterable<? extends CharSequence> elements) {
 Objects.requireNonNull(delimiter);
 Objects.requireNonNull(elements);
 StringJoiner joiner = new StringJoiner(delimiter);
 for (CharSequence cs: elements) {
 joiner.add(cs);
 }
 return joiner.toString();
 }

trim

/**
 * 去除字符串首尾部分的空值,如,' ' or " ",非""
 * 原理是通过substring去实现的,首尾各一个指针
 * 头指针发现空值就++,尾指针发现空值就--
 * ' '的Int值为32,其实不仅仅是去空的作用,应该是整数值小于等于32的去除掉
 */
publicString trim() {
 int len = value.length; //代表尾指针,实际是尾指针+1的大小
 int st = 0; //代表头指针
 char[] val = value; /* avoid getfield opcode */
 //st<len,且字符的整数值小于32则代表有空值,st++
 //去掉头部空格
 while ((st < len) && (val[st] <= ' ')) { 
 st++;
 }
 //len - 1才是真正的尾指针,如果尾部元素的整数值<=32,则代表有空值,len--
 //去掉尾部空格
 while ((st < len) && (val[len - 1] <= ' ')) {
 len--;
 }
 //截取st到len的字符串(不包括len位置)
 return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

toString


 //就是返回自己
 public String toString() {
 return this;
 }

toCharArray

 /**
 * 就是将String转换为字符数组并返回
 */
public char[] toCharArray() {
 // Cannot use Arrays.copyOf because of class initialization order issues
 //不能使用 Arrays.copyOf 因为类初始化顺序的问题
 char result[] = new char[value.length]; //定义一个要返回的空数组,长度为字符串长度
 System.arraycopy(value, 0, result, 0, value.length); //拷贝
 return result; //返回
}

toLowerCase()、toUpperCase

这两个函数真真的我没想到 我一开始以为是循环对字母范围进行判断 然后加减32 没想到很复杂 说实话有点没看懂 等有机会研究研究

valueOf 与 copyValueOf

https://zhidao.baidu.com/question/195140952.html 就直引用了

我觉得你最大的疑问应该在char数组上吧?比如

char[] test = new char[]{‘a’,‘b’,‘c’};

String a = String.valueOf(test);

String b = String.copyValueOf(test);

有什么区别?答案:没有任何区别!

首先你得知道,String的底层是由char[]实现的:通过一个char[]类型的value属性!早期的String构造器的实现呢,不会拷贝数组的,直接将参数的char[]数组作为String的value属性。然后 test[0] = ‘A’;

将导致字符串的变化。为了避免这个问题,提供了copyValueOf方法,每次都拷贝成新的字符数组来构造新的String对象。但是现在的String对象,在构造器中就通过拷贝新数组实现了,所以这两个方面在本质上已经没区别了。

请问String类的CopyValueOf 和ValueOf有什么不同吗?

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码