String text = "this is a test text ";
上面这一句话实际上是执行了三件事
1、声明变量 String text;
2、在内存中开辟空间 (内存空间一)
3、将变量的text的引用指向开辟的内存空间
当有
text = "this is a change text";
测试实践一:
String text = "oo";
//循环体系将字符串拼接
for (int i = 0; i < 90000; i++) {
text+=i;
}
这段小程序在我的应用中执行了8s的时间 ,太长了,原因很简单,就是不断的在重复创建新的对象与内存空间,同时还要不时的释放未使用的内存空间
测试实践二:
String text = "oo";
//创建字符缓冲区
StringBuilder builder = new StringBuilder(text);
//循环体系将字符串拼接
for (int i = 0; i < 100000; i++) {
builder.append(i);
}执行这一小段代码,执行的次数远远超于实践一中,然而时间只使用了 30 ms,大优化了性能,原因只是因为其在只是开辟了一个缓存空间,每次只把新的数据添加到缓存中。
这种方法是创建了一个空的String,在内存空间中开辟了一个空内容的地址,实际上也没有什么用,源码中有这样的描述
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String() {
this.value = "".value;
}
/** The value is used for character storage. */
private final char value[];这种方法来创建String,与我们常用创建方式分析中的思路一至,声明变量,开辟空间,赋值引用
源码中这样操作
public String(String original) {
this.value = original.value;
this.hash = original.hash;
} /** Cache the hash code for the string */
private int hash; // Default to 0
char[] chars = new char[]{"q","e","e","q","e","e"};
//将char数组中的内容构造为String类型
String string = new String(chars);
//构造的字符串为 qeeqee public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
可以看到这里并没有直接通过 Arrays的copyOf创建了一个新的字符数组,并赋值 于this.value,public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
} char[] chars = new char[]{"q","e","e","q","e","e"};
//构造字符串
String string = new String(chars,0,2);
//构造的字符串为 qe
//也就是说将字符数组中的部分字符 构造成String
public String(char value[], int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= value.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
this.value = Arrays.copyOfRange(value, offset, offset+count);
}也就是说当我们通过这种方法来构造String 的时候 , 传入的参数中构造字符起始位置 offset小于零,那么将会出异常,构造字符个数 count 小于0,
那么意味取出的字符数组中的长度为0,也就是构造一个 ""字符串,同时赋值其字符数组,
当构造起始位置 字符个娄都不小于0的时候 ,当起始位置与取出的字符长度设置不合理(所谓不合理指的是 例 字符数组长度为 5,
构造字符串的时候传入的 起始位置 为3 ,构造长度为5,也就是说在字符数组中从3号位置取值,向后延取5个值,原字符数组长度必然不够)的时候,
抛出异常
public static char[] copyOfRange(char[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}int[] charIntArray = new int[]{67,68,69,70};
String string = new String (charIntArray,0,charIntArray.length);
//对应的字符串 CEDF public String(int[] codePoints, int offset, int count) {
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
if (offset <= codePoints.length) {
this.value = "".value;
return;
}
}
// Note: offset or count might be near -1>>>1.
if (offset > codePoints.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
final int end = offset + count;
// Pass 1: Compute precise size of char[]
int n = count;
for (int i = offset; i < end; i++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
continue;
else if (Character.isValidCodePoint(c))
n++;
else throw new IllegalArgumentException(Integer.toString(c));
}
// Pass 2: Allocate and fill in char[]
final char[] v = new char[n];
for (int i = offset, j = 0; i < end; i++, j++) {
int c = codePoints[i];
if (Character.isBmpCodePoint(c))
v[j] = (char)c;
else
Character.toSurrogates(c, v, j++);
}
this.value = v;
}byte[] newByte = new byte[]{4,5,6,34,43};
//构造字符
String string = new String (newByte,0,newByte,"UTF-8");
//参数一 对应的字节数组
//参数二 参数三 构造字符串的字节范围
//参数四 构造字符串的编码方式 这里使用的 为UTF - 8;public String(byte bytes[], int offset, int length, String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null)
throw new NullPointerException("charsetName");
checkBounds(bytes, offset, length);
this.value = StringCoding.decode(charsetName, bytes, offset, length);
}而下面的checkBounds方法只是做了一些安全性检验
private static void checkBounds(byte[] bytes, int offset, int length) {
if (length < 0)
throw new StringIndexOutOfBoundsException(length);
if (offset < 0)
throw new StringIndexOutOfBoundsException(offset);
if (offset > bytes.length - length)
throw new StringIndexOutOfBoundsException(offset + length);
} byte[] newByte = new byte[]{4,5,6,34,43};
//构造字符
String string = new String (newByte,"UTF-8");
String text = "thisisapicture";
//取出角标索引为0位置的字符
char cahrString = text . charAt(0);
//这里取出来的字符为 t public char charAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return value[index];
}则是从其对应的内存数组中拿到对应角标下的相应字符
3.2、 对字符串的分割
3.2.1、 split方法进行分割
String textString = "q,q,w,e,e,r,f,g3,g";
//将字符串以“,”为基准进行分割
String[] stringArray = textString.split(",");
//得到相应的字符串数组
// [q, q, w, e, e, r, f, g3, g]public String[] split(String regex) {
return split(regex, 0);
} 实际中调用了两个参数的重载方法public String[] split(String regex, int limit) {
/* fastpath if the regex is a
(1)one-char String and this character is not one of the
RegEx's meta characters ".$|()[{^?*+\\", or
(2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter.
*/
char ch = 0;
if (((regex.value.length == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
(regex.length() == 2 &&
regex.charAt(0) == '\\' &&
(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
boolean limited = limit > 0;
ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
list.add(substring(off, value.length));
off = value.length;
break;
}
}
// If no match was found, return this
if (off == 0)
return new String[]{this};
// Add remaining segment
if (!limited || list.size() < limit)
list.add(substring(off, value.length));
// Construct result
int resultSize = list.size();
if (limit == 0) {
while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
resultSize--;
}
}
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
return Pattern.compile(regex).split(this, limit);
}可以看到方法内有一个if,如果条件为true,那么就使用indexOf()打开循环体系,判断后substring()截取,
//第一步部分:当regex的长度为1且不是“.$|()[{^?*+\\”中的时,为真
(regex.value.length == 1 &&".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1)
//第二部分:当长度为2时且第一个字符为“\”转义字符,第二个字符不是字符0-9 a-z A-Z 以及utf-16之间的字符
从if可以看出如果regex内容为一个非正则匹配符或者是转以后的特殊字符时,采用indexOf()+substring()处理,
否则使用正则表达式 Pattern.compile(regex).split(this, limit)
也就是说,我们在使用Split方法对String字符串进行分割的时候,不仅可以以一个普通的字符为标准进行分割,
还可以使用一个正则表达式进行分割
而当使用的分割符号正好为正则表达式中的某些符号的时候,需要正则转义才能够得到正确的结果
String text = "ABCD";
//获取0号位置也就是'A'字符的编码
int uniCode = text.codePointAt(0);
从源码来看 :
public int codePointAt(int index) {
if ((index < 0) || (index >= value.length)) {
throw new StringIndexOutOfBoundsException(index);
}
return Character.codePointAtImpl(value, index, value.length);
}
也就是直接将String text对应的字符数组,以及要获取字符角标,以及字符数组长度传参
Unicode给世界上每个字符分配了一个编号,编号范围从0x000000到0x10FFFF。
编号范围在0x0000到0xFFFF之间的字符,为常用字符集,称BMP(Basic Multilingual Plane)字符。
编号范围在0x10000到0x10FFFF之间的字符叫做增补字符(supplementary character)。
Unicode主要规定了编号,但没有规定如果把编号映射为二进制,UTF-16是一种编码方式,或者叫映射方式,
它将编号映射为两个或四个字节,对BMP字符,它直接用两个字节表示,
对于增补字符,使用四个字节,前两个字节叫高代理项(high surrogate),范围从0xD800到0xDBFF,
后两个字节叫低代理项(low surrogate),范围从0xDC00到0xDFFF,UTF-16定义了一个公式,可以将编号与四字节表示进行相互转换。
Java内部采用UTF-16编码,char表示一个字符,但只能表示BMP中的字符,对于增补字符,需要使用两个char表示,一个表示高代理项,一个表示低代理项。
使用int可以表示任意一个Unicode字符,低21位表示Unicode编号,高11位设为0。整数编号在Unicode中一般称为代码点(Code Point),表示一个Unicode字符,与之相对,还有一个词代码单元(Code Unit)表示一个char。
而在Character这个类中,对应的静态操作方法实则为:
static int codePointAtImpl(char[] a, int index, int limit) {
char c1 = a[index];
if (isHighSurrogate(c1) && ++index < limit) {
char c2 = a[index];
if (isLowSurrogate(c2)) {
return toCodePoint(c1, c2);
}
}
return c1;
} 实际 在这个方法中的第一步是从text对应的字符数组中取出对应的角标的字符,如果不符合其中if的条件,那么将直接获取的是字符本身,
也就是字符本身的unicode编码是本身
在if的判断条件中.执行判断取出的字符是否在isHighSurrogate这个方法所限定的范围内,
public static boolean isHighSurrogate(char ch) {
// Help VM constant-fold; MAX_HIGH_SURROGATE + 1 == MIN_LOW_SURROGATE
return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1);
} MIN_HIGH_SURROGATE utf-16 编码中的 unicode 高代理项代码单元的最小值。高代理项也称为前导代理项。
如果在,则执行 isLowSurrogate方法的限定判断
public static boolean isLowSurrogate(char ch) {
return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1);
}public static int toCodePoint(char high, char low) {
// Optimized form of:
// return ((high - MIN_HIGH_SURROGATE) << 10)
// + (low - MIN_LOW_SURROGATE)
// + MIN_SUPPLEMENTARY_CODE_POINT;
return ((high << 10) + low) + (MIN_SUPPLEMENTARY_CODE_POINT
- (MIN_HIGH_SURROGATE << 10)
- MIN_LOW_SURROGATE);
}
String textString = "ABCDEF";
//这里是获取三号位置前面一位,也就是二号位 C 的uniCode编码
int uniCode = textString.codePointBefore(3); 从源码来看:实际实操作的还是字符串对应的字符数组,操作方法依然是Character这个类所定义的静态方法
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);
}然后判定是否在编码区中的 高 低代理区,如果 在,那么就计算返回对应的编码
static int codePointBeforeImpl(char[] a, int index, int start) {
char c2 = a[--index];
if (isLowSurrogate(c2) && index > start) {
char c1 = a[--index];
if (isHighSurrogate(c1)) {
return toCodePoint(c1, c2);
}
}
return c2;
}
String textString = "ABCDEF";
//这里获取的是整个字符串所对应的 代码点数
int uniCodeCount = textString.codePointCount(0, textString.length()); 从源码角度来看 实际还是在操作String对应的字符数组,负责操作的是 Character这个类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);
} 这里直接传入字符串对应的字符数组,以及范围的开始点,范围长度 static int codePointCountImpl(char[] a, int offset, int count) {
int endIndex = offset + count;
int n = count;
for (int i = offset; i < endIndex; ) {
if (isHighSurrogate(a[i++]) && i < endIndex &&
isLowSurrogate(a[i])) {
n--;
i++;
}
}
return n;
} 可以看出来 在这里面也是一个循环判断每一个字符是否在高代理项区与低代理项区,然后进行计数 String text1 = "ABCDEF";
String text2 = "ABCDEFG";
//比较
int compareNumber = text1.compareTo(text2); 其实就是依次比较两个字符串ASC码。如果两个字符的ASC码相等则继续后续比较,否则直接返回两个ASC的差值。如果两个字符串完全一样,则返回0从源码角度来看:
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;
}String text1 = "ABCDEF";
String text2 = "ABCDEFG";
//比较
int compareNumber = text1.compareToIgnoreCase(text2);
public int compareToIgnoreCase(String str) {
return CASE_INSENSITIVE_ORDER.compare(this, str);
}而CASE_INSENSITIVE_ORDER是String类中定义的一个比较器
(1.2版本开始使用)
public static final Comparator<String> CASE_INSENSITIVE_ORDER
String text1 = "ABCDEF";
String text2 = "ABCDEFG";
//这里将 text2 拼接到text1后面
String newString = text1.concat(text2);
将两个字符串拼接到一起,可以使用 text1+text2这个方法,只不过是在性能上有一点点的不合适
从源码角度来看
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
} public static char[] copyOf(char[] original, int newLength) {
char[] copy = new char[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
//这里创建一个新长度的数组空间并将原来的字符数组COPY进去
String text = "ABCD ";
//查找 "A" 在字符串text中第一次出现的位置
int index = text.indexOf("A"); public int indexOf(String str) {
return indexOf(str, 0);
}
//再看indexOf(String str, int fromIndex)方法
public int indexOf(String str, int fromIndex) {
return indexOf(value, 0, value.length,
str.value, 0, str.value.length, fromIndex);
}上述indexfOf(String str)方法中调用indexOf(String str,int fromIndex)方法,然后传入0,也就是说将从String的开始位置查找指定字符在字符串中出现的位置,
而在indexOf(String str,int fromIndex)这个方法中则调用了indexOf的多参数方法,这时分别传入
value 父字符串的字符数组
0 父字符串的有效字符起始角标索引 这里传入0,也就是整个父字符串都可作为操作对象
value.length 父字符串的字符数组长度
str.value 子字符串的字符数组
0 子字符串的有效字符起始角标索引
str.value.length 子字符串的字符数组长度
fromIndex 在父字符串的查找的开始位置
再看多参数方法
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
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;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}在这个方法中,参数最多,那么说明处理的方法就在这里面
先分析参数
char[] source, 父String 对应字符数组
int sourceOffset, 父String 被使用起始索引
int sourceCount, 父String 对应字符数组长度
char[] target, 子String 对应字符数组
int targetOffset, 子String 被使用超始索引
int targetCount, 子String 对应字符数组长度
int fromIndex 检索起始位置
从上到下
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
如果查找子String标识的在父View中的起始位置 大于等于 父String的长度
则终止操作,返回0 或者 -1
当子字符串的长度为0的时候,则返加0,此时子字符串为”“ 内容为空的空字符串
当子字符串的长度不为0的时候,返回-1,也就是说没有查找到
if (fromIndex < 0) {
fromIndex = 0;
}
当检索起始位置小于0,将起始位置默认设为0
if (targetCount == 0) {
return fromIndex;
}
当检索的子String对应的字符数组长度为0时,返回传入的检索位置
char first = target[targetOffset];
取出检索子String的第一个字符
int max = sourceOffset + (sourceCount - targetCount);
父String被检索起始位 + (父String对应字符数组长度 - 子String对应字符数组长度)
for (int i = sourceOffset + fromIndex; i <= max; i++) {
。。。。
}
如果循环体系中的条件没有被满足,那说明没有查找到对应的字符,返回-1
在循环体系中
/* 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;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
String text = "ABCE";
//判断text中是否包含 "A"
boolean isContans = text.contains("A");
public boolean contains(CharSequence s) {
return indexOf(s.toString()) > -1;
} String text1 = "ABCDEF";
//比较序列
boolean isExit = text1.contentEquals("AABCDEF"); public boolean contentEquals(StringBuffer sb) {
return contentEquals((CharSequence)sb);
}
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;
}
这里两个方法重载,传类型不一样,CharSequence类型和StringBuffer类型
而实际操作起作用的是contentEquals(CharSequence cs)方法
而在这个方法中
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} 可以看出来,当我们传入的参数 cs 是AbstractStringBuilder的实例的时候 执行if内部的方法并且 如果是StringBuffer的实例,加同步锁,
而在方法nonSyncContentEquals中
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;
}这个方法中吧,感觉到无语,首先先获取参数的对应字符数组的长度,然后比较字符数组的长度,如果长度不相同,那么直接返回false,也就是这两个字符串的序列号肯定不一样,
如果长度一样,再一循环比较每一个字符
如果不满足if中的判断语句后,在向下执行,
// Argument is a String
if (cs instanceof String) {
return equals(cs);
} 如果传参是String的实例的时候
则调用了String的equals方法进行比较
如果不满足上面的条件,再向下执行
// 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;
}
}
String string = "4444";
char[] charTest = new char[]{'d','r','w','q'};
String newString = string.copyValueOf(charTest);
构建结果尽然是: drwq
不忍心看源码,但是还得看下,一看,更是无语
/**
* Equivalent to {@link #valueOf(char[])}.
*
* @param data the character array.
* @return a {@code String} that contains the characters of the
* character array.
*/
public static String copyValueOf(char data[]) {
return new String(data);
} String string = "andThisIs4";
//判断是否以a开头
boolean flag = string.startsWith("a");
//输出结果为 true
public boolean startsWith(String prefix) {
return startsWith(prefix, 0);
}
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)) {
return false;
}
while (--pc >= 0) {
if (ta[to++] != pa[po++]) {
return false;
}
}
return true;
}
String string = "andrThisIs4";
//判断是否是以 4 结尾
boolean flag = string.endsWith("4");
//结果 为true从源码角度来看
public boolean endsWith(String suffix) {
return startsWith(suffix, value.length - suffix.value.length);
}(2016-9-23 8:33 更新)
String text1 = "ABCD";
String text2 = "ABCE";
//比较两个字符串是否相等
boolean flage = text1.equals(text2);text1 text2 分别指向两个堆内存空间
当使用 text1 == text2 来判断时,比较的是text1 与 text2这两个变量 对应的引用地址是否相等,也就是说其指向的内存地址是否一样
从源码角度来看 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;
}
(2016-9-27 14:33 更新)
String text1 = "ABCDEF";
//获取默认编码下的字节数组
byte[] bytes = text1.getBytes();
从源码角度来看:
public byte[] getBytes() {
return StringCoding.encode(value, 0, value.length);
} 这里间接使用了StringCoding类的静态方法 encode方法
static byte[] encode(char[] ca, int off, int len) {
String csn = Charset.defaultCharset().name();
try {
// use charset name encode() variant which provides caching.
return encode(csn, ca, off, len);
} catch (UnsupportedEncodingException x) {
warnUnsupportedCharset(csn);
}
try {
return encode("ISO-8859-1", ca, off, len);
} catch (UnsupportedEncodingException x) {
// If this code is hit during VM initialization, MessageUtils is
// the only way we will be able to get any kind of error message.
MessageUtils.err("ISO-8859-1 charset not available: "
+ x.toString());
// If we can not find ISO-8859-1 (a required encoding) then things
// are seriously wrong with the installation.
System.exit(1);
return null;
}
} String text1 = "abef";
byte[] bytes = null;
try {
bytes = text1.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
可见这个方法是获取默认编码格式下的字节数组方法的重载方法 public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
if (charsetName == null) throw new NullPointerException();
return StringCoding.encode(charsetName, value, 0, value.length);
} 可以看到这里直接调用的是 StringCoding 的四个参数的重载方法(getBytes()方法调用的是三个参数的encode方法) String text1 ="ABCDEF";
//目标字符数组
char[] chars = new char[10];
//拷贝
text1.getChars(0,text1.length(),chars,0);
//参数一 参数二 拷贝String中字符的范围
//参数三 目标字符数组
//参数四 目标字符数组中的存储起始位置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);
}其直接调用 System 的拷贝数组的方法将数据拷贝
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);对于System的arraycopy方法来说,其直接调用 JNI层方法实现
原文:http://blog.csdn.net/zl18603543572/article/details/52614585