国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Java > 正文

java string的一些細(xì)節(jié)剖析

2019-11-26 16:18:50
字體:
供稿:網(wǎng)友
首先說明這里指的是Java中的String,雖然我已經(jīng)決定轉(zhuǎn)戰(zhàn)C/C++了,但是因?yàn)榻裉炫龅揭粋€(gè)問題,還是來看一下。String的定義如下:
復(fù)制代碼 代碼如下:

public final class String
{
private final char value[]; // 保存的字符串
private final int offset; // 開始的位置
private final int count; // 字符數(shù)目
private int hash; // 緩存的hash值
......
}

在Debug的時(shí)候可以看到保存的值如下:
 
需要說明一下的是:如果沒有調(diào)用過hashCode(),那么hash的值為0。容易知道這里的value也就是真正保存的字符串的值(也就是“字符串測(cè)試”)的char數(shù)組,而每個(gè)char的值是多少呢?很容易驗(yàn)證:Unicode。
到這里大家也就猜到我們常用的subString是怎么實(shí)現(xiàn)的了:如果是讓我們實(shí)現(xiàn)的話讓new String使用相同的value(char數(shù)組),只修改offset和count就可以了。這樣的話既省空間又快(不需要拷貝),而事實(shí)上也是這樣的:
復(fù)制代碼 代碼如下:

public String substring(int beginIndex) {
return substring(beginIndex, count);
}
public String substring(int beginIndex, int endIndex) {
......
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}

既然是在討論字符串,JVM默認(rèn)使用的是什么編碼呢?通過調(diào)試可以發(fā)現(xiàn):
復(fù)制代碼 代碼如下:

public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
java.security.PrivilegedAction pa = new GetPropertyAction("file.encoding");
String csn = (String)AccessController.doPrivileged(pa);
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}

其中defaultCharset的值可以通過:
  -Dfile.encoding=utf-8
進(jìn)行設(shè)置。當(dāng)然如果你想設(shè)置為“abc”也可以,但會(huì)默認(rèn)設(shè)置為UTF-8。可以通過System.getProperty("file.encoding")來看具體的值。看defaultCharset是為什么呢?因?yàn)榫W(wǎng)絡(luò)傳輸?shù)倪^程中應(yīng)該都是byte數(shù)組,不同的編碼方式得到的byte數(shù)組可能是不相同的。所以,我們得知道編碼方式是怎么得到的吧?具體得到byte數(shù)組的方法也就是我們下面重點(diǎn)要看的getBytes了,它最終要調(diào)用的是CharsetEncoder的encode方法,如下:
復(fù)制代碼 代碼如下:

public final CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput) {
int newState = endOfInput ? ST_END : ST_CODING;
if ((state != ST_RESET) && (state != ST_CODING) && !(endOfInput && (state == ST_END)))
throwIllegalStateException(state, newState);
state = newState;
for (;;) {
CoderResult cr;
try {
cr = encodeLoop(in, out);
} catch (BufferUnderflowException x) {
throw new CoderMalfunctionError(x);
} catch (BufferOverflowException x) {
throw new CoderMalfunctionError(x);
}
if (cr.isOverflow())
return cr;
if (cr.isUnderflow()) {
if (endOfInput && in.hasRemaining()) {
cr = CoderResult.malformedForLength(in.remaining());
} else {
return cr;
}
}
CodingErrorAction action = null;
if (cr.isMalformed())
action = malformedInputAction;
else if (cr.isUnmappable())
action = unmappableCharacterAction;
else
assert false : cr.toString();
if (action == CodingErrorAction.REPORT)
return cr;
if (action == CodingErrorAction.REPLACE) {
if (out.remaining() < replacement.length)
return CoderResult.OVERFLOW;
out.put(replacement);
}
if ((action == CodingErrorAction.IGNORE) || (action == CodingErrorAction.REPLACE)) {
in.position(in.position() + cr.length());
continue;
}
assert false;
}
}

當(dāng)然首先會(huì)根據(jù)需要的編碼格式選擇對(duì)應(yīng)的CharsetEncoder,而最主要的是不同的CharsetEncoder實(shí)現(xiàn)了不同的encodeLoop方法。這里可能會(huì)不明白為什么這里有個(gè)for(;;)?其實(shí)看CharsetEncoder所處的包(nio)和它的參數(shù)也就大概明白了:這個(gè)函數(shù)是可以處理流的(雖然我們這里使用的時(shí)候不會(huì)循環(huán))。
在encodeLoop方法中會(huì)將盡可能多的char轉(zhuǎn)換為byte,new String差不多就是上面的逆過程。
在實(shí)際的開發(fā)過程中經(jīng)常會(huì)遇到亂碼問題:
在上傳文件的時(shí)候取到文件名;
JS傳到后端的字符串;
首先先嘗試下下面代碼的的運(yùn)行結(jié)果:
復(fù)制代碼 代碼如下:

public static void main(String[] args) throws Exception {
String str = "字符串";
// -41 -42 -73 -5 -76 -82
printArray(str.getBytes());
// -27 -83 -105 -25 -84 -90 -28 -72 -78
printArray(str.getBytes("utf-8"));
// ???
System.out.println(new String(str.getBytes(), "utf-8"));
// 瀛 主站蜘蛛池模板: 日土县| 吉林省| 余庆县| 沧源| 襄樊市| 电白县| 柏乡县| 砚山县| 克什克腾旗| 许昌县| 和顺县| 厦门市| 长顺县| 水城县| 婺源县| 卫辉市| 醴陵市| 惠来县| 蕲春县| 忻州市| 黔西县| 黄平县| 石城县| 吐鲁番市| 修文县| 峨山| 乌兰浩特市| 涟水县| 宣恩县| 新津县| 梓潼县| 松潘县| 赤水市| 衡南县| 仙居县| 顺平县| 江油市| 井研县| 正蓝旗| 汝城县| 屯昌县|