Java反射

一、java的反射机制

反射的定义:
反射机制可以将一个类的实例化操作。 方法的调用,属性的调用等操作由编码期决定改为在运行期决定。
Reflection机制允许程序在正在执行的过程中,利用Reflection APIs取得任何已知名称的类的内部信息,包括:package、 type parameters、 superclass、 implemented interfaces、 inner classes、 outer classes、 fields、 constructors、 methods、 modifiers等,并可以在执行的过程中,动态生成instances、变更fields内容或唤起methods。
反射的作用:
大大的提高了代码的灵活性。
反射的利弊:
1: 适度使用反射机制可以提高代码复用及灵活性。
2: 由于反射会有额外的性能开销,所以过度使用会降低系统性能。 二、Class类
定义:
Class的每个实例称为类的类对象。它是反射机制中的最重要的一个类。
过程:
1加载:(三种)
当我们需要使用一个类时,首先JVM会加载该类的class文件,
注:
这时JVM就会实例化一个Class的实例,用来表示加载的这个类的信息。
由于JVM加载一个类只进行一次, 所以每个被JVM加载的类都有且只有唯一 的一个Class的实例用于表示它。
通过Class的实例可以获取其表示的类的一系列信息: 比如类的名字,有哪些 属性,哪些构造方法,哪些方法等。

(加载的三种方式)获取一个类的类对象的三种方法:

 		 方法一:每个类都有一个静态属性:class,可以直接返回其类对象,
            例如:想获取表示String类的类对象:
   		 Class cls = String.class;
	
  	    方法二:通过Class的静态方法forName加载该类并得到其类对象
		 Class cls = Class.forName("java.lang.String")  

 		方法三:还可以通过类加载器ClassLoader加载(更灵活)
 		//加载指定名称(包括包名)的二进制类型,供用户调用的接口
 		public Class<?> loadClass(String name);
 		//加载指定名称(包括包名)的二进制类型, 
 		protected synchronized Class<?> loadClass(String name, boolean resolve);
 		protected Class<?> findClass(String name)
 		//定义类型,一般在findClass方法中读取到对应字节码后调用,可以看出不可继承
 		说明:JVM已经实现了对应的具体功能,解析对应的字节码,产生对应的内部数据
 		结构放置到方法区,所以无需覆写,直接调用就可以了)
 		protected final Class<?> defineClass(String name, byte[] b, int off, int len)
 		 throws ClassFormatError{}

2实例化: Object obj = cls.newInstance();
其提供了一个方法newInstance可以调用其表示的类的无参构造方法将其实例化(必须 有无参构造方法,否则会抛出异常)
eg:
//1加载Person
Class cls = Class.forName(“reflect.Person”);
//2通过Class实例化其表示的类
Object obj = cls.newInstance();

               等价与
        Person p = new Person();

三、 通过反射调用方法

eg:利用反射机制调用sayHello方法
1 . 实例化
1.1 加载Person类
1.2. 通过Class实例化Person
2. 调用sayHello方法
2.1. 通过Class获取Person的sayHello方法(Method实例)
2.2. 通过Method调用其表示的方法

    //1  Person o = new Person();                          
	Class cls = Class.forName("reflect.Person");
	Object o = cls.newInstance();
	
	//2  o.sayHello();
	Method method = cls.getDeclaredMethod("sayHello");
	method.invoke(o, null);	
	* Method类
	* Method的每一个实例,用于表示一个类中的一个方法
	 * 通常通过Class获取,通过它可以得知其表示的方法更多的
	 * 详细信息:访问修饰符,返回值类型,参数,名字等。
	 * 并且可以通过invoke方法调用该方法。该方法要求传入
	 * 两个参数,第一个为当前方法所属对象,第二个为调用该
	 * 方法时需要传入的实参(如果有,没有则直接传入null)

四、 调用有参方法
1:Person p = new Person();
2:p.sayName(“小明”,22);

	//1获得Class类
	Class cls = Class.forName("reflect.Person");
	Object o = cls.newInstance();
	
	 * 2 获取sayName(String,int)
	 *  Class的getDeclaredMethod方法的第一个参数为方法名
	 *  第二个参数是一个Class数组,数组每个元素表示要获取的
	 *  方法中的一个参数类型。注意,参数类型在数组中的顺序
	 *  必须和该方法定义的参数顺序一致。
	 */
	Method method = cls.getDeclaredMethod("sayName", new Class[]{String.class,int.class}
	);
	/*
	 * invoke方法在执行时,第二个参数为Object数组,数组中
	 * 每个元素是调用该方法是传入的实际参数。
	 */
	method.invoke(o, new Object[]{"小明",22});

五、使用反射机制在类外面调用该类的获取构造方法

Class类提供了四个public方法,用于获取某个类的构造方法。

1. Constructor getConstructor(Class[] params)     
根据构造函数的参数,返回一个具体的具有public属性的构造函数

2. Constructor getConstructors()     
返回所有具有public属性的构造函数数组

3. Constructor getDeclaredConstructor(Class[] params)     
根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)

4. Constructor getDeclaredConstructors()    
返回该类中所有的构造函数数组(不分public和非public属性)

六、反射调用有参方法过程:
1:加载(有三种方法)

	静态属性:Class cls = String.class;
	静态方法: Class cls = Class.forName("java.lang.String") (常用:参数为类名)
	类加载器:ClassLoader

2:实例化

调用表示类的无参构造方法:Object o = cls.newInstance();

3:获取一个 Method实例

通过Class获取:(Method的每一个实例,用于表示一个类中的一个方法)
Method method = cls.getDeclaredMethod
	("sayName", new Class[]{String.class,int.class});
	第一个参数为方法名(无参方法只方法名)  
	第二个参数为Object数组,数组中每个元素是调用该方法是传入的实际参数。

4:通过invoke方法调用该方法

	  method.setAccessible();                										  			  			  
      method.invoke(o, new Object[]{"小明",22});
第一个为当前方法所属对象,
第二个为调用该方法时需要传入的实参(如果有,没有则直	接传入null)
       (//设置为true后就可以访问该私有方法		
		method.setAccessible(true);)

获取类的成员方法

1. Method getMethod(String name, Class[] params)    
  根据方法名和参数,返回一个具体的具有public属性的方法

2. Method[] getMethods()    
  返回所有具有public属性的方法数组

3. Method getDeclaredMethod(String name, Class[] params)    
  根据方法名和参数,返回一个具体的方法(不分public和非public属性)

4. Method[] getDeclaredMethods()    
  返回该类中的所有的方法数组(不分public和非public属性)

获取类的成员变量(成员属性)

存在四种获取成员属性的方法:

1. Field getField(String name)    
根据变量名,返回一个具体的具有public属性的成员变量

2. Field[] getFields()  
返回具有public属性的成员变量的数组

3. Field getDeclaredField(String name)  
根据变量名,返回一个成员变量(不分public和非public属性)

4. Field[] getDelcaredFields()    
返回所有成员变量组成的数组(不分public和非public属性)

使用反射机制在类外面调用该类的私有方法

 	   Class cls = Class.forName("reflect.Person");
 	   Object o = cls.newInstance();
	   //获取dosome方法
	   Method method = cls.getDeclaredMethod("dosome");
		//设置为true后就可以访问该私有方法
		method.setAccessible(true);
		method.invoke(o, null);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值