2.4 字節(jié)緩沖區(qū)在本章節(jié)中,我們將進(jìn)一步觀察字節(jié)緩沖區(qū)。所有的基本數(shù)據(jù)類型都有相應(yīng)的緩沖區(qū)類(布爾型除外),但字節(jié)緩沖區(qū)有自己的獨(dú)特之處。字節(jié)是操作系統(tǒng)及其 I/O 設(shè)備使用的基本數(shù)據(jù)類型。當(dāng)在 JVM 和操作系統(tǒng)間傳遞數(shù)據(jù)時(shí),將其他的數(shù)據(jù)類型拆分成構(gòu)成它們的字節(jié)是十分必要的。如我們?cè)诤竺娴恼鹿?jié)中將要看到的那樣,系統(tǒng)層次的 I/O 面向字節(jié)的性質(zhì)可以在整個(gè)緩沖區(qū)的設(shè)計(jì)以及它們互相配合的服務(wù)中感受到。 為了提供參考,以下是ByteBuffer的完整 API。這些函數(shù)有些已經(jīng)在前面的章節(jié)中討論,并且僅僅是針對(duì)具體類型的版本。新的函數(shù)將在本節(jié)以及后面的章節(jié)中涉及。 - package java.nio;
- public abstract class ByteBuffer extends Buffer implements Comparable
- {
- public static ByteBuffer allocate (int capacity)
- public static ByteBuffer allocateDirect (int capacity)
- public abstract boolean isDirect();
- public static ByteBuffer wrap (byte[] array, int offset, int length)
- public static ByteBuffer wrap (byte[] array)
- public abstract ByteBuffer duplicate();
- public abstract ByteBuffer asReadOnlyBuffer();
- public abstract ByteBuffer slice();
- public final boolean hasArray()
- public final byte [] array()
- public final int arrayOffset()
- public abstract byte get();
- public abstract byte get (int index);
- public ByteBuffer get (byte[] dst, int offset, int length)
- public ByteBuffer get (byte[] dst, int offset, int length)
- public abstract ByteBuffer put (byte b);
- public abstract ByteBuffer put (int index, byte b);
- public ByteBuffer put (ByteBuffer src)
- public ByteBuffer put (byte[] src, int offset, int length)
- public final ByteBuffer put (byte[] src)
- public final ByteOrder order()
- public final ByteBuffer order (ByteOrder bo)
- public abstract CharBuffer asCharBuffer();
- public abstract ShortBuffer asShortBuffer();
- public abstract IntBuffer asIntBuffer();
- public abstract LongBuffer asLongBuffer();
- public abstract FloatBuffer asFloatBuffer();
- public abstract DoubleBuffer asDoubleBuffer();
- public abstract char getChar();
- public abstract char getChar(int index);
- public abstract ByteBuffer putChar (char value);
- public abstract ByteBuffer putChar (int index, char value);
- public abstract short getShort();
- public abstract short getShort (int index);
- public abstract ByteBuffer putShort (short value);
- public abstract ByteBuffer putShort (int index, short value);
- public abstract int getInt();
- public abstract int getInt (int index);
- public abstract ByteBuffer putInt (int value);
- public abstract ByteBuffer putInt (int index, int value);
- public abstract long getLong();
- public abstract long getLong (int index);
- public abstract ByteBuffer putLong (long value);
- public abstract ByteBuffer putLong (int index, long value);
- public abstract float getFloat();
- public abstract float getFloat (int index);
- public abstract ByteBuffer putFloat (float value);
- public abstract ByteBuffer putFloat (int index, float value);
- public abstract double getDouble();
- public abstract double getDouble (int index);
- public abstract ByteBuffer putDouble (double value);
- public abstract ByteBuffer putDouble (int index, double value);
- public abstract ByteBuffer compact();
- public boolean equals (Object ob)
- public int compareTo (Object ob)
- public String toString()
- public int hashCode()
- }
字節(jié)總是八位的,對(duì)嗎?
目前,字節(jié)幾乎被廣泛認(rèn)為是八個(gè)比特位。但這并非一直是實(shí)情。在過(guò)去的時(shí)代,每個(gè)字節(jié)可以是3到12之間任何個(gè)數(shù)或者更多個(gè)的比特位,最常見(jiàn)的是6到9位。八位的字節(jié)來(lái)自于市場(chǎng)力量和實(shí)踐的結(jié)合。它之所以實(shí)用是因?yàn)?位足以表達(dá)可用的字符集(至少是英文字符),8是2 的三次乘方(這簡(jiǎn)化了硬件設(shè)計(jì)),八恰好容納兩個(gè)十六進(jìn)制數(shù)字,而且8的倍數(shù)提供了足夠的組合位來(lái)存儲(chǔ)有效的數(shù)值。最初的市場(chǎng)推廣力量是IBM。在 1960 年首先推出的 IBM360 大型機(jī)使用的就是8位字節(jié)。 2.4.1 字節(jié)順序 非字節(jié)類型的基本類型,除了布爾型都是由組合在一起的幾個(gè)字節(jié)組成的。這些數(shù)據(jù)類型及其大小總結(jié)在表 2-1 中。 | 表 2-1.基本數(shù)據(jù)類型及其大小數(shù)據(jù)類型大小(以字節(jié)表示) |
|---|
| 數(shù)據(jù)類型 | 大小(以字節(jié)表示) | | Byte | 1 | | Char | 2 | | Short | 2 | | Int | 4 | | Long | 8 | | Float | 4 | | Double | 8 |
每個(gè)基本數(shù)據(jù)類型都是以連續(xù)字節(jié)序列的形式存儲(chǔ)在內(nèi)存中。例如,32位的int值0x037fb4c7(十進(jìn)制的58,700,999)可能會(huì)如圖 2-14 所顯示的那樣被塞入內(nèi)存字節(jié)中(內(nèi)存地址從左往右增加)。注意前一個(gè)句子中的「可能」一詞。盡管字節(jié)大小已經(jīng)被確定,但字節(jié)順序問(wèn)題一直沒(méi)有被廣泛認(rèn)同。表示一個(gè)整型值的字節(jié)可能在內(nèi)存中僅僅如圖 2-15 所示的那樣被簡(jiǎn)單地排列。 圖 2.14 大端字節(jié)順序
布爾型代表兩種值:true或false。一個(gè)字節(jié)可以包含256個(gè)唯一值,所以一個(gè)布爾值不能準(zhǔn)確地對(duì)應(yīng)到一個(gè)或多個(gè)字節(jié)上。字節(jié)是所有緩沖區(qū)的構(gòu)造塊。NIO 架構(gòu)決定了布爾緩沖區(qū)的執(zhí)行是有疑問(wèn)的,而且對(duì)這種緩沖區(qū)類型的需求不管怎么說(shuō)都是頗具爭(zhēng)議的。 圖 2.15 小端字節(jié)順序
多字節(jié)數(shù)值被存儲(chǔ)在內(nèi)存中的方式一般被稱為endian-ness(字節(jié)順序)。如果數(shù)字?jǐn)?shù)值的最高字節(jié)——big end(大端),位于低位地址,那么系統(tǒng)就是大端字節(jié)順序(如圖 2-14 所示)。如果最低字節(jié)最先保存在內(nèi)存中,那么小端字節(jié)順序(如圖 2-15 所示)。 字節(jié)順序很少由軟件設(shè)計(jì)者決定;它通常取決于硬件設(shè)計(jì)。字節(jié)順序的兩種類型有時(shí)被稱為字節(jié)性別,在當(dāng)今被廣泛使用。兩種方式都具有自身的優(yōu)勢(shì)。Intel 處理器使用小端字節(jié)順序涉及。摩托羅拉的CPU系列、SUN的Sparc工作站,以及PowerPC的CPU架構(gòu)都采用大端字節(jié)順序。 字節(jié)順序的問(wèn)題甚至勝過(guò)CPU硬件設(shè)計(jì)。當(dāng)Internet的設(shè)計(jì)者為互聯(lián)各種類型的計(jì)算機(jī)而設(shè)計(jì)網(wǎng)際協(xié)議(IP)時(shí),他們意識(shí)到了在具有不同內(nèi)部字節(jié)順序的系統(tǒng)間傳遞數(shù)值數(shù)據(jù)的問(wèn)題。因此,IP協(xié)議規(guī)定了使用大端的網(wǎng)絡(luò)字節(jié)順序概念。所有在IP分組報(bào)文的協(xié)議部分中使用的多字節(jié)數(shù)值必須先在本地主機(jī)字節(jié)順序和通用的網(wǎng)絡(luò)字節(jié)順序之間進(jìn)行轉(zhuǎn)換。 在java.nio中,字節(jié)順序由ByteOrder類封裝。 - package java.nio;
- public final class ByteOrder
- {
- public static final ByteOrder BIG_ENDIAN
- public static final ByteOrder LITTLE_ENDIAN
- public static ByteOrder nativeOrder( )
- public String toString( )
- }
ByteOrder類定義了決定從緩沖區(qū)中存儲(chǔ)或檢索多字節(jié)數(shù)值時(shí)使用哪一字節(jié)順序的常量。這個(gè)類的作用就像一個(gè)類型安全的枚舉。它定義了以其本身實(shí)例預(yù)初始化的兩個(gè)public區(qū)域。只有這兩個(gè)ByteOrder實(shí)例總是存在于 JVM 中,因此它們可以通過(guò)使用--操作符進(jìn)行比較。如果您需要知道JVM運(yùn)行的硬件平臺(tái)的固有字節(jié)順序,請(qǐng)調(diào)用靜態(tài)類函數(shù)nativeOrder()。它將返回兩個(gè)已確定常量中的一個(gè)。調(diào)用toString()將返回一個(gè)包含兩個(gè)文字字符串BIG_ENDIAN或者LITTLE_ENDIAN之一的String。
每個(gè)緩沖區(qū)類都具有一個(gè)能夠通過(guò)調(diào)用order()查詢的當(dāng)前字節(jié)順序設(shè)定。 - public abstract class CharBuffer extends Buffer implements Comparable, CharSequence
- {
- // 這里僅列出部分API
- public final ByteOrder order()
- }
因特網(wǎng)技術(shù)將字節(jié)成為八位位組(octet)。如側(cè)欄所介紹的,一個(gè)字節(jié)的大小是有歧義的。通過(guò)使用「octet」這一術(shù)語(yǔ),IP規(guī)則明確表明字節(jié)由八個(gè)位組成。 這個(gè)函數(shù)從ByteOrder返回兩個(gè)常量之一。對(duì)于除了ByteOrder之外的其他緩沖區(qū)類,字節(jié)順序是一個(gè)只讀屬性,并且可能根據(jù)緩沖區(qū)的建立方式而采用不同的值。除了ByteBuffer,其他通過(guò)分配或包裝一個(gè)數(shù)組所創(chuàng)建的緩沖區(qū)將從order()返回與ByteOrder.nativeOrder()相同的數(shù)值。這使因?yàn)榘诰彌_區(qū)中的元素在JVM中將會(huì)被作為基本數(shù)據(jù)直接存取。 ByteBuffer類有所不同:默認(rèn)字節(jié)順序總是ByteBuffer.BIG_ENDIAN,無(wú)論系統(tǒng)的固有字節(jié)順序是什么。Java的默認(rèn)字節(jié)順序是大端字節(jié)順序,這允許類文件等以及串行化的對(duì)象可以在任何JVM中工作。如果固有硬件字節(jié)順序是小端,這會(huì)有性能隱患。在使用固有硬件字節(jié)順序時(shí),將ByteBuffer的內(nèi)容當(dāng)作其他數(shù)據(jù)類型存取(很快就會(huì)討論到)很可能高效得多。
很可能您會(huì)對(duì)為什么ByteBuffer類需要一個(gè)字節(jié)順序設(shè)定這一問(wèn)題感到困惑。字節(jié)就是字節(jié),對(duì)嗎?當(dāng)然,但是如您不久將在 2.4.4 節(jié)所看到的那樣,ByteBuffer對(duì)象像其他基本數(shù)據(jù)類型一樣,具有大量便利的函數(shù)用于獲取和存放緩沖區(qū)內(nèi)容。這些函數(shù)對(duì)字節(jié)進(jìn)行編碼或解碼的方式取決于 ByteBuffer當(dāng)前字節(jié)順序的設(shè)定。ByteBuffer的字符順序設(shè)定可以隨時(shí)通過(guò)調(diào)用以ByteOrder.BIG_ENDIAN或ByteOrder.LITTL_ENDIAN為參數(shù)的order()函數(shù)來(lái)改變。
- public abstract class ByteBuffer extends Buffer implements Comparable
- {
- // 這里僅列出部分API
- public final ByteOrder order()
- public final ByteBuffer order (ByteOrder bo)
- }
如果一個(gè)緩沖區(qū)被創(chuàng)建為一個(gè)ByteBuffer對(duì)象的視圖(參見(jiàn) 2.4.3 節(jié)),那么order()返回的數(shù)值就是視圖被創(chuàng)建時(shí)其創(chuàng)建源頭的 ByteBuffer的字節(jié)順序設(shè)定。視圖的字節(jié)順序設(shè)定在創(chuàng)建后不能被改變,而且如果原始的字節(jié)緩沖區(qū)的字節(jié)順序在之后被改變,它也不會(huì)受到影響。 Java nio入門教程詳解(八)
0
0
我們認(rèn)為:用戶的主要目的,是為了獲取有用的信息,而不是來(lái)點(diǎn)擊廣告的。因此本站將竭力做好內(nèi)容,并將廣告和內(nèi)容進(jìn)行分離,確保所有廣告不會(huì)影響到用戶的正常閱讀體驗(yàn)。用戶僅憑個(gè)人意愿和興趣愛(ài)好點(diǎn)擊廣告。
我們堅(jiān)信:只有給用戶帶來(lái)價(jià)值,用戶才會(huì)給我們以回報(bào)。
|