〇、写在前面 碎碎念
终于要把基础的课程给结束了,其实早该结束了。给自己加个油。It will get better.
2019.3.20
为了丁丁女朋友加油吧!
2019.3.21
一、反射的概述
1. 获取Class文件对象的三种方式
Class<?> clazz = Class.forName("全类名"); //用于读取配置文件
Class<?> clazz = Person.class; //当作静态方法的同步锁对象
Class<?> clazz = p.getClass(); //判断是否是同一个字节码对象(HashCode()方法中使用到)
2.用Class对象来创建实例
Class clazz = Class.forName(lassName);
Person p = (Person)clazz.newInstance();
3.通过反射获取xxx
(1) 构造方法getConstructor[s] (Class … [parameterTypes);
Constructor<?> con = clazz.getConstructor(String.class,int.class);
Constructor 中的方法
public T newInstance(Object args) throws manyException; //通过构造方法来获取创建实例对象
(2) 成员变量getField[s] (“name”);
Field[] f = clazz.getFields();
(3) 成员方法getMethod[s] (String name, Class … parameterTypes)
Method me = clazz.getMethod("say",String.class);
Method 中的方法
public void invoke(Object o,Object ...parameterTypes); //执行有参方法
public void invoke(Object o); //执行无参方法
三、动态代理
概述
(用自己的话来说)通过反射的方法来调用了class对象,给class对象所映射的类的每一个方法都加上一些额外的功能。无论是Animal接口的子类还是Person接口的子类,通过动态代理的方法都能在每个方法中添加额外的代理功能代码.
使用到的类和接口:Proxy类和InvocationHandler接口
具体步骤
- 已有Person接口和实现了Person接口的子类PersonImp类;
- 创建一个MyInvocationHandler类实现了InvocationHandler接口;
- 在该类中创建一个Object target对象,并私有;
- 创建有参构造传入一个Object target对象;
- 在该类中重写了invoke方法,形参是Object proxy,Method method, Object[] args.我们只需关注method和args(类中调用方法的形参列表);
- 在invoke方法中调用method.invoke(target,args);在加上需要添加的代理功能代码;
- 在测试类中新建一个Person p = new PersonImp();
- 用Person接口来接受Proxy类中的静态方法(Person)newProxyInstance(ClassLoader c,Interface i,InvocationHandler h)的返回值
- 调用原来的方法会发现加上了代理的功能方法
代码实现
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("xxxxx代码");
method.invoke(target, args);
System.out.println("yyyyyy代码");
return null;
}
}
public static void main(String[] args) {
Person p = new PersonImps();
p.drink();
p.eat();
p.sleep();
System.out.println("-----------");
Person p1 = (Person) Proxy.newProxyInstance(p.getClass().getClassLoader(),
p.getClass().getInterfaces(), new MyInvocationHandler(p));
p1.drink();
p1.eat();
p1.sleep();
}
Result:
四、设计模式之 模板设计模式(Template)
概述
- 模版设计模式概述
- 模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现
- 优点和缺点
- 优点
- 使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求
- 缺点
- 如果算法骨架有修改的话,则需要修改抽象类
- 如果算法骨架有修改的话,则需要修改抽象类
- 优点
五、枚举(enum)
1. 概述
枚举相当于单例设计模式的衍生,相当于多例设计模式。
1/自定义的实现枚举的方法
使用单例设计模式的第三种创建方法,私有构造方法,将设置的实例用final修饰,在类中指定生成实例的个数。
2/使用enum关键字实现枚举类
2. 自定义实现枚举的方法
public abstract class Week2 {
private String name;
private Week2(String name) { //私有构造,不让其他类创建本类对象
this.name = name;
}
public String getName() { //对外提供公共的获取方法
return name;
}
public abstract void show(); //设置抽象方法
//使用匿名内部类的方式来创建抽象类的子类对象
public static final Week2 MON = new Week2("周一") {
@Override
public void show() {
System.out.println("周一惹");
}
};
public static final Week2 TUE = new Week2("周二") {
@Override
public void show() {
System.out.println("周二惹");
}
};
public static final Week2 WED = new Week2("周三") {
@Override
public void show() {
System.out.println("周三惹");
}
};
}
3. enum来实现枚举
public enum Week2 {
Mon("周一"){
@Override
public void show() {
System.out.println("你好周一");
}
},The("周二"){
@Override
public void show() {
System.out.println("你好周二");
}
},Wed("周三"){
@Override
public void show() {
System.out.println("你好周三");
}
};
String name;
private Week2(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void show();
}
4. enum的注意事项
- 定义枚举类要用关键字enum
- 所有枚举类都是Enum的子类
- 枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
- 枚举类可以有构造器,但必须是private的,它默认的也是private的。
- 枚举类也可以有抽象方法,但是枚举项必须重写该方法
- 枚举在switch语句中的使用
(1) 枚举在switch语句中的使用
Week2 mon = Week2.Mon;
switch (mon) {
case Mon:
System.out.println("周一好");
break;
case Tue:
System.out.println("周二好");
break;
case Wed:
System.out.println("周三好");
break;
}
5.枚举Method
int ordinary(); //返回枚举常量的序数
int compareTo(); //比较编号...,相当于做减法
String name(); //获取实例名称
String toString(); //未重写时=name()方法
T <T> values(); //返回枚举项数组