反射和正则表达式
1:正则表达式
(1)概念:符合一定规则的字符串。
(2)规则字符:
A:字符
x:字符x,任意字符代表其本身。
\\:反斜线字符
\r: 回车
\n: 换行
B:字符类
[abc]a、b或c,任意字符一次。
[^abc]除了a、b、c以外的任何字符。
[a-zA-Z]a到z或A到Z,两端的字母也包括在内。
C:预定义字符类
.任意的字符
\d 数字:[0-9]
\w 单词字符:[a-zA-Z_0-9]
单词字符:英文,数字及_
D:边界匹配器
^:行的开头
$:行的结尾
\b:单词边界(就是说这里出现的不能是单词字符)
如:abc hello world?haha
E:Greedy 数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
F:组
捕获组可以通过从左到右计算其开括号来编号。组零始终代表整个表达式。
((A)(B(C)))
第一组:(A)(B(C))
第二组:A
第三组:B(C)
第四组:C
(3)常用功能:
正则表达式的判断功能:
public boolean matches(String regex)
看到这个方法,我们应该知道有一个字符串对象调用该方法,还应该有一个字符串规则。
切割功能:
public String[] split(String regex)
替换功能:
public String replaceAll(String regex,String replacement)
用给定的字符串去替换字符串对象中满足正则表达式的字符。
获取功能:
使用模式对象Pattern和匹配器对象Mathcher
Example:
(1)
/*
* 复杂的叠词切割: "sdqqfgkkkhjppppkl";
*
* 叠词:相同的字符重复的出现2次以上。
*
* 叠词的规则:
* (.)\\1+
*/
public class RegexDemo2 {
public static void main(String[] args) {
String str = "sdqqfgkkkhjppppkl";
String regex = "(.)\\1+";
//右边出现的应该是和左边是一模一样的。
String[] strArray = str.split(regex);
for (String s : strArray) {
// sd,fg,hj,kl
System.out.println(s);
}
}
}
(2)我要学编程
/*
* 我我....我...我.要...要要...要学....学学..学.编..编编.编.程.程.程..程
* 将字符串还原成:“我要学编程”。
*
* 思路:
* A:把点去掉
* B:叠词保留一个
*/
public class RegexTest {
public static void main(String[] args) {
String str = "我我....我...我.要...要要...要学....学学..学.编..编编.编.程.程.程..程";
// 替换
String result = str.replaceAll("\\.", "");
// System.out.println(result);
String finalResult = result.replaceAll("(.)\\1+", "$1");
System.out.println(finalResult);
}
}
(3)校验邮箱和电话号码
/*
* 校验邮箱:xxx@yyy.zzz
*
* liuyi@163.com
* linqingxia@126.com
* yangmi@qq.com
* liukaiwei@sina.com.cn
* shaoyifu@yahoo.cn
* hello@itcast.cn
*/
public class RegexTest {
public static void main(String[] args) {
// 定义规则
// String regex = "[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,8}(\\.[a-zA-Z_0-9]{2,3})+";
String regex = "\\w+@\\w{2,8}(\\.\\w{2,3})+";
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的邮箱:");
String email = sc.nextLine();
boolean flag = email.matches(regex);
System.out.println(flag);
}
}
2:反射
(1)概念:在运行状态下,通过class文件对象,去使用构造方法,成员变量,成员方法。
反射就是把Java类中的各种成分映射成相应的java类。例如,一个Java类中用一个Class类的对象来表示,
一个类中的组成部分:成员变量,方法,构造方法,包等等信息 也用一个个的Java类来表示,就像汽车是一
个类,汽车中的发动机,变速箱等等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方
法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field、Method、Contructor
、Package等等。
(2)获取class文件对象的方法
A:Object类的getClass()方法
B:数据类型的静态的class属性
C:Class类forName()静态方法
推荐:开发使用第三种。
到底使用哪一种呢?
开发中用第三种。自己写例子测试可以使用前两种。
因为第三种方式可以结合配置文件使用。
Example:
// 方式1
<span style="white-space:pre"> </span>Person p = new Person();
Class c = p.getClass();
Person p2 = new Person();
Class c2 = p2.getClass();
System.out.println(p == p2);// false
System.out.println(c == c2);// true
// 方式2
Class c3 = Person.class;
System.out.println(c == c3);// true
// 方式3
Class c4 = Class.forName("cn.itcast_01.Person");// true
System.out.println(c == c4);
(3)反射的应用
A:通过反射获取构造方法并使用
Class c = Class.forName("cn.itcast_01.Person");
// 所有公共构造方法
//public Constructor<?>[] getConstructors()
Constructor[] cons = c.getConstructors();
// 所有构造方法
// public Constructor<?>[] getDeclaredConstructors()
Constructor[] cons = c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
Constructor con = c.getConstructor();// 表示我使用的是无参数构造方法
// 通过构造器对象创建对象
// public T newInstance(Object... initargs)
Object obj = con.newInstance();
System.out.println(obj);
}
B:通过反射获取成员变量并使用
// 获取字节码文件对象
<span style="white-space:pre"> </span>// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// 赋值前
System.out.println(obj);
// 获取年龄并赋值
Field ageField = c.getField("age");
ageField.set(obj, 26);
// 获取姓名并赋值
// NoSuchFieldException
// Field nameField = c.getField("name");
Field nameField = c.getDeclaredField("name");
// IllegalAccessException
//public void setAccessible(boolean flag)
//暴力访问
nameField.setAccessible(true);//你就不要限制我了。
nameField.set(obj, "林青霞");
// 赋值后
System.out.println(obj);
C:通过反射获取成员方法并使用
// 获取字节码文件对象
Class c = Class.forName("cn.itcast_01.Person");
// 创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
// Method[] methods = c.getMethods();// 所有公共方法,包括父类的
// Method[] methods = c.getDeclaredMethods();// 本类的所有方法
// for (Method method : methods) {
// System.out.println(method);
// }
//第一种:无参数无返回值
Method m1 = c.getMethod("show", null);
m1.invoke(obj, null);
System.out.println("---------------");
//第二种:带参数无返回值
Method m2 = c.getMethod("function", String.class);
m2.invoke(obj, "林青霞");
System.out.println("---------------");
//第三种:带多个参数有返回值
Method m3 = c.getMethod("reutrnValue", String.class,int.class);
Object ooo = m3.invoke(obj, "林青霞",26);
System.out.println(ooo);
System.out.println("---------------");
//第四种:私有方法的调用
Method m4 = c.getDeclaredMethod("hello", null);
m4.setAccessible(true);
m4.invoke(obj, null);
案例:
import java.lang.reflect.Method;
import java.util.ArrayList;
/*
* 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
* 通过反射实现。
*
* 反射可以越过泛型检查。
*/
public class ArrayListTest {
public static void main(String[] args) throws Exception {
ArrayList<Integer> array = new ArrayList<Integer>();
// array.add(10);
// array.add("hello");
// 获取字节码文件对象
Class c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello");
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
}
}