创建类的对象:
- 调用Class对象的newlnstance()
- 类必须有一个无参数的构造器,否则就需要传入构造器对应的参数
- 类的构造器的访问权限需要足够,通常设置为public
public void test1() throws IllegalAccessException, InstantiationException {
//方式一:默认调用无参构造器
Class<Person> clazz = Person.class;
Person obj = clazz.newInstance();
System.out.println(obj);
//方式二:调用有参构造器
//1.根据全类名获取对应的Class对象
String name ="com.Person";
Class clazz=null;clazz=Class.forName(name);
//2.调用指定参数结构的构造器,生成Constructor的实例
Constructor con=clazz.getConstructor(String.class,Integer.class);
//3.通过Constructor的实例创建对应类的对象,并初始化类属性
Person p2=(Person)con.newlnstance("Peter",20);
System.out.println(p2);
}
调用类的内容
- 通过Class类的getMethod(String name,Class...parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型
- 之后使用Object invoke(Object obj,Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息
public void test() throws Exception{
Class clazz = Person.class;
//1.通过反射,创建Person类的对象
Constructor cons = clazz.getConstructor(String.class,int.class);
Object obj = cons.newInstance("Tom", 12);
Person p = (Person) obj;
System.out.println(p.toString());
//2.通过反射,调用对象指定的属性、方法
//调用属性
Field age = clazz.getDeclaredField("age");
age.set(p,10);
System.out.println(p.toString());
//调用方法
Method show = clazz.getDeclaredMethod("show");
show.invoke(p);
System.out.println("*******************************");
//通过反射,可以调用Person类的私有结构的。比如:私有的构造器、方法、属性
//调用私有的构造器
Constructor cons1 = clazz.getDeclaredConstructor(String.class);
cons1.setAccessible(true);
Person p1 = (Person) cons1.newInstance("Jerry");
System.out.println(p1);
//调用私有的属性
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p1,"HanMeimei");
System.out.println(p1);
//调用私有的方法
Method showNation = clazz.getDeclaredMethod("showNation", String.class);
showNation.setAccessible(true);
//相当于String nation = p1.showNation("中国")
String nation = (String) showNation.invoke(p1,"中国");
System.out.println(nation);
}
Object invoke(Object obj, Object..… args)
- Object对应原方法的返回值,若原方法无返回值,此时返回null
- 若原方法若为静态方法,此时形参Object obj可为null
- 若原方法形参列表为空,则Object[] args为null
- 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。
动态代理步骤
- 创建一个实现接口InvocationHandler的类,它必须实现invoke方法以完成代理的具体操作。
- 创建被代理的类以及接口
- 通过Proxy的静态方法newProxylnstance()创建一个接口代理调用实现类方法
class MyInvocationHandler implements InvocationHandler{
//需要使用被代理类的对象进行赋值
private Object obj;
public void bind(Object obj){
this.obj = obj;
}
//当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
//将被代理类要执行的方法a的功能就声明在invoke()中
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
//obj:被代理类的对象
Object returnValue = method.invoke(obj,args);
//上述方法的返回值就作为当前类中的invoke()的返回值。
return returnValue;
}
}
class ProxyFactory{
//调用此方法,返回一个代理类的对象。解决问题一
//obj:被代理类的对象
public static Object getProxyInstance(Object obj){
MyInvocationHandler handler = new MyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
handler
);
}
}
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//proxyInstance:代理类的对象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
String belief = proxyInstance.getBelief();
System.out.println(belief);
proxyInstance.eat("food");
}
}