java第23到25天----正则表达式,反射
文章目录
知识总结
- 1.转换流的编码
- 2.流的编码
- 3.网络通信的三要素
- 4.TCP
- 5.UDP
正则表达式
1.匹配
- 使用的是String类中的boolean matches(String regex)方法
- 实例一:匹配手机号,
- 要求
- 1.全部是数字
- 2.是11位
- 3.第二位不能是1,2,6,9,0
- 4.第一位只能是1
public static void piPei() throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String qq = bufferedReader.readLine();
String regex = "1[34578]\\d{9}";
System.out.println(qq.matches(regex));
bufferedReader.close();
实例二:可以在b和k之间有零个或多个o
// X? X,一次或一次也没有
// X* X,零次或多次
// X+ X,一次或多次
// X{n} X,恰好 n 次
// X{n,} X,至少 n 次
public static void piPei() throws IOException {
String s = "boooooooooooooook";
String regex = "bo*k";
System.out.println(s.matches(regex));
}
2.切割
- 使用的是String类中的 String[] split(String regex)方法
- 依据正则表达式的字符串来切割
public static void qieGe() {
// String string = "dhkjar djkhser,as leir uyf,aseliru";
// String regex = ",";
//实例要求按照空格切割
// String string = "dhkjar djkhser,as leir uyf,aseliru";
// String regex = " +";
//实例:
String string = "dhkjar.djkhser.as.leir.uyf.aseliru";
String regex = "\\.";//.代表任意字符
String[] strs = string.split(regex);
for (String string2 : strs) {
System.out.println(string2);
}
}
3.替换
- 使用的是String类中的 String replaceAll(String regex, String replacement)
- 把字符串中符合正则表达式的内容替换成第二个参数的内容
public static void tiHuan() {
// 实例:将连续超过三个数字的部分替换成*******
String string = "helloworld1d333333goodboy3644747bingbing7697823456chenchen54646564zhangsan888888list";
String regex = "\\d{4,}";
String str = string.replaceAll(regex, "*");
System.out.println(str);
}
4.获取
public static void huoQu() {
// 获取连续超过四个字母的字符串
String string = "hellow orld1d333333goodboy3644 747bingbing7697823456ch enchen546 46564zhangsan8 88888list";
String regex = "[a-zA-Z]{4,}";
// 将正则表达式进行了简单的转化,但是Pattern本身没有获取数据的能力
Pattern pattern =Pattern.compile(regex);
// 有获取数据的能力
Matcher matcher = pattern.matcher(string);
//matcher.find();//判断是否有符合要求的内容
//matcher.group();//获取数据
while (matcher.find()) {
System.out.println(matcher.group());
}
}
反射
- 反射:动态的获取类的字节码文件对象,对其成员进行抽象
- 想做的:就是通过字节码文件对象,直接创建普通的对象
- 1.获取字节码文件对象
- 2.获取对象
- a. 通过字节码文件对象,获取具体的实例对象
- b. 获取具体的构造方法(通过从构造方法中抽象出来的类Constructor)
- 3.获取具体的属性,并给属性赋值(通过从属性中抽象出来的类Field实现)
- 4.获取具体的方法,并调用方法(通过从方法中抽象出来的类Method实现)
后面用到的Person类代码
public class Person {
private String name;
@Override
public String toString() {
return "Person [name=" + name + "]";
}
public Person(String name) {
super();
this.name = name;
}
public Person() {
super();
// TODO Auto-generated constructor stub
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//非静态无参
public void play() {
System.out.println("play");
}
//非静态有参
public void run(String number) {
System.out.println("run"+number);
}
//静态有参
public static void show(String number,int age) {
System.out.println("show"+number+age);
}
}
1.获取字节码文件对象
- a:通过Object提供的getClass方法得到字节码文件对象
- 缺点,首先要有一个对象
public static void fun1() {
Person person = new Person();
Class class1 = person.getClass();
System.out.println(class1);
Person person2 = new Person();
Class class2 = person.getClass();
System.out.println(class1.equals(class2));
}
- b:每种数据类型都有一个class属性,通过它也可以获取当前类的字节码文件
- 缺点:首先要知道这个类的名字
public static void fun2() {
Class class1 = Person.class;
System.out.println(class1);
}
- c:Class提供的方法forName(字符串) 字符串的构成:包名+类名
- 优点:只需提供一个当前类的字符串形式
public static void fun3() throws ClassNotFoundException {
Class class1 = Class.forName("com.qianfeng.test.Person");
System.out.println(class1);
}
- 注意:字符串表示的类,在工作的时候,必须保证对应一个真正的类,否则报异常:ClassNotFoundException
2.获取对象
- 通过普通方式
Person person = new Person("bingbing");
- 通过反射
- 1.无参的构造方法
public static void fun1(Class class1) throws InstantiationException, IllegalAccessException{
//创建实例对象
//相当于在newInstance方法的内部调用了无参的构造方法
Object person = class1.newInstance();
//向下转型
Person person2 = (Person)person;
person2.setName("bingbing");
System.out.println(person2.getName());
}
- 通过反射
- 2.有参的构造方法
public static void fun2(Class class1) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//这里的参数是实际的构造方法的参数的字节码文件
Constructor constructor = class1.getConstructor(String.class);
Object person = constructor.newInstance("bingbing");//给定的实际参数
System.out.println(person);
}
3.获取具体的属性,并给属性赋值
- 通过普通的方式
public static void main(String[] args) {
// 通过普通的方式
// Person person = new Person();
// person.setName("bingbing");
// System.out.println(person.name);
- 通过反射
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException,
InstantiationException, IllegalAccessException {
//1.获取字节码文件
Class class1 = Class.forName("com.qianfeng.test.Person");
//2.调出Field的方法得到对应的属性
//参数就是那个实际的属性
//注意:getField方法在获取属性的时候,必须保证属性存在,还要保证权限够大--public
// Field field1 = class1.getField("name");
//当属性是私有的,可以通过下面的设置,临时更改属性的权限,完成属性的获取
Field field1 = class1.getDeclaredField("name");
field1.setAccessible(true);
// 3.给当前的属性指定一个具体的实例对象
Person person1 = (Person)class1.newInstance();
System.out.println(person1);
//4.将filed1指定给person1
//第一个参数是field对应的具体的实例对象 第二个参数是赋的具体的值
field1.set(person1, "bingbing");
System.out.println(field1.get(person1));
System.out.println(person1.getName());
//3.给当前的属性指定一个具体的实例对象
Object person2 = class1.newInstance();
//4.将filed1指定给person2
//第一个参数是field对应的具体的实例对象 第二个参数是赋的具体的值
field1.set(person2, "chenchen");
System.out.println(field1.get(person2));
}
4.获取具体的方法,并调用方法
- 调用普通的方法
Person person = new Person();
person.run("123");
- 使用反射
调用非静态的无参方法
public static void fun1(Class class1) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//第一个参数:对应的方法的具体名字 第二个参数:具体方法参数的字节码文件对象
Method method = class1.getMethod("play");
//创建实例对象
Constructor constructor = class1.getConstructor(String.class);
Object person = constructor.newInstance("bingbing");
//调用方法
//第一个参数:给当前方法指定的具体对象 第二个参数:方法的具体参数
method.invoke(person);
}
调用非静态的有参方法
public static void fun2(Class class1) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//第一个参数:对应的方法的具体名字 第二个参数:具体方法参数的字节码文件对象
Method method = class1.getMethod("run",String.class);
//创建实例对象
Constructor constructor = class1.getConstructor(String.class);
Object person = constructor.newInstance("bingbing");
//调用方法
//第一个参数:给当前方法指定的具体对象 第二个参数:方法的具体参数
method.invoke(person,"123");
}
调用静态的有参方法
public static void fun3(Class class1) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//第一个参数:对应的方法的具体名字 第二个参数:具体方法参数的字节码文件对象
//注意:所有数据类型都有自己的字节码文件对象.
Method method = class1.getMethod("show",String.class,int.class);
//调用方法
//第一个参数:给当前方法指定的具体对象 第二个参数:方法的具体参数
method.invoke(null, "苹果",222);
}
代理
- 作用:根据OCP(对扩展开发,对修改关闭)的原则,在不改变原来类的基础上,给这个类增加额外的功能
静态代理
- 作用:可以实现代理
- 缺点:代理对象要保证跟目标对象实现同样的接口,在维护的时候两个对象都要维护,而且代理对象实现的接口是死的,这是如果要给想实现不同功能的多个目标添加代理对象的话,要添加很多个类
public class Test {
public static void main(String[] args) {
Bingbing bingbing = new Bingbing();
//bingbing.findHouse();
Chenchen chenchen = new Chenchen();
//chenchen.findHouse();
Agent agent = new Agent(bingbing);
agent.findHouse();
}
}
interface TestInter {
public void findHouse();
}
class Bingbing implements TestInter {
@Override
public void findHouse() {
System.out.println("冰冰到西三旗找房");
}
}
class Chenchen implements TestInter {
@Override
public void findHouse() {
System.out.println("晨晨到宝盛里找房");
}
}
//代理类
public class Agent implements TestInter{
private TestInter persom;
public Agent(TestInter persom) {
super();
this.persom = persom;
}
@Override
public void findHouse() {
// TODO Auto-generated method stub
System.out.println("扣一半房租作为中介费");
this.persom.findHouse();
System.out.println("哈哈大笑");
}
}
动态代理
- 动态代理
*要实现InvocationHandler接口 - 调用动态代理的方法实现功能
- 动态生成代理对象的方法–通过JDK内置的java.lang.reflect.Proxy动态代理类完成代理对象的创建
- 参数一:这里代表类加载器,代理类的类加载器要与目标类的类加载器一致,类加载器用来装载内存中的字节码文件
- 参数二:代理类的与目标类实现的接口必须相同,既指定给代理类的接口,目标类必须实现了
- 参数三:代理类的构造方法生成的对象–主意:指定给构造方法的参数要使用Object
下面要用到的类
interface TestInter {
public void findHouse();
}
class Bingbing implements TestInter {
@Override
public void findHouse() {
System.out.println("冰冰到宝盛里找房");
}
}
通过新写一个具体类的方式完成动态代理
public class Test {
public static void main(String[] args) {
TestInter bingbing = new Bingbing();
TestInter agent = (TestInter)Proxy.newProxyInstance(bingbing.getclass.getClassLoader(),new Class[] {TestInter.class},new Agent(bingbing));
//代理对象调动方法的时候,invoke方法会自动被调用
agent.findHouse();
}
}
public class Agent implements InvocationHandler{
private Object person;
public Agent(Object person) {
super();
this.person = person;
}
@Override
/**
* 接口中的方法
* 主要:这个方法在调用接口方法的时候,会自动调动
* 参数一:代理对象的引用
* 参数二:目标对象的方法
* 参数三:目标对象的参数
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
System.out.println("扣一半房租作为中介费");
//通过反射的方法调用具体的对象的方法
Object object = method.invoke(person, args);
System.out.println("哈哈大笑");
return object;
}
}
通过匿名内部类的方式完成动态代理
public class Test {
public static void main(String[] args) {
TestInter bingbing = new Bingbing();
TestInter agent = (TestInter)Proxy.newProxyInstance(bingbing.getClass().getClassLoader(), new Class[] {TestInter.class},new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("扣一半房租做中介费");
// TODO Auto-generated method stub
//通过反射的方法调用具体对象的方法
Object object = method.invoke(bingbing, args);
System.out.println("哈哈大笑");
return object;
}
});
agent.findHouse();
}
}