You need to pass
a number like an
int
into a routine, and get back the
routine’s updated version of that value in addition to the
routine’s return value.
This often comes up in working
through strings; the routine may need to return a
boolean
, say, or the number of characters
transferred, but also needs to increment an integer array or string
index in the calling class.
It is also useful in constructors, which can’t return a value but may need to indicate that they have “consumed” or processed a certain number of characters from within a string, such as when the string will be further processed in a subsequent call.
The Integer
class is one of Java’s predefined
Number
subclasses, mentioned in the Introduction
to Chapter 5. It serves as a wrapper for an
int
value, and also has
static
methods for parsing and formatting
integers.
It’s fine as it is, but you may want something simpler.
Here is a class I wrote, called
MutableInteger
, that is like an
Integer
but specialized by omitting the overhead
of Number
and providing only the
set
, get
, and
incr
operations, the latter overloaded to provide
a no-argument version that performs the
increment (++
)
operator on its value, and also a one-integer version that adds that
increment into the value (analogous to the +=
operator). Since Java doesn’t support
operator overloading, the calling
class has to call these methods instead of invoking the operations
syntactically, as you would on an int
. For
applications that need this functionality, the advantages outweigh
this minor syntactic restriction. First let’s look at an
example of how it might be used. Assume you need to call a scanner
function called, say, parse( )
, and get back both
a boolean (indicating whether or not a value was found) and an
integer value indicating where it was found:
import com.darwinsys.util.*; /** Show use of MutableInteger to "pass back" a value in addition * to a function's return value. */ public class StringParse { /** This is the function that has a return value of true but * also "passes back" the offset into the String where a * value was found. Contrived example! */ public static boolean parse(String in, char lookFor, MutableInteger whereFound) { int i = in.indexOf(lookFor); if (i == -1) return false; // not found whereFound.setValue(i); // say where found return true; // say that it was found } public static void main(String[] args) { MutableInteger mi = new MutableInteger( ); String text = "Hello, World"; char c = 'W'; if (parse(text, c, mi)) { System.out.println("Character " + c + " found at offset " + mi + " in " + text); } else { System.out.println("Not found"); } } }
Now many OO purists will argue -- convincingly -- that you
shouldn’t do this. That you can always rewrite it so there is
only one return value. Either return and have the caller interpret a
single value (in this case, return the offset in the return
statement, and let the user know that -1 indicates not found), or
define a trivial wrapper class containing both the integer and the
boolean. However, there is precedent in the standard API: this code
is remarkably similar to how the
ParsePosition
class (see Section 6.6) is used. Anyway, this functionality is
requested often enough that I feel justified in showing how to do it,
accompanied by this disclaimer: try to avoid doing it this way in new
code!
Having said all that, here is the MutableInteger
class:
package com.darwinsys.util; /** A MutableInteger is like an Integer but mutable, to avoid the * excess object creation involved in * c = new Integer(c.getInt( )+1) * which can get expensive if done a lot. * Not subclassed from Integer, since Integer is final (for performance :-)) */ public class MutableInteger { private int value = 0; public MutableInteger( ) { } public MutableInteger(int i) { value = i; } public void incr( ) { value++; } public void decr( ) { value--; } public void setValue(int i) { value = i; } public int getValue( ) { return value; } public String toString( ) { return Integer.toString(value); } public static String toString(int val) { return Integer.toString(val); } public static int parseInt(String str) { return Integer.parseInt(str); } }
As mentioned, this use of MutableInteger
could be
replaced with ParsePosition
. However,
MutableInteger
has other uses; it makes
a fine in-memory
counter in a servlet (see Section 18.1).
52.15.78.83