Java反射(二)

创建类的对象:

  • 调用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);

}

调用类的内容

  1. 通过Class类的getMethod(String name,Class...parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型
  2. 之后使用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的方法。

动态代理步骤

  1. 创建一个实现接口InvocationHandler的类,它必须实现invoke方法以完成代理的具体操作。
  2. 创建被代理的类以及接口
  3. 通过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");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值