java源码解析之String类
Posted GolLong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java源码解析之String类相关的知识,希望对你有一定的参考价值。
上一节主要介绍了String类的一些构造方法,主要分为四类
- 无参构造器:String(),创建一个空字符串"",区别于null字符串,""已经初始化,null并未初始化
- 副本构造器:String(String s),简单的赋值,得到的是一个副本,俩个引用指向的是常量池中的同一个String,但是String是不可变的,所有用意不大
- byte类构造器:String(byte[] b),将byte数组转换为String,注意并不是简单的赋值,而是整体copy一份
- char类构造器:String(char[] c),将char数组转换成String,注意并不是简单的赋值,而是整体copy一份
- codepoints构构器:String(int[] i),将超过char表示范围的字符转换为为String
- String缓存流的转换:String(StringBuffer),将字符换缓冲流转换为String
/* * 获得字符串的长度,也就是属性value数组的长度 */ public int length() { return value.length; } /* * 判断字符串是否为空,也就是判断属性value数组的长度是否等于0 */ public boolean isEmpty() { return value.length == 0; } /* * charAt方法可以直接获取当前下标对应的字符,这对于判断某个位置的字符值很方便 * 区别于 */ public char charAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return value[index]; } /* * 返回指定索引处的字符(Unicode代码点)。 codePoint在上一章已经介绍过了,具体就是那些超出byte和char表示方位的字符 */ public int codePointAt(int index) { if ((index < 0) || (index >= value.length)) { throw new StringIndexOutOfBoundsException(index); } return Character.codePointAtImpl(value, index, value.length); } /* * 返回指定索引之前的字符(Unicode代码点)。 */ 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); } /* * 返回此 String指定文本范围内的Unicode代码点数。 */ 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); } /* * 返回此String中的索引,该索引通过codePointOffset代码点从给定的index偏移。 * index和codePointOffset给出的文本范围内的未配对代理计为每个代码点。 * */ 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); } /* * 将此字符串复制给dst字节数组,默认为整体复制,其中dstBegin为目标数组dst中的开始位置 * 此方法为包访问权限,所以我们并没有调用的权限 */ void getChars(char dst[], int dstBegin) { System.arraycopy(value, 0, dst, dstBegin, value.length); } /* * 将此字符串的额指定位置开始到指定位置结束复制给dst字节数组,其中dstBegin为目标数组dst的开始位置, * 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); } /* * 方法已过时 * 使用平台的默认字符集将此 String编码为字节序列,将结果存储到新的字节数组中,可以指定字符串的开始位置和结束位置, * 但结果往往是不正确的,在源码中我们可以看到,仅仅是将字符串的每一位字符强转成字节类型,实际用处很少。 * */ @Deprecated public void getBytes(int srcBegin, int srcEnd, byte 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); } Objects.requireNonNull(dst); int j = dstBegin; int n = srcEnd; int i = srcBegin; char[] val = value; /* avoid getfield opcode */ while (i < n) { dst[j++] = (byte) val[i++]; } } /* * 指定编码字符集将此 String编码为字节序列,将结果存储到新的字节数组中 */ public byte[] getBytes(String charsetName) throws UnsupportedEncodingException { if (charsetName == null) throw new NullPointerException(); return StringCoding.encode(charsetName, value, 0, value.length); } /* * 指定编码字符集将此 String编码为字节序列,将结果存储到新的字节数组中 */ public byte[] getBytes(Charset charset) { if (charset == null) throw new NullPointerException(); return StringCoding.encode(charset, value, 0, value.length); } /* * 使用平台的默认字符集将此 String编码为字节序列,将结果存储到新的字节数组中 */ public byte[] getBytes() { return StringCoding.encode(value, 0, value.length); } /* * String重写Object类的equals方法,详细阅读源码,我们发现形参是Object类型,那么在实际传参的过程当中 * 除了String类型,别的引用类型都会返回false,重点注意的是StringBuffer和StringBuild,在实际比较的时候一定要先进行转换 * equals实际比较的就是字符串的每一位依次进行比较,直到全部比较完毕都没有不一样的才返回true */ 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; } /* * 将此字符串与指定的StringBuffer进行 比较内容是否相等 */ public boolean contentEquals(StringBuffer sb) { return contentEquals((CharSequence) sb); } 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; } /* * 将此字符串与指定的CharSequence进行内容比较是否相等 */ public boolean contentEquals(CharSequence cs) { // Argument is a StringBuffer, StringBuilder if (cs instanceof AbstractStringBuilder) { if (cs instanceof StringBuffer) { synchronized (cs) { return nonSyncContentEquals((AbstractStringBuilder) cs); } } else { return nonSyncContentEquals((AbstractStringBuilder) cs); } } // Argument is a String if (cs instanceof String) { return equals(cs); } // Argument is a generic CharSequence 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; } /* * 能用一行代价解决的事就不用俩行,三元运算符?:直接解决。其中regionMatches(true, 0, anotherString, 0, value.length)是测试是否相等的函数 * 第一个参数true代表忽略大小写 */ public boolean equalsIgnoreCase(String anotherString) { return (this == anotherString) ? true : (anotherString != null) && (anotherString.value.length == value.length) && regionMatches(true, 0, anotherString, 0, value.length); }
以上是关于java源码解析之String类的主要内容,如果未能解决你的问题,请参考以下文章