Advanced Java Services | Die nio.Buffer Hierarchie |
Die in Java 1.4 eingeführten und in Java 1.7 ergänzten Channels arbeiten mit den ebenfalls in 1.4 eingeführten Buffers
zusammen. Channels sind Verallgemeinerungen der Reader- und Writerklassen ebenso wie der Streamklassen. Channels lesen oder
schreiben Daten von einem Medium. Für den Programmierer erfolgt der Zugriff auf diese Daten über Buffers.
Die Channels schreiben gelesene Daten in einen Buffer und umgekehrt lesen Sie den Inhalt von Buffers aus um Daten zu schreiben.
Die Buffers werden vom Entwickler erzeugt und gelesen oder gefüllt.
Buffer ist eine abstrakte Klasse die folgende Realisierungen hat: ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer,
IntBuffer, LongBuffer, ShortBuffer und MappedByteBuffer, siehe die obige Graphik. MappedByteBuffer wird hier nicht behandelt.
Alle Realisierungen der abstrakten Klasse Buffer die sich auf einen primitiven Datentyp beziehen verwenden im
Hintergrund ein Array des entsprechenden primitiven Datentyps um die Daten zu speichern. Der Zugriff auf dieses Array wird
jedoch über die Methoden gesteuert, die die abstrakte Klasse Buffer zur Verfügung stellt und die die Realisierungen ergänzen.
Die folgende Tabelle listet die Methoden der Klasse Buffer auf.
Modifier and Type | Method and Description |
---|---|
abstract Object | array()
Returns the array that backs this buffer (optional operation). |
abstract int | arrayOffset()
Returns the offset within this buffer's backing array of the first element of the buffer (optional operation). |
int | capacity()
Returns this buffer's capacity. |
Buffer | clear()
Clears this buffer. |
Buffer | flip()
Flips this buffer. |
abstract boolean | hasArray()
Tells whether or not this buffer is backed by an accessible array. |
boolean | hasRemaining()
Tells whether there are any elements between the current position and the limit. |
abstract boolean | isDirect()
Tells whether or not this buffer is direct. |
abstract boolean | isReadOnly()
Tells whether or not this buffer is read-only. |
int | limit()
Returns this buffer's limit. |
Buffer | limit(int newLimit)
Sets this buffer's limit. |
Buffer | mark()
Sets this buffer's mark at its position. |
int | position()
Returns this buffer's position. |
Buffer | position(int newPosition)
Sets this buffer's position. |
int | remaining()
Returns the number of elements between the current position and the limit. |
Buffer | reset()
Resets this buffer's position to the previously-marked position. |
Buffer | rewind()
Rewinds this buffer. |
Die Kapazität (capacity) ist die bei der Instantiierung eines konkreten Buffers festgelegte Größe, also die Anzahl der Elemente, die der Buffer aufnehmen kann. Diese ist fest.
Der Zugriff auf einen Buffer erfolgt wie bei einem Array über einen Index. Es gibt verschiedene Arten von Indices. Die Position (position) ist der Index, an dem das nächste Element gelesen oder geschrieben werden kann. Die Anfangsposition ist 0. Die Position kann sich durch Lese- oder Schreibvorgänge automatisch ändern. Die Position kann aber auch von Hand gesetzt und gelesen werden. Es gilt die Ungleichung
0 <= position <= capacity
Das Limit ist der Index des ersten Elements ab dem keine Lese- oder Schreiboperationen stattfinden sollen. Das Limit ist zu Beginn gleich der Kapazität und wird dann nicht mehr automatisch gesetzt. Das Limit kann mit Methoden gelesen oder gesetzt werden. Aus der Definition des Limits folgt die Ungleichung:
0 <= position <= limit <= capacity
Zusätzlich ist es möglich eine Markierung zu setzen. Eine Markierung ist zu Anfang nicht gesetzt. Eine Markierung kann nach einer Positionierung gesetzt werden und markiert dann diese Position. Eine unbeabsichtige Löschung einer Markierung kann zu einer InvalidMarkException führen. Es gilt die erweiterte Ungleichung:
0 <= mark <= position <= limit <= capacity
clear() setzt die Position auf 0, das Limit auf capacity und die Markierung wird gelöscht. Daten werden nicht gelöscht.
rewind() setzt die Position auf 0, das Limit bleibt unverändert und die Markierung wird gelöscht. Daten werden nicht gelöscht.
reset() versucht die Position auf die Markierung zu zurückzusetzen! Gibt es keine Markierung so wird eine InvalidMarkException geworfen. Daten werden nicht gelöscht.
clear(), rewind() löschen die Markierung. Eine Positionierung vor den Wert der Markierung löscht ebenfalls die Markierung.
Es gibt keine Methode zum Löschen der Daten. Daten können aber durch Positionierung überschrieben werden. Für Buffers, die intern mit einem Array arbeiten (und das sind alle Implementierungen der primitiven Datentypen) gibt es jedoch eine Möglichkeit. Man holt sich mit der Methode array() das interne Array und setzt dann die Methode fill() der Utilityklasse Arrays ein. Für einen ByteBuffer sieht das so aus:
ByteBuffer buffer = ByteBuffer.allocate(256); // ... Buffer enthält Daten Arrays.fill(buffer.array(), (byte)0); // Inhalt mit 0 überschrieben
Die sich von Buffer direkt ableitenden Klassen sind zwar selbst wieder abstrakt, implementieren aber die Methoden aus Buffer. Es gibt für jeden primitiven Datentyp (außer boolean) eine entsprechende Bufferklasse. Alle diese Klassen verfügen über die statischen Methoden allocate() und wrap() mit denen man Bufferobjekte ins Leben rufen kann. Im folgenden werden zwei Bufferobjekte angelegt, ein Doublebuffer mit einem internen Array der Größe 256 und ein ByteBuffer mit Hilfe eines externen Arrays.
DoubleBuffer buffer = DoubleBuffer.allocate(256);
byte[] arr = new byte[128]; ByteBuffer buffer = ByteBuffer.wrap(arr);
Die zu den primitiven datentypen gehörenden Bufferklassen haben die Mehrzahl ihrer Methoden in dem Sinne gemein, daß sie sich nur im primitiven Datentyp unterscheiden. Diese Methoden sind hier zusammengestellt. Xxx steht dabei für Byte bzw. Char bzw. Double bzw. Float bzw. Int bzw. Long bzw. Short.
Modifier and Type | Method and Description |
---|---|
static XxxBuffer | allocate(int capacity)
Allocates a new xxx buffer. |
abstract XxxBuffer | asReadOnlyBuffer()
Creates a new, read-only xxx buffer that shares this buffer's content. |
abstract XxxBuffer | compact()
Compacts this buffer (optional operation). |
int | compareTo(XxxBuffer that)
Compares this buffer to another. |
abstract XxxBuffer | duplicate()
Creates a new xxx buffer that shares this buffer's content. |
boolean | equals(Object ob)
Tells whether or not this buffer is equal to another object. |
abstract xxx | get()
Relative get method. |
XxxBuffer | get(xxx[] dst)
Relative bulk get method. |
XxxBuffer | get(xxx[] dst,
int offset,
int length)
Relative bulk get method. |
abstract xxx | get(int index)
Absolute get method. |
int | hashCode()
Returns the current hash code of this buffer. |
abstract ByteOrder | order()
Retrieves this buffer's byte order. |
abstract XxxBuffer | put(xxx d)
Relative put method (optional operation). |
XxxBuffer | put(xxx[] src)
Relative bulk put method (optional operation). |
XxxBuffer | put(xxx[] src,
int offset,
int length)
Relative bulk put method (optional operation). |
XxxBuffer | put(XxxBuffer src)
Relative bulk put method (optional operation). |
abstract XxxBuffer | put(int index,
xxx d)
Absolute put method (optional operation). |
abstract XxxBuffer | slice()
Creates a new xxx buffer whose content is a shared subsequence of this buffer's content. |
String | toString()
für CharBuffer: Returns a string containing the characters in this buffer. für alle anderen Bufferklassen: Returns a string summarizing the state of this buffer. |
static XxxBuffer | wrap(xxx[] array)
Wraps a xxx array into a buffer. |
static XxxBuffer | wrap(xxx[] array,
int offset,
int length)
Wraps a xxx array into a buffer. |