谜题20:我的类是什么
来看一个打印其类文件名称的程序:
package com.javapuzzlers; public class Me{ public static void main(String[] args){ System.out.println(Me.class.getName().replaceAll(".","/") + ".class"); } }
这个程序是先获得它的类名("com.javapuzzlers.Me"),然后用"/"替换所有出现的字符串".",并在末尾追加字符串".class"。说到这里,你会认为这个程序将打印"com/javapuzzlers/Me.class",但是当你运行程序后,就会发现,实际上打印的是"///////////////////.class",那这到底是怎么回事呢?
问题在于String.replaceAll接受了一个正则表达式作为它的第一个参数,而并非接受了一个字符序列字面常量。正则表达式中的"."可以匹配任何单个的字符,因此,类名中的每一个字符都被替换成了一个斜杠,所以会打印出上述的输出。
那么怎么来只匹配句点符号呢?之前谜题中就提到了转义字符序列,那么在正则表达式中的句点也是必须在其前面添加一个反斜杠进行转义。又因为反斜杠字符在字面含义的字符串中具有特殊的含义,它标识转义字符序列的开始,因此反斜杠自身必须用另外一个反斜杠来转义,这样就产生了一个转义字符序列,它可以在字面含义的字符串中生成一个反斜杠,修正后的程序如下:
package com.javapuzzlers; public class Me{ public static void main(String[] args){ System.out.println(Me.class.getName().replaceAll("\\.","/") + ".class"); } }
为了解决这类问题,5.0版本提供了新的静态方法java.util.regex.Pattern.quote。它接受一个字符串作为参数,并可以添加必须的转义字符,返回一个正则表达式字符串,该字符串将精确匹配输入的字符串。下面是使用该方法之后的程序:
package com.javapuzzlers; public class Me{ public static void main(String[] args){ System.out.println(Me.class.getName().replaceAll(Pattern,quote("."),"/") + ".class"); } }
该程序的另外一个问题是:其正确的行为是与平台相关的,并不是所有的文件系统都使用斜杠符号来分隔层次结构的文件名组成部分。想获取一个正在运行的平台上的有效文件名,应该使用正确的平台相关的分隔符号来代替斜杠符号。
时间: 2024-10-09 22:28:40