This program was designed to print the name of its class file.
In case you aren't familiar with class literals, Me.class.getName()
returns the fully qualified name of the class Me, or
"com.javapuzzlers.Me". What does the program print?
package com.javapuzzlers; public class Me { public static void main(String[] args) { System.out.println( Me.class.getName().replaceAll(".", "/") + ".class"); } }
Solution 20: What's My Class?
The program appears to obtain its class
name ("com.javapuzzlers.Me"), replace all occurrences of the string
"." with "/", and append the string ".class". You
might think that the program would print com/javapuzzlers/Me.class,
which is the class file from which it was loaded. If you ran the program, you
found that it actually prints ///////////////////.class. What's going
on here? Are we a victim of the slasher?
The problem is that String.replaceAll takes a regular expression as its
first parameter, not a literal sequence of characters. (Regular
expressions were added to the Java platform in release 1.4.) The regular
expression "." matches any single character, and so every character of
the class name is replaced by a slash, producing the output we saw.
To match only the period character, the period in the regular
expression must be escaped by preceding it with a
backslash (\). Because the backslash character has special meaning in a
string literal—it begins an escape sequence—the backslash itself must be escaped
with a second backslash. This produces an escape sequence that generates a
backslash in the string literal. Putting it all together, the following program
prints com/javapuzzlers/Me.class as expected:
package com.javapuzzlers;
public class Me {
public static void main(String[] args) {
System.out.println(
Me.class.getName().replaceAll("\\.", "/") + ".class");
}
}
To solve this kind of problem, release 5.0 provides the new
static method java.util.regex.Pattern.quote. It takes a string as a
parameter and adds any necessary escapes, returning a regular expression string
that matches the input string exactly. Here is how the program
looks when modified to make use of this method:
package com.javapuzzlers;
import java.util.regex.Pattern;
public class Me {
public static void main(String[] args) {
System.out.println(Me.class.getName().
replaceAll(Pattern.quote("."), "/") + ".class");
}
}
Another problem with this program is that the correct behavior
is platform dependent. Not all file systems use the slash character to separate
hierarchical filename components. To get a valid filename for the platform on
which you are running, you should use the correct platform-dependent separator
character in place of the slash. That is exactly what the next puzzle does.
No comments:
Post a Comment
Your comments are welcome!