java基础——反射

      反射就是把Java类中的各个成分映射成一个个java对象。
      一个类有成员变量、方法、构造函数等信息,利用反射可以对一个类进行解  剖,把各个组成部分映射成一个个对象。

反射也可以理解为动态调用写了一个.java文件,编译后为字节码文件,虚拟机加载了这个字节码文件也就是加载到内存中,就能执行一些指令。在这个类中 当我需要调用另外一个类的时候,而内存中并没有这个类,这时候我就可以使用反射动态加载这个类,使用其中的属性 跟方法。

 

反射获取class对象的三种方式

1)通过 Class 的 forName 的静态方法获得(参数:包名 + 类名):
 
 Class<?>  classType = Class.forName("java.lang.String");

2)通过类名 + 点 class 的方法获得:

     Class<?>  c = String.class;

3)通过类的对象的 getClass 的方法获得:

 String str = "heima";
 Class<?>  typeClass = str.getClass();


反射构造函数:
      //获取字节码文件
      Class clazz = Class.forName(对象的路径如:”cn.itcast.domain.Student”)
      //获取构造器
      Constructor con =clazz.getConstructor(String.class);//如果是空参的就写null
      //创建对象
      Object obj = con.newInstance(“liwen”);//如果是空参的就写null
反射方法:
      //获取字节码文件

      Classclazz = Class.forName(对象的路径如:”cn.itcast.domain.Student”)
      //创建一个对象
      Student stu =(student)clazz.newInstance();
      //获取方法
Method method = clazz.getMethod(方法名如“aa’“,参数类型如”String.calss”)
      //运行
      method.invoke(对象名如stu,参数如“liwen”)
反射字段:
      //获取字节码文件
      Class clazz = Class.forName(对象的路径如:”cn.itcast.domain.Student”)
      //创建对象
      Student stu =(Student)clazz.newInstance();
      //获取字段
      Field field = clazz.getField(字段名称如“name”);
      //设置字段的值
      field.set(对象名称如stu,参数如“liwen”)


注意:
      以上反射的都是非私有的,那么反射私有的怎么办呢?

总体步骤是不变的,只是在获取构造器。方法或字段是的方法变了,在获取后还要将其打开(暴力访问)
===================================================
获取私有构造器:
Constructor con =clazz.getDeclaredConstructor(String.class,int.class,String.class);
将其打开
con.setAccessible(true);//true是打开,false是关闭
===================================================获取私有方法
Method method = clazz.getDeclaredMethod("cc",String.class,int.class,String.class);
将其打开
method.setAccessible(true);
===================================================
获取私有字段
Field field = clazz.getDeclaredField("age");
将其打开
field.setAccessible(true);
===================================================

 

访问被private 修饰的方法和属性

package com.weaver.java;

public class Person
{
    private String name = "小四";
    
    private String getName()
    {
        return name;
    }
}

 

package com.weaver.java;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class PersonReflect {

    public static void main(String[] args)throws Exception
    {
        Class<?> classType = Class.forName("com.weaver.java.Person");
        Constructor con = classType.getDeclaredConstructor(new Class[]{});
        Object object =con.newInstance(new Object[]{});//new实例
        Field field = classType.getDeclaredField("name");

        field.setAccessible(true);//暴力访问

        field.set(object, "小小四");

        Method getNameMethod = classType.getDeclaredMethod("getName", new Class[]{});

        getNameMethod.setAccessible(true);

        Object  obj = getNameMethod.invoke(object, new Object[]{});
        System.out.println("通过反射修改后的值为:"+obj.toString());
    }
}


动态代理

 在java种怎样实现动态代理呢 
第一步,我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象,所谓代理呢也就是在调用实现类的方法时,可以在方法执行前后做额外的工作,这个就是代理。 
第二步,我们要自己写一个在要代理类的方法执行时,能够做额外工作的类,而这个类必须继承InvocationHandler接口,为什么要继承它呢?因为代理类的实例在调用实现类的方法的时候,不会调真正的实现类的这个方法, 而是转而调用这个类的invoke方法(继承时必须实现的方法),在这个方法中你可以调用真正的实现类的这个方法。 
第三步,在要用代理类的实例去调用实现类的方法的时候,写出下面的代码。

package com.weaver.java;

//去黑马学习的接口
public interface ToSchool {
	void study(); 
}
package com.weaver.java;


//去黑马学习的实现类
public class ToSchoolImp implements ToSchool{

	@Override
	public void study() {
		System.out.println("终于到黑马学习了");
		
	}

}
package com.weaver.java;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

//去黑马学习的代理类
//监听方法所在类,该类实现了InvocationHandler 接口,通过invoke方法利用java的反射机制实现对相关方法的监听
public class ToSchoolProxy implements InvocationHandler{

	private Object study = null;
	
	public ToSchoolProxy(Object obj) {
		
		this.study = obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("去黑马之前要自学");//去学习之前需要做的事情
		return method.invoke(study, args);
	}

}
package com.weaver.java;

import java.lang.reflect.Proxy;

public class ToSchoolMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		//先将实现类实例化,也就是得到ToSchool接口的一个实例对象   
		ToSchool school = new ToSchoolImp();
		//得到ToSchoolImp这个类的一个代理类,同时为代理类绑定了一个处理类ToSchoolProxy。  
		ToSchool toSchool = (ToSchool) Proxy.newProxyInstance(
				school.getClass().getClassLoader(), //要代理类的类加载器
				school.getClass().getInterfaces(), //代理类所实现的所有的接口  
				new ToSchoolProxy(school));
		
		toSchool.study();//调用方法
		
	}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值