反射详解

反射技术==>动态加载一个指定的类.获得该类的字节码文件对象-->获得该类中所有的内容.-->对类进行解剖

1.类的初始化:

    类的初始化:就是类的加载,将类从硬盘放到内存中.

    时机:什么时候使用到这个类,加载器就会将该类加载到内存中.

1. 创建类的实例

2. 类的静态变量,或者为静态变量赋值

3. 类的静态方法

4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

5. 初始化某个类的子类

6. 直接使用java.exe命令来运行某个主类

 

 

2.类的加载器: -->(原理:就是按照一定的格式将硬盘上的文件读入到内存中)

负责将.class文件加载到内在中,并为之生成对应的Class对象。

虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行

    Bootstrap ClassLoader 根类加载器.==>也叫引导类加载器

         加载核心类库...System,String...主要是\lib\rt.jar

    Extension ClassLoader 扩展类加载器==>

         扩展类加载器,目前只要加载src\lib\ext文件夹.

    System ClassLoader 系统类加载器

         主要是加载用户自定义的,或者用户导入的第三方jar.

3.如何获得Class文件对象,字节码文件对象.

    1.通过该类的对象,直接获得:

         Class clazz = obj.getClass(); ==>必须创建该类的对象.

    2.通过类中的静态方法或者静态的成员变量.静态的属性class.

    3.使用Class类中的方法.

         Class clazz = Class.forName(classname);

 

注意:第三种和前两种的区别前两种你必须明确Person类型.后面是指定这种类型的字符串就行.这种扩展更强.我不需要知道你的类.我只提供字符串,按照配置文件加载就可以了

 

4. 反射的使用步骤:    

    1.获得指定类的Class文件对象,(获得字节码文件对象)

    2.实例化对象,获得类的属性,方法或构造方法.

    3.访问属性,方法,调用构造方法创建对象.

5.反射的用法:

    1.获得Class文件的对象.

         ★★Class clazz = Class.forName(classname); 用于类加载.

                   classname需要全名..eg:com.mysql.jdbc.Driver  -->不可以带class后缀.

         Class clazz = Person.class             类名获取.

          Class clazz = p.getClass()         类对象直接获取.

        快速创建对象:

              1.类需要有空参构造

              2.该空参构造权限需要是public

                   Object obj =clazz.newInstance();

                   直接通过clazz文件对象创建对象,底层就是使用类的空参获得的实例.

     2.反射类的构造方法:

         Constructor con =clazz.getConstructor(Class<?>... params );//只能获得public修饰的.

              获得任意一个公有的指定参数列表的构造,如果不指定参数,获得的就是空参构造.

         Constructor con =clazz.getDeclareConstructor(Class<?>... params );//可以获得私有的构造

              获得任意一个(包括私有的)指定参数列表的构造,如果不指定参数,获得的就是空参构造.

         Constructor[] cons= clazz.getDeclareConstructors(Class<?>... params );//可以获得私有的构造

              获得该类中的所有的(包括私有的)构造方法.  

         通过对象的构造器,获得该类的实例对象:

              Object obj =con.newInstance(Object ... params); //参数传递,是根据使用的构造方法的参数列表来确定.

    3.反射类的属性.

         Field field = clazz.getField(String name);

              //获得指定名称的属性字段对象.只能是public修饰的

         Field[] fields = clazz.getDeclareFields();//无需名称.

              获得该类中以及父类或者接口中继承的所有字段,包括私有的.

         field.setAccessable(true);//取消访问权限.

         field.set(Object obj,Object value); //设置obj对象的该field字段的值为value.

     

    4.反射类的方法.

         Method[] methods = clazz.getDeclareMethods();

              //返获得该类中所有的方法,包括私有的.

              返回 Method 对象的一个数组,这些对象反映此Class 对象表示的类或接口声明的所有的方法,

              包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法.

         Method method = clazz.getDeclareMethod(Stringmethodname,Class<?>...params);

              获得一个指定名称的方法.参数为该方法的参数类型的class文件.

         method.setAccessable(true);

         method.invoke(Object obj,params);

              -->调用obj对象中的method方法.传入的参数为params.(需要和前面获得的方法的参数列表相同.)

          

 

反射的应用:

    1.泛型擦除.

    定义泛型限制的集合,向其中存入非泛型限定的数据类型.

     

 * 分析:

 * 1.要想在一个指定泛型(Integer类型)list集合中存入一个String类型的对象,就需要使用到反射技术.

 * 2.考虑到list添加元素的方法是add.因此,准备使用add方法进行反射添加.

     ArrayList<Integer> list= new ArrayList<Integer>();

     //第一步,获得该对象的字节码文件.

    Class c = list.getClass();

    //第一个参数,是方法名.第二个参数是参数类型的字节码文件.

    Method method = c.getDeclaredMethod("add" ,Object.class );//获得该类的add方法

    method.setAccessible( true); //取消访问限制

     method.invoke(list, "我是字符串,就要加进来,气死你!");





使用代码进行测试:

/**
 * 自定义一个测试类
 * @author myth
 *
 */
public class User {
	//私有属性.
	private String name;
	private String sex;
	//一个方法
	public void  say(String exten) {
		System.out.println("你好:"+name+"附加字符为  :"+exten);
	}
	//构造默认为无参的.
	public User(){} //可以不声明的.
}


用于测试用的类


反射的代码:

/**
 * 这个测试,是为了说明,有了反射,有了对应类的全路径.
 * 我们可以获得该对象的所有的字段,方法.以及构造.(包括私有的.)
 * 并且,我们可以暴力反射,即使该类没有指定对应的get/set方法,我们也可以去设置值.
 * @author myth
 *
 */
public class ProxyTest {

	@Test
	public void test() throws Exception {
		//获得该类的字节码文件对象.
		Class clazz = Class.forName("com.myth.proxy.User");
		//通过该类的空参构造一个对象.没有空参,这个方法就会报错.
		User user = (User) clazz.newInstance();
		//获得所有的属性字段.包括私有的.
		Field[] declaredFields = clazz.getDeclaredFields();
		//遍历所有字段.
		for (Field field : declaredFields) {
			//因为想对name字段赋值.所以对字段进行判断.
			if ("name".equals(field.getName())) {
				//暴力反射,否则无法设置参数.因为该字段声明是私有的.
				field.setAccessible(true); 
				field.set(user, "二哈"); //设置对应字段的值.
				//该语句类似于 user.setName("二哈");但是我们并没有提供get/set方法的.
			}
		}
		
		//获得对应方法名称的方法.(方法也是一个Method类的对象.)
		//通过匹配方法名,得到一个唯一方法对象.
		Method method = clazz.getDeclaredMethod("say",String.class);
		//System.out.println(method);//public void com.myth.proxy.User.say(java.lang.String)
		//System.out.println(method.getName()); //say
		method.invoke(user, "哈哈");
	}
}




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值