java解惑之字符之谜(谜题20)

谜题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

java解惑之字符之谜(谜题20)的相关文章

java解惑之字符之谜(谜题16)

谜题16:行打印程序 行分隔符是为分割文本行的字符或字符串而起的名字,并且在不同平台上它是存在差异的.在windows平台上,它由CR字符(回车)和紧随其后的LR(换行)字符组成.在UNIX平台上,通常引用单独的LF字符作为换行字符.那么,这次的谜题也就由行分隔符引出,来看看下面这个将LF字符传递给println方法的程序会打印什么,它的行为是否依赖于平台? public class LinePrinter{ public static void main(String[] args){ //N

java解惑之字符之谜(谜题21)

谜题21:我的类是什么?镜头2 下面的程序所要做的事情正是前一个谜题所做的事情,但是它没有假设斜杠符号就是分隔文件名组成部分的符号.相反,该程序使用的是java.io.File.separetor,它被指定为一个公共的String域,包含了平台相关的文件名分隔符.这个程序会打印正确的.平台相关的类文件名吗?该程序是从这个类文件中被加载的. package com.javapuzzlers; import java.io.File; public class MeToo{ public stati

java解惑之字符之谜(谜题18)

谜题18:字符串奶酪 下面这个程序从一个字节序列创建一个字符串,然后迭代遍历字符串中的字符,并将它们作为数字打印.请描述程序打印的数字序列: public class StringCheese{ public static void mian(String[] args){ byte bytes[] new byte[256]; for(int i = 0; i < 256; i++){ bytes[i] = (byte)i; } String str = new String(bytes);

java解惑之字符之谜(谜题22)

谜题22:URL的愚弄 本谜题利用了一个java编程语言中一个鲜为人知的特性.请考虑下面的程序将会做什么? public class BrowerTest{ public static void main(String[] args){ System.out.ptintln("iexplore"); http://www.google.com; System.out.println(":maximize"); } } 这是个有点诡异的问题.当我们初次看到这个程序时,

Java解惑七:更多类之谜

谜题66 继承的问题. 对于实例方法:命名相同时,子类会覆写父类的方法,且访问权限至少和父类一样大. 对于域:命名相同时,子类会隐藏父类的域,且访问权限任意. 谜题67 不要重用库中的类名. 谜题68 命名的问题. 类名应该以大写字母开头,形式为:MixedCase. 变量以小写字母开头,形式为:mixedCase. 常量以大写字母开头,形式为:MIXED_CASE. 单个大写字母,只能用于类型参数,形式为:Map<K, V>. 包名应该都是小写,形式为:lower.case. 当一个变量和一

Java解惑五:类之谜

本文是依据JAVA解惑这本书,做的笔记.电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题46 函数重载的问题. JAVA重载解析过程:1. 选取全部可用的方法或者构造器:2. 从过程1中选取的方法或构造器中选择最精确的. 一般而言:能够强制要求编译器选择一个精确的重载版本号,将实參转型为形參所声明的类型. 谜题47 继承中静态域的问题. 静态域由声明它的类及其全部子类共享. 假设须要让每个子类都具有某个域的单独拷贝,必须在每个子

Java解惑八:更多库之谜

本文是根据JAVA解惑这本书,做的笔记. 电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题76 将线程的启动方法start(),写成了run(); PS:管程(monitor)锁有待进一步理解. 谜题77 线程中锁的问题. 理解不深刻. 谜题78 反射会造成访问其他包中的非公共类型的成员,引起运行期异常. 谜题79 遮蔽:Thread.sleep()方法遮蔽了自定的方法. 谜题80 反射:如何实例化非静态内部类以及静态内部类.

Java解惑六:库之谜

本文是根据JAVA解惑这本书,做的笔记. 电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题56 BigInteger.BigDecimal以及包装类型的实例是不可改变. BigInteger five = new BigInteger("5"); BigInteger total = BigInteger.ZERO; total.add(five); //这并不会改变total的值,调用该方法的返回值,才是加法得到的结

Java解惑四:异常之谜

谜题36 finally语句中的return语句会覆盖掉try语句中的. 谜题37 该部分还需要进一步理解 一个方法可以抛出的被检查异常集合是它所适用的所有类型声明要抛出的被检查集合的交集. Java解惑四:异常之谜,布布扣,bubuko.com