Understanding the Buffer class in Java
#1780New features in SDK Version 1.4.0
The recently released JavaTM 2 SDK, Standard Edition Version 1.4.0 contains a number of new features. I plan to publish articles explaining how to use some of those new features from time to time, and this is the first such article.
Among the new features is a new I/O API. Here is how Sun describes that API and the new features that it provides:
"The new I/O (NIO) APIs introduced in v 1.4 provide new features and improved performance in the areas of buffer management, scalable network and file I/O, character-set support, and regular-expression matching. The NIO APIs supplement the I/O facilities in the java.io package."Basic classes
The abstract Buffer class, and its subclasses, are basic to many of the new features in the NIO. One of those subclasses is named ByteBuffer. Since Buffer is abstract, you can only work with it in terms of its subclasses. In this article, I will use the ByteBuffer class to explore the features of the Buffer class.
You must understand how to use the Buffer class and its subclasses before you can understand how to use many of the other classes in the API. Therefore, the main purpose of this lesson is to help you understand how to use the features of the Buffer class. I will describe many of those features, and will illustrate the use of those features by explaining the code in a sample program.
You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth among the different listings and figures while you are reading about them.
I recommend that you also study the other lessons in my extensive collection of online Java tutorials. You will find those lessons published at Gamelan.com. However, as of the date of this writing, Gamelan doesn't maintain a consolidated index of my Java tutorial lessons, and sometimes they are difficult to locate there. You will find a consolidated index at Baldwin's Java Programming Tutorials.
The class named ByteBuffer extends the abstract class named Buffer. Because Buffer is abstract, it is not possible to create an instance of Buffer. Rather, the capabilities of Buffer become available when you create an instance of one of the subclasses of Buffer. The Sun documentation lists the following known subclasses of Buffer:
A container for primitive data
You may already be aware that none of the container classes in the Java Collections Framework are designed to contain primitive data. Rather, those containers are all designed to contain references to objects. If you want to store primitive data in one of those containers, you must first wrap the primitive value in an object.
Sun describes Buffer as "A container for data of a specific primitive type." However, as you will see in a subsequent lesson, an object of the ByteBuffer class can also be used as a container for storing a mixture of data of many different primitive types.
Three important properties
Sun tells us " ...the essential properties of a buffer are its capacity, limit, and position."
I will illustrate these three properties in the sample program later in this lesson. For now, here is a brief description of each of the three properties of a buffer:
- capacity: The number of elements the buffer contains; never negative and never changes.
- limit: The index of the first element that should not be read or written; never negative and never greater than the capacity.
- position: The next element to be read or written; never negative and never greater than the limit.
Subclasses of Buffer (such as ByteBuffer) use put and get operations to store data into a buffer and to retrieve data from the buffer (to transfer data into and out of the buffer). Each subclass defines two categories of put and get operations: relative and absolute.
Relative put and get operations
Relative data transfer operations store or retrieve one or more elements starting at the current position. The position is automatically incremented based on the number of items transferred and the type of data transferred. Transfer requests that exceed the limit cause exceptions to be thrown with no data being transferred.
Absolute put and get operations
Absolute data transfer operations take an element index as a parameter and use that index to store or retrieve data. These operations do not affect the value of the position property. Absolute put and get operations throw an exception if the index exceeds the limit.
The channel concept
Here is another important quotation from Sun. I show it here simply to introduce the concept of a channel, which will be the topic of a future lesson.
"Data may ... be transferred into or out of a buffer by the I/O operations of an appropriate channel, ..."One of the main reasons for discussing Buffer in this lesson is to prepare you to understand I/O channels, which I plan to discuss in a subsequent lesson
Mark and reset
The Buffer class also supports the concept of mark and reset. It is just about impossible to discuss one without the other. For example, according to Sun, here is a description of the behavior of the reset method:
"Resets this buffer's position to the previously-marked position."Similarly, here is Sun's description of a buffer's mark.
"A buffer's mark is the index to which its position will be reset when the reset method is invoked."