CHAPTER 15 ■ GENERICS AND REGULAR EXPRESSIONS
Finally, ensuring that your collections contain only the types you expect is one aspect of defensive
programming (another good practice every programmer should adopt). If you ensure that no other
programmer (including yourself at a later date) can pass bad values to your code, you ensure less trouble
for your users. It's a thankless task, as no one (except possibly your co-workers) will ever realize you did
it, but it's a good idea all the same. If you wish to think of it in more positive terms, think of it as ensuring
that the developers who use your code are more likely to write error-free code. One of my co-workers
(Matt Hinze, who also writes books about MVC when not coding) calls it “pushing our customers into a
pit of success.” However you phrase it, limiting the possibilities for errors to creep into the system is the
epitome of good software development practice.
Regular Expressions
If you've ever worked with files from the command line on your computer, you may very well have used
a regular expression without realizing it. For example, I recently wanted a list of all the HTML files in a
directory (on a Windows 7 system). In a command window, I typed dir .htm and got the list I wanted.
.htm is in fact a regular expression that means all the files with an extension of htm. Suppose I had
wanted all the HTML files with names that start with “s”. The command would have been dir s*.htm.
Regular expressions in Java work in much the same way, except that you can specify much more
complex patterns.
The Java regular expression package is java.util.regex. It contains the MatchResult interface, the
Matcher class (which implements the MatchResult interface), the Pattern class, and the
PatternSyntaxException class. You can't directly instantiate the Matcher and Pattern classes, as they
have no public constructors. In other words, new Matcher and new Pattern don't work. Instead, the
pattern for using them is to get a Pattern object by calling one of the compile methods within the Pattern
class. Then you get a Matcher object by calling the matcher method within the Pattern class. Finally, to
find the substrings that match your pattern, you call the find method within the Matcher class. Let's
create a class that will let us experiment with the Pattern and Matcher classes. Listing 15-11 shows one
possible implementation of such a class.
Listing 15-10. RegexTester Class
package com.bryantcs.examples;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexTester {
public static void main(String[] args) {
Pattern pattern = Pattern.compile(args[0]);
Matcher matcher = pattern.matcher(args[1]);
while(matcher.find()) {
String groupText = matcher.group();
int matchBegin = matcher.start();
int matchEnd = matcher.end();
StringBuilder sb = new StringBuilder("Found a match for ");
sb.append(groupText);
sb.append(" beginning at ");
sb.append(matchBegin);