Routinely, a select statement returns a 2-D matrix of strings. JDBC's ResultSet class "flattens" the 2-D matrix into a 1-D array. In order to process the results as rows, the programmer must know at compile-time how many columns are in the table, or, must use the ResultSetMetaData class at run-time to request the number of columns. This latter option is demonstrated in lines 26 and 27.
Once the number of columns has been divined, it is a matter of using an inner loop to process the columns of a row (lines 32 and 33), and an outer loop to process the rows (lines 31-35). getString() is the most general way of retrieving each "cell" value, but if the type of a column is known, then calls like getBoolean() and getInt() can be useful.
The ResultSetMetaData class is capable of providing all manner of useful information. Lines 28 and 29 are outputting the column labels displayed at lines 41, 46, and 51.
Notice how this retrieval mechanism is capable of handling a matrix (lines 42-44), a column (lines 47-49), and a scalar (line 52).
The printResultsTable() method in the example that follows does the same thing as the outputResults() method here, but with a bit more panache. This is the method that was used (but not defined) in the previous example. In addition to the getColumnCount() and getColumnLabel() methods called here, it also leverages the ResultSetMetaData class's getColumnDisplaySize() method.