1.自定义类实现“克隆”的步骤
1. 自定义类实现Cloneable接口。这是一个标记性的接口,实现该接口的对象可以实现“自我克隆”,接口里没有定义任何方法
2. 自定义类实现自己的clone()方法
3. 实现clone()方法时通过super.clone();调用Object实现的clone()方法来得到该对象的副本,并返回该副本
例:
package com.test.clone;
public class Address {
String detail;
public Address(String detail) {
this.detail = detail;
}
}
package com.test.clone;
public class User implements Cloneable {
int age;
Address address;
public User(int age) {
this.age = age;
address = new Address("广州天河");
}
public User clone() throws CloneNotSupportedException {
return (User)super.clone();
}
}
package com.test.clone;
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
User user = new User(28);
User user2 = user.clone();
System.out.println("(user == user2) ? " + (user == user2));
System.out.println("(user.address == user2.address) ? "
+ (user.address == user2.address));
}
}
执行结果为:
(user == user2) ? false
(user.address == user2.address) ? true
注意:Object类提供的Clone机制只对对象里各实例变量进行“简单赋值”,如果实例变量的类型是引用类型,Object的Clone机制也只是简单的赋值这个引用变量,这样原有对象的引用类型的实例变量与克隆对象的引用类型的实例变量依然指向内存中的同一个实例。
String、StringBuffer和StringBuilder类
String类时不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。
StringBuffer对象则代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。
StringBuilder也代表字符串对象,实际上,StringBuilder和StringBuilder基本相似,两个类的构造器和方法也基本相同。不同的是,StringBuffer时线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。因此在通常情况下,如果需要创建一个内容可变的字符串对象,则应该优先考虑使用StringBuilder类。
正则表达式
正则表达式中的特殊字符
特殊字符 说明
$ 匹配一行的结尾。要匹配$字符本身,请使用\$
^ 匹配一行的开头。要匹配^字符本身,请使用\^
() 标记子表达式的开始和结尾位置。要匹配这些字符,请使用\(和\)
[] 用于确定中括号表达式的开始和结束位置。要匹配这些字符,请使用\[和\]
{} 用于标记前面字表达式的出现频度。要匹配这些字符,请使用\{和\}
* 指定前面子表达是可以出现零次或多次。要匹配*字符本身,请使用\*
+ 指定前面子表达式可以出现一次或多次。要匹配+字符本身,请使用\+
? 指定前面子表达式可以出现零次或一次。要匹配?字符本身,请使用\?
. 匹配除换行符\n之外的任何单字符。要匹配.字符本身,请使用\.
\ 用于转义下一个字符,或指定八进制、十六进制字符。要匹配\字符本身,请使用\\
| 指定两项之间任选一项。要匹配|字符本身,请使用\|
正则表达式中的“通配符”,即预定义字符
预定义字符 说明
. 可以匹配任何字符
\d 匹配0~9的所有数字
\D 匹配非数字
\s 匹配所有的空白字符,包括空格、制表符、回车符、换页符、换行符等
\S 匹配所有的非空白字符
\w 匹配所有的单词字符,包括0~9所有数字、26个英文字母和下划线(_)
\W 匹配所有的非单词字符
备注:d是digit,s是space,w是word。
在一些特殊情况下,例如,若指向匹配a~f的字母,或者匹配除了ab之外的所有小写字母,或者匹配中文字符,上面这些预定义字符就无能为力了,此时就需要使用方括号表达式,方括号表达式有如下所示的几种形式。
方括号表达式
方括号表达式 说明
表示枚举 例如[abc],表示a、b、c其中任意一个字符;[gz],表示g、z其中任意一个字符
表示范围:- 例如[a-f],表示a~f范围内的任意字符;[\\u0041-\\u0056],表示十六进制字符\u0041到\u0056范围的字
符。范围可以合枚举结合使用,如[a-cx-z],表示a~c、x~z范围内的任意字符
表示求否:^ 例如[^abc],表示非a、b、c的任意字符;[^a-f],表示不是a~f范围内的任意字符
表示“与”运算:&& 例如[a-z&&[def]],求a~z和[def]的交集,表示d、e或f;
[a-z&&[^bc]],a~z范围内的所有字符,除了b和c之外,即[ad-z];
[a-z&&[^m-p]],a~z范围内的所有字符,除了m~p范围之外的字符,即[a-lq-z]
表示“并”运算 并运算与前面的枚举类似。例如[a-d[m-p]],表示[a-dm-p]
正则表达式还支持如下所示的边界匹配符
边界匹配符 说明
^ 行的开头
$ 行的结尾
\b 单词的边界
\B 非单词的边界
\A 输入的开头
\G 前一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符
\z 输入的结尾
使用正则表达式
一旦在程序中定义了正则表达式,就可以使用Pattern和Matcher来使用正则表达式。
Pattern对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译为Pattern对象,然后再利用该Pattern对象创建对应的Matcher对象。执行匹配所涉及的状态保留在Matcher对象中,多个Matcher对象可共享同一个Pattern对象。
因此,典型的调用顺序如下:
Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaaab");
boolean b = matcher.matches(); //返回true
注:Pattern是不可变类,可供多个并发线程安全使用。